cvik1
cvik1

Reputation: 35

OpenCV error: bitwise_and throws error that mask and image are not same size

I am trying to apply a mask I have made to an image using openCV (3.3.1) in python (3.6.5) to extract all the skin. I am looping over a photo and checking windows and classifying them using two premade sklearm GMMs. If the window is skin I have changing that area of the mask to True (255) otherwise leaving it as 0.

I have initialized the numpy array to hold the mask before the loop to be the same dimensions as the image, but openCV keeps saying that the image and mask do not have the same dimensions (output and error message are below). I have seen other somewhat similar problems on the site but none with solutions that have worked for me.

Here is my code:

# convert the image to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
delta = 6
# create an empty np array to make the mask
#mask = np.zeros((img.shape[0], img.shape[1], 1))
mask = np.zeros(img.shape[:2])
# loop through image and classify each window
for i in range(0,hsv.shape[0],delta):
    for j in range(0,hsv.shape[1],delta):
        # get a copy of the window
        arr = np.copy(hsv[i:i+delta,j:j+delta,0])
        # create a normalized hue histogram for the window
        if arr.sum() > 0:
            arr = np.histogram(np.ravel(arr/arr.sum()), bins=100, range=(0,1))
        else:
            arr = np.histogram(np.ravel(arr), bins=100, range=(0,1))
        # take the histogram and reshape it
        arr = arr[0].reshape(1,-1)
        # get the probabilities that the window is skin or not skin
        skin = skin_gmm.predict_proba(arr)
        not_skin = background_gmm.predict_proba(arr)
        if skin > not_skin:
            # becasue the window is more likely skin than not skin
            # we fill that window of the mask with ones
            mask[i:i+delta,j:j+delta].fill(255)
# apply the mask to the original image to extract the skin
print(mask.shape)
print(img.shape)
masked_img = cv2.bitwise_and(img, img, mask = mask)

The output is:

(2816, 2112)
(2816, 2112, 3)
OpenCV Error: Assertion failed ((mtype == 0 || mtype == 1) && 
_mask.sameSize(*psrc1)) in cv::binary_op, file C:\ci\opencv_1512688052760
\work\modules\core\src\arithm.cpp, line 241
Traceback (most recent call last):
File "skindetector_hist.py", line 183, in <module>
main()
File "skindetector_hist.py", line 173, in main
skin = classifier_mask(img, skin_gmm, background_gmm)
File "skindetector_hist.py", line 63, in classifier_mask
masked_img = cv2.bitwise_and(img, img, mask = mask)
cv2.error: C:\ci\opencv_1512688052760\work\modules\core\src
\arithm.cpp:241: error: (-215) (mtype == 0 || mtype == 1) && 
_mask.sameSize(*psrc1) in function cv::binary_op

As you can see in the output, the image and mask have the same width and height. I have also tried making the mask have depth one (line 5) but that didn't help. Thank you for any help!

Upvotes: 1

Views: 6399

Answers (1)

api55
api55

Reputation: 11420

It is not only complaining about the size of the mask. It is complaining about the type of the mask. The error:

OpenCV Error: Assertion failed ((mtype == 0 || mtype == 1) && _mask.sameSize(*psrc1))

Means that either the type of the mask or the size (that in your case is equal) is not the same. In the documentation we see:

mask – optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.

And this is consistent with the error that asks for a type 0 (CV_8U) or 1 (CV_8S).

Also, even if it is not said, the img should not be float, since it will not give a desired result (probably it will do it anyways).

The solution is probably enough to change:

mask = np.zeros(img.shape[:2])

to

mask = np.zeros(img.shape[:2], dtype=np.uint8)

A small test shows what type you will get:

np.zeros((10,10)).dtype

gives you dtype('float64') which means doubles and not 8 bit

Upvotes: 2

Related Questions