Ask Your Question
1

When segment an image with same mask multiple times continuously with same parameters, get different results.

asked 2017-09-16 01:08:39 -0500

AndrewHK gravatar image

updated 2017-09-16 03:18:41 -0500

When I grabcut an image with the same mask multiple times continuously, I got different segment results. The parameters are same too, for example the iteration was set as 1. Although the difference is very small( at pixel-level), it should be same.

But, for same image and mask, if I run the grabcut once, then restart the program run again, the results are same.

The attach is example of test image and related mask, and three results(to show clearly, I used the color-codedimage [0,0,0]==background, [255,0,0] == foreground, [0,0,255]== possible background). You can change them to mask label.

source image color-coded mask the first result the second result the third result Looking forwards to your answers.

the code is as following:

import cv2
import numpy as np

imgCut = cv2.imread('test.png', 1)
maskimg = cv2.imread('testmask.png', 1)
GrayImg = cv2.cvtColor(maskimg, cv2.COLOR_BGR2GRAY)

# first grabcut & its result
mask = np.zeros(GrayImg.shape, np.uint8)
mask[GrayImg > 20] = 2
mask[GrayImg > 70] = 1
mask[GrayImg == 0] = 0
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
mask, bgdModel, fgdModel = cv2.grabCut(imgCut, mask, None, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_MASK)
newmask = np.where((mask == 2) | (mask == 0), 0, 255).astype('uint8')
imgF = imgCut * newmask[:, :, np.newaxis]
cv2.imwrite('cut.png', imgF)

# second grabcut & its result
mask1 = np.zeros(GrayImg.shape, np.uint8)
mask1[GrayImg > 20] = 2
mask1[GrayImg > 70] = 1
mask1[GrayImg == 0] = 0
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
mask1, bgdModel, fgdModel = cv2.grabCut(imgCut, mask1, None, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_MASK)
newmask1 = np.where((mask1 == 2) | (mask1 == 0), 0, 255).astype('uint8')
imgF1 = imgCut * newmask1[:, :, np.newaxis]
cv2.imwrite('cut1.png', imgF1)
# third grabcut & its result
mask2 = np.zeros(GrayImg.shape, np.uint8)
mask2[GrayImg > 20] = 2
mask2[GrayImg > 70] = 1
mask2[GrayImg == 0] = 0
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
mask2, bgdModel, fgdModel = cv2.grabCut(imgCut, mask2, None, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_MASK)
newmask2 = np.where((mask2 == 2) | (mask2 == 0), 0, 255).astype('uint8')
imgF2 = imgCut * newmask2[:, :, np.newaxis]
cv2.imwrite('cut2.png', imgF2)
edit retag flag offensive close merge delete

Comments

have you read doc ? if you don't understand you can read paper too "GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts"

LBerger gravatar imageLBerger ( 2017-09-16 02:31:32 -0500 )edit

@LBerger, I know how to use grabcut also the theory. I just make an experiment. When I segment an image for three times with same parameters and mask, but the segmented results are different. I want to ask why

AndrewHK gravatar imageAndrewHK ( 2017-09-16 03:08:48 -0500 )edit

show your code

LBerger gravatar imageLBerger ( 2017-09-16 03:12:04 -0500 )edit
1

@LBerger the code is attached. I also ask my friends, opencv for android&ios also have the same issue.

AndrewHK gravatar imageAndrewHK ( 2017-09-16 03:20:13 -0500 )edit

@LBerger I test a group of 30 images, they all have the same issue. The image in this question is just an example. You can test it, thanks.

AndrewHK gravatar imageAndrewHK ( 2017-09-16 03:30:59 -0500 )edit

1 answer

Sort by » oldest newest most voted
2

answered 2017-09-16 07:37:04 -0500

LBerger gravatar image

Ok I can reproduce issue in C++. IMHO There is no problem. Why results are differents? Because in grabcut you need to estimate gaussian mixture for foreground and background. In opencv mixture are estimated using kmeans. kmeans gives a gaussian mixture using an iterative algorithm with random trials (5=GMM::componentsCount). Mixture are hence differents and grabut results too....

Good questions!

edit flag offensive delete link more

Comments

@LBerger Thanks for your answer. The explain is very clear. But I notice that if run the code once, we can get three different results. And close the process & run it again, the new three results are same to last three correspondingly. Is that because the random trials follow a rule but not real random?

If I need to keep the segmentation results consistence, could you suggest a solution? thanks so much.

AndrewHK gravatar imageAndrewHK ( 2017-09-16 23:11:42 -0500 )edit

Probably the default seed for the RNG is fixed somehow. Try to change the seed maybe (here in C++)?

Eduardo gravatar imageEduardo ( 2017-09-17 04:29:55 -0500 )edit

@Eduardo thanks,is there some method to change the seed in opencv-python binding?

AndrewHK gravatar imageAndrewHK ( 2017-09-17 06:01:12 -0500 )edit
1

I don't know answer in python but in C++ something like this should work before calling grabcut :

RNG& rng = theRNG();
rng.state=0;
LBerger gravatar imageLBerger ( 2017-09-17 11:08:48 -0500 )edit

Thanks @LBerger.

AndrewHK gravatar imageAndrewHK ( 2017-09-17 20:45:54 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2017-09-16 01:08:39 -0500

Seen: 515 times

Last updated: Sep 16 '17