I used the interactive grabcut.py from the OpenCV samples to segment an image and saved the foreground and background models. Then I used these models to segment more images of the same kind, as I don't want to retrain the model each time.
After running the grabcut algorithm, the mask is all zeros (all background) and therefore it doesn't segment anything.
from matplotlib import pyplot as plt
import numpy as np
import cv2
img = cv2.imread('usimg1.jpg')
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.load('bgdmodel.npy')
fgdModel = np.load('fgdmodel.npy')
cv2.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv2.GC_EVAL)
mask = np.where((mask==2) | (mask==0), 0, 1).astype('uint8')
img = img * mask[:, :, np.newaxis]
plt.imshow(img)
plt.show()
I tried to initialize the algorithm with a mask or a rectangle but this produces an error because the models are not empty (which is what I actually want).
How do I have to pass the pre-trained models to the algorithm, such that they are not retrained from scratch each time I'm segmenting an image?
EDIT After rayryeng's comment I implemented following code:
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 0, cv2.GC_INIT_WITH_RECT)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 2, cv2.GC_EVAL)
It seems to work but the first call now changes my model. In the source code it calls learnGMMs
without checking whether a pretrained model is provided.
cv2.GC_EVAL
's purpose is to already use pretrained models. You can even see that in the source. github.com/opencv/opencv/blob/master/modules/imgproc/src/…. When theGC_EVAL
is encountered, it does simple error checking of the masks without actually doing the learning before actually doing the segmentation. You should be able to usecv2.GC_EVAL
and specifying the foreground mask toNone
should work without a problem. – Tredecilliongrabcut
also are very curious: github.com/opencv/opencv/blob/…. You see that they first callgrabcut
with 0 iterations to learn the model, then they reuse those same models again to actually do the segmentation - 2 iterations. Give that a try? Try learning the model first with 0 iterations, then use the precomputed models withGC_EVAL
to finally do the segmentation. – TredecillionlearnGMMs
call that should not be there if you have a pre-trained model: github.com/opencv/opencv/blob/master/modules/imgproc/src/…. The only way to get around this now would be to place anif
statement checking forGC_EVAL
before thelearnGMMs
call, then recompile the code. It also looks like this issue has been encountered in the past: #23806564. This really should be fixed. – TredecillioninitGMMs
is only called if you provided theGC_INIT_WITH_RECT
orGC_INIT_WITH_MASK
flags. It does not get called withGC_EVAL
... the culprit is thelearnGMMs
function which actually does the GMM learning required for Grabcut, but since you have the models already computed, you should not need to do this when theGC_EVAL
flag is provided... and so oncelearnGMMs
is called, the models get cleared due to no foreground mask being provided. – Tredecillion