Skip to content

Commit cb84fae

Browse files
committed
review grabcut
1 parent b5f2cc2 commit cb84fae

File tree

6 files changed

+11
-8
lines changed

6 files changed

+11
-8
lines changed
-6.65 KB
Loading
-3.62 KB
Loading
-7.11 KB
Loading
11.9 KB
Loading
Binary file not shown.

source/py_tutorials/py_imgproc/py_grabcut/py_grabcut.rst

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Theory
1515

1616
GrabCut algorithm was designed by Carsten Rother, Vladimir Kolmogorov & Andrew Blake from Microsoft Research Cambridge, UK. in their paper, `"GrabCut": interactive foreground extraction using iterated graph cuts <http://dl.acm.org/citation.cfm?id=1015720>`_ . An algorithm was needed for foreground extraction with minimal user interaction, and the result was GrabCut.
1717

18-
How it works from user point of view ? Initially user draws a rectangle around the foreground region (foreground region shoule be completely inside the rectangle). Then algorithm segments it iteratively to get the best result. Done. But in some cases, the segmentation won't be fine, like, it may have marked some foreground region as background and vice versa. In that case, user need to do fine touch-ups. Just give some strokes on the images where some faulty results are there. Strokes basically says "Hey, this region should be foreground, you marked it background, correct it in next iteration" or its opposite for background. Then in the next iteration, you get better results.
18+
How it works from user point of view ? Initially user draws a rectangle around the foreground region (foreground region shoule be completely inside the rectangle). Then algorithm segments it iteratively to get the best result. Done. But in some cases, the segmentation won't be fine, like, it may have marked some foreground region as background and vice versa. In that case, user need to do fine touch-ups. Just give some strokes on the images where some faulty results are there. Strokes basically says *"Hey, this region should be foreground, you marked it background, correct it in next iteration"* or its opposite for background. Then in the next iteration, you get better results.
1919

2020
See the image below. First player and football is enclosed in a blue rectangle. Then some final touchups with white strokes (denoting foreground) and black strokes (denoting background) is made. And we get a nice result.
2121

@@ -25,7 +25,7 @@ See the image below. First player and football is enclosed in a blue rectangle.
2525

2626
So what happens in background ?
2727

28-
* User inputs the rectangle. Everything outside this rectangle will be taken as sure background (That is the reason it is mentioned before that your rectangle should include all the object). Everything inside rectangle is unknown. Similarly any user input specifying foreground and background are considered as hard-labelling which means they won't change in the process.
28+
* User inputs the rectangle. Everything outside this rectangle will be taken as sure background (That is the reason it is mentioned before that your rectangle should include all the objects). Everything inside rectangle is unknown. Similarly any user input specifying foreground and background are considered as hard-labelling which means they won't change in the process.
2929
* Computer does an initial labelling depeding on the data we gave. It labels the foreground and background pixels (or it hard-labels)
3030
* Now a Gaussian Mixture Model(GMM) is used to model the foreground and background.
3131
* Depending on the data we gave, GMM learns and create new pixel distribution. That is, the unknown pixels are labelled either probable foreground or probable background depending on its relation with the other hard-labelled pixels in terms of color statistics (It is just like clustering).
@@ -50,7 +50,7 @@ Now we go for grabcut algorithm with OpenCV. OpenCV has the function, **cv2.grab
5050
* *rect* - It is the coordinates of a rectangle which includes the foreground object in the format (x,y,w,h)
5151
* *bdgModel*, *fgdModel* - These are arrays used by the algorithm internally. You just create two np.float64 type zero arrays of size (1,65).
5252
* *iterCount* - Number of iterations the algorithm should run.
53-
* *mode* - It should be *cv2.GC_INIT_WITH_RECT* or *cv2.GC_INIT_WITH_MASK* or combined which decides whether we are drawing rectangle or final touchup strokes.
53+
* *mode* - It should be **cv2.GC_INIT_WITH_RECT** or **cv2.GC_INIT_WITH_MASK** or combined which decides whether we are drawing rectangle or final touchup strokes.
5454

5555
First let's see with rectangular mode. We load the image, create a similar mask image. We create *fgdModel* and *bgdModel*. We give the rectangle parameters. It's all straight-forward. Let the algorithm run for 5 iterations. Mode should be *cv2.GC_INIT_WITH_RECT* since we are using rectangle. Then run the grabcut. It modifies the mask image. In the new mask image, pixels will be marked with four flags denoting background/foreground as specified above. So we modify the mask such that all 0-pixels and 2-pixels are put to 0 (ie background) and all 1-pixels and 3-pixels are put to 1(ie foreground pixels). Now our final mask is ready. Just multiply it with input image to get the segmented image.
5656
::
@@ -75,13 +75,13 @@ First let's see with rectangular mode. We load the image, create a similar mask
7575
7676
See the results below:
7777

78-
.. image:: images/grabcut_rect.png
78+
.. image:: images/grabcut_rect.jpg
7979
:alt: Segmentation in rect mode
8080
:align: center
8181

82-
Oops, Messi's hair is gone. What is Messi without his hair? We need to bring it back. So we will give there a fine touchup with 1-pixel (sure foreground). At the same time, Some part of ground has come to picture which we don't want, and also some logo. We need to remove them. There we give some 0-pixel touchup (sure background). So we modify our resulting mask in previous case as we told now.
82+
Oops, Messi's hair is gone. *Who likes Messi without his hair?* We need to bring it back. So we will give there a fine touchup with 1-pixel (sure foreground). At the same time, Some part of ground has come to picture which we don't want, and also some logo. We need to remove them. There we give some 0-pixel touchup (sure background). So we modify our resulting mask in previous case as we told now.
8383

84-
*What I actually did is that, I opened image in paint, added another layer to image. Using brush tool in the paint, I marked missed foreground (hair, shoes, ball etc) with white and unwanted background( like logo, ground etc) with black. Filled remaining background with gray. Then loaded that mask image in OpenCV, edited original mask image we got with corresponding values in newly added mask image. Check the code below*
84+
*What I actually did is that, I opened input image in paint application and added another layer to the image. Using brush tool in the paint, I marked missed foreground (hair, shoes, ball etc) with white and unwanted background (like logo, ground etc) with black on this new layer. Then filled remaining background with gray. Then loaded that mask image in OpenCV, edited original mask image we got with corresponding values in newly added mask image. Check the code below:*
8585
::
8686

8787
# newmask is the mask image I manually labelled
@@ -92,7 +92,7 @@ Oops, Messi's hair is gone. What is Messi without his hair? We need to bring it
9292
mask[newmask == 0] = 0
9393
mask[newmask == 255] = 1
9494

95-
cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
95+
mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)
9696

9797
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
9898
img = img*mask[:,:,np.newaxis]
@@ -109,7 +109,10 @@ So that's it. Here instead of initializing in rect mode, you can directly go int
109109
Additional Resources
110110
=======================
111111

112+
113+
112114
Exercises
113115
============
114-
#. Here, you can make this into a interactive sample with drawing rectangle and strokes with mouse, create trackbar to adjust stroke width etc. Such an example is already there in OpenCV samples. Please have a look at it.
115116

117+
#. OpenCV samples contain a sample ``grabcut.py`` which is an interactive tool using grabcut. Check it. Also watch this `youtube video <http://www.youtube.com/watch?v=kAwxLTDDAwU>`_ on how to use it.
118+
#. Here, you can make this into a interactive sample with drawing rectangle and strokes with mouse, create trackbar to adjust stroke width etc.

0 commit comments

Comments
 (0)