Search code examples
pythonopencvimage-processingcomputer-visionfeature-extraction

Unknown C++ exception while drawing matches using cv2.line_descriptor.drawLineMatches() in OpenCV Python


I am trying to match line descriptors extracted from two images using the binary descriptor module of OpenCV in Python. But, when drawing the matches using cv2.line_descriptor.drawLineMatches() function, I am getting the below error

img3 = cv2.line_descriptor.drawLineMatches(img,keylines1,field,keylines2,matches[:10],None)

cv2.error: Unknown C++ exception from OpenCV code

What's wrong I am doing? Any suggestion would help. Thanks.

import cv2
import numpy as np 

#Read gray image
img = cv2.imread("8.jpg",0)
field = cv2.imread('field1.png',0)

lsd = cv2.line_descriptor.LSDDetector.createLSDDetector()


#Detect lines in the image
keylines1 = lsd.detect(img, scale=2, numOctaves=2)
keylines2 = lsd.detect(field, scale=2, numOctaves=2)


# # # compute descriptors for lines
bd = cv2.line_descriptor.BinaryDescriptor.createBinaryDescriptor()
k1,descr1 = bd.compute(img, keylines1)
k2,descr2 = bd.compute(field, keylines2)

bdm =  cv2.line_descriptor.BinaryDescriptorMatcher()

matches = bdm.match(descr1, descr2)

matches = sorted(matches, key = lambda x:x.distance)
#img3 = cv2.drawMatches(img,k1,field,k2,matches[10],None,1)

img3 = cv2.line_descriptor.drawLineMatches(img,keylines1,field,keylines2,matches[:10],None)

#Show image
cv2.imshow("LSD",img3 )
cv2.waitKey(0)

Solution

  • It looks like there is a bug in the Python to C++ binding in cv2.line_descriptor.drawLineMatches method.
    When adding the matchesMask argument, the method seems to work.

    Note that the code is working only with very specific versions of OpenCV.
    The LSDDetector was removed in OpenCV version 4 (it may be part of the reason that the bug is not fixed).

    The following example is working with opencv-contrib-python version 3.4.18.65:

    ...
    
    matches = sorted(matches, key = lambda x:x.distance)
    
    good_matches = np.ones(10, np.uint8)
    
    #Recommended to use colored images:
    #img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    #field = cv2.cvtColor(field, cv2.COLOR_GRAY2BGR)
    
    img3 = cv2.line_descriptor.drawLineMatches(img, keylines1, field, keylines2, matches[:10], None, matchColor=-1, singleLineColor=-1, matchesMask=good_matches)