10

I am building a simple project in Python3, using OpenCV3, trying to match jigsaw pieces to the "finished" jigsaw image. I have started my tests by using SIFT.

I can extract the contour of the jigsaw piece and crop the image but since most of the high frequencies reside, of course, around the piece (where the piece ends and the floor starts), I want to pass a mask to the SIFT detectAndCompute() method, thus forcing the algorithm to look for the keypoints only within the piece.

test_mask = np.ones(img1.shape, np.uint8)
kp1, des1 = sift.detectAndCompute(img1, mask = test_mask)

After passing a test mask (to make sure it's uint8), I get the following error:

kp1, des1 = sift.detectAndCompute(img1,mask = test_mask) cv2.error: /home/pyimagesearch/opencv_contrib/modules/xfeatures2d/src/sift.cpp:772: error: (-5) mask has incorrect type (!=CV_8UC1) in function detectAndCompute

From my research, uint8 is just an alias for CV_8U, which is the same as CV_8UC1. Couldn't find any code sample passing a mask to any feature detection algorithm in Python.

Michał Gacka
  • 2,935
  • 2
  • 29
  • 45
  • 1
    if `img1` is a color image, it has 3 channels, so your mask ends up being of type `CV_8UC3` because you use `img1.shape`, which is something like `[rows, cols, 3]`. You need to build a single channel mask. – Miki Feb 20 '17 at 14:12
  • I was also using a binary mask created in a different method and I assumed it was [rows, cols, 1] but thanks to your answer, I found out that somewhere along the way it got converted to 3-channel image. Thank you! And sorry for the trouble (still trying to figure out type control in Python). Is there a way I can accept your comment as an answer? – Michał Gacka Feb 20 '17 at 14:33
  • See [THIS ANSWER](http://stackoverflow.com/questions/22375430/opencv-display-only-the-keypoints-not-the-image-using-sift/42255816#42255816) . It might help. – Jeru Luke Feb 20 '17 at 14:43
  • Thanks @JeruLuke - not exactly what I was looking for but I did solve the issue thanks to Miki. Thank you both! – Michał Gacka Feb 21 '17 at 07:47

1 Answers1

6

Thanks to Miki I've managed to find a bug.

It turned out that my original mask that I created using threshold operations, even though looked binary, was a 3-channel image ([rows], [cols], 3). Thus it couldn't be accepted as a mask.

After checking for type and shape (has to be uint8 and [rows,cols,1]):

print(mask.dtype)
print(mask.shape)

Convert the mask to gray if it's still 3-channel:

mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Michał Gacka
  • 2,935
  • 2
  • 29
  • 45