2

I am using threshold in Opencv to find the contours. My input is a hand image. Sometimes the threshold is not good so I couldnt find the contours.

I have applied the below preprocessing steps
1. Grabcut

cv::grabCut(image, result,rectangle,bgModel,fgModel, 3,cv::GC_INIT_WITH_RECT);
  1. gray Scale conversion

    cvtColor(handMat, handMat, CV_BGR2GRAY);

  2. meadianblur

    medianBlur(handMat, handMat, MEDIAN_BLUR_K);

I used the below code to find threshold

threshold( handMat, handMat, 141, 255, THRESH_BINARY||CV_THRESH_OTSU );

Sometimes I get good output and sometimes the threshold output is not good. I have attached the two output images.

Is there any other way than threshold from which contours can be found?

Good threshold Output:

enter image description here

Bad threshold Output

enter image description here

user2727765
  • 616
  • 1
  • 12
  • 28
  • Are you converting the image into HSV color space? look at the following links..1.http://stackoverflow.com/questions/12968576/opencv-skin-detection?rq=1 2. http://stackoverflow.com/questions/8753833/exact-skin-color-hsv-range – G453 Feb 26 '14 at 05:51
  • 2
    `THRESH_BINARY||CV_THRESH_OTSU == 1`. you probably wanted to say : `THRESH_BINARY|CV_THRESH_OTSU` but still, both flags are xor – berak Feb 26 '14 at 07:49
  • Could you show the input image as well? – Rethunk Mar 01 '14 at 06:29

2 Answers2

5

Have you tried an adaptive threshold? A single value of threshold rarely works in real life application. Another truism - threshold is a non-linear operation and hence non-stable. Gradient on the other hand is linear so you may want to find a contour by tracking the gradient if your background is smooth and solid color. Gradient is also more reliable during illumination changes or shadows than thresholding.

Grab-cut, by the way, uses color information to improve segmentation on the boundary when you already found 90% or so of the segment, so it is a post processing step. Also your initialization of grab cut with rectangle lets in a lot of contamination from background colors. Instead of rectangle use a mask where you mark as GC_FGD deep inside your initial segment where you are sure the hand is; mark as GC_BGD far outside your segment where you sure background is; mark GC_PR_FGD or probably foreground everywhere else - this is what will be refined by grab cut. to sum up - your initialization of grab cut will look like a russian doll with three layers indicating foreground (gray), probably foreground (white) and background (balck). You can use dilate and erode to create these layers, see below

enter image description here

Overall my suggestion is to define what you want to do first. Are you looking for contours of arbitrary objects on arbitrary moving background? If you are looking for a contour of a hand to find fingers on relatively uniform background I would: 1. use connected components or MSER to segment out a hand. Possibly improve results with grab cut initialized with the conservative mask and not rectangle! 2. use convexity defects to find fingers if this is your goal;

Vlad
  • 4,425
  • 1
  • 30
  • 39
1

One issue is to try to find contours without binarizing the image. If your input is in color, you can try to change color space in order to enhance the difference between the hand and the background.

Otsu try to find an optimal threshold, you can also try to set it manually but Otsu is useful because if the illumination change, the threshold will adapt automatically.

There are also many other kind of binarization : Sauvola, Bradley, Niblack, Kasar... but Otsu is simple, and work well. I suggest you to do preprocessing or postprocessing if you want to improve the binarization result.

Olivier A
  • 842
  • 4
  • 8
  • OpenCV function is adaptiveThreshold: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html – Sebastian Schmitz Feb 26 '14 at 08:17
  • Hi I have updated the question. Please have a look. I have used pre-processing techniques like 1) Grabcut 2) gray scale 3) Median blur. – user2727765 Feb 26 '14 at 12:00
  • Did you try to use Canny for detecting edges ? After Canny you can also try to use [findContours](http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html). – Olivier A Feb 26 '14 at 12:10
  • You can also try to do histogram equalization in order to enhance the contrast automatically of grayscale images. – Olivier A Feb 26 '14 at 12:31