Sending correct mask for grabcut in python

I am trying to send a mask for which the border pixel of the mask is 0 (sure background) and the rest of the pixels are at some gray level(say 120 as we do not know the sure foreground)

This is the function for finding the mask.

def maskImage(img):
    width = img.shape[1]
    height = img.shape[0]
    image = np.ones((height, width), dtype=np.uint8) * 120 #gray pixels
    # Set boundary pixels to black
    image[0, :] = 0  # Top boundary
    image[height - 1, :] = 0  # Bottom boundary
    image[:, 0] = 0  # Left boundary
    image[:, width - 1] = 0  # Right boundary
    _, image = cv2.threshold(image, 128,255,cv2.THRESH_BINARY)

Now , I want to call grabcut with this mask as initializer instead of rect.

def grabCut(img):
    imgcopy = img.copy()
    img = cv2.cvtColor(img,cv2.COLOR_RGBA2BGR)
    mask = np.zeros(img.shape[:2], np.uint8)
    m = maskImage(img)
    mask[m == 0] = 0
    bgdModel = np.zeros((1,65),np.float64)
    fgdModel = np.zeros((1,65),np.float64)
    rect = (0,0, img.shape[1]-1, img.shape[0]-1)
    mask = (0,0, mask.shape[1]-1, mask.shape[0]-1)
    mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
    mask2 = np.where((mask==2)|(mask==0),1,0).astype('uint8')
    img = img*mask2[:,:,np.newaxis]
    cv2.imwrite("grab.png", img)

With this I am getting this error:

cv2.error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/imgproc/src/grabcut.cpp:328: error: (-5:Bad argument) mask must have CV_8UC1 type in function ‘checkMask’

Need help fixing it.

this is an array of boolean, not uint8

how can I fix it? need some more inputs

I am following this tutorial https://docs.opencv.org/3.4/d8/d83/tutorial_py_grabcut.html

what is that supposed to be?

that’s not shown in the tutorial.

that’s not a mask. that’s a 4-tuple.

please think about the difference between a rectangle and a mask.

Thanks for pointing this .

Now I have modified my grabCut function:

def grabCut1(img):
    imgcopy = img.copy()
    img = cv2.cvtColor(img,cv2.COLOR_RGBA2BGR)
    mask = np.zeros((img.shape[0], img.shape[1]), np.uint8)
    m = maskImage(img)
    mask[m == 0] = 0
    print("mask shape ", mask.shape)
    bgdModel = np.zeros((1,65),np.float64)
    fgdModel = np.zeros((1,65),np.float64)
    mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
    mask2 = np.where((mask==2)|(mask==0),1,0).astype('uint8')
    img = img*mask2[:,:,np.newaxis]
    cv2.imwrite("graby.png", img)


But still getting this error related to bgdModel, fgdModel.

", line 167, in run_endpoint_function
return await dependant.call(**values)
File “./api.py”, line 37, in find_contour
contours = grabCut1(img)
File “./api.py”, line 67, in grabCut1
mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
cv2.error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/imgproc/src/grabcut.cpp:380: error: (-215:Assertion failed) !bgdSamples.empty() && !fgdSamples.empty() in function ‘initGMMs’

In fact it is not working with the example given in the opencv doc. I used the same image as mask just for sanity testing.

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
newmask = cv.imread('messi.jpg', cv.IMREAD_GRAYSCALE)
assert newmask is not None, "file could not be read, check with os.path.exists()"
# wherever it is marked white (sure foreground), change mask=1
# wherever it is marked black (sure background), change mask=0
mask[newmask == 0] = 0
mask[newmask == 255] = 1
_ = cv.grabCut(img,mask,None,bgdModel,fgdModel,5,cv.GC_INIT_WITH_MASK)
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()

Still getting:

Traceback (most recent call last):
File “mask.py”, line 15, in
_ = cv.grabCut(img,mask,None,bgdModel,fgdModel,5,cv.GC_INIT_WITH_MASK)
cv2.error: OpenCV(3.4.2) /opt/concourse/worker/volumes/live/9523d527-1b9e-48e0-7ed0-a36adde286f0/volume/opencv-suite_1535558719691/work/modules/imgproc/src/grabcut.cpp:380: error: (-215:Assertion failed) !bgdSamples.empty() && !fgdSamples.empty() in function ‘initGMMs’