OpenCV Skin Detection

Og Namdik picture Og Namdik · Oct 19, 2012 · Viewed 18.9k times · Source

I've been doing some skin detection but can't get a smooth one. The image below contains the input (left) and output (right) using the code also attached below. Now, the desired output should have been the bottom most image (the one that is smooth on the edges and doesn't have holes within). How do I achieve this output? A sample code on where to start would be of great help.

Input (left) and Incorrect output (right):

enter image description here

Desired output:

enter image description here

Code to generate the Incorect output:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int main(){
    Mat src = imread("qq.jpg");
    if (src.empty())
        return -1;
    blur( src, src, Size(3,3) );
    Mat hsv;
    cvtColor(src, hsv, CV_BGR2HSV);
    Mat bw;
    inRange(hsv, Scalar(0, 10, 60), Scalar(20, 150, 255), bw);
    imshow("src", src);
    imshow("dst", bw);
    waitKey(0);
    return 0;
}

Modified Code (after Astor's suggestion): (the problem now is: how do you smoothen the output?)

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int findBiggestContour(vector<vector<Point> >);

int main(){
    Mat src = imread("qq.jpg");
    if (src.empty())
        return -1;
    blur( src, src, Size(3,3) );

    Mat hsv;
    cvtColor(src, hsv, CV_BGR2HSV);

    Mat bw;
    inRange(hsv, Scalar(0, 10, 60), Scalar(20, 150, 255), bw);
    imshow("src", src);
    imshow("dst", bw);

    Mat canny_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    findContours( bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    int s = findBiggestContour(contours);

    Mat drawing = Mat::zeros( src.size(), CV_8UC1 );
    drawContours( drawing, contours, s, Scalar(255), -1, 8, hierarchy, 0, Point() );

    imshow("drw", drawing);
    waitKey(0);
    return 0;
}

int findBiggestContour(vector<vector<Point> > contours){
    int indexOfBiggestContour = -1;
    int sizeOfBiggestContour = 0;
    for (int i = 0; i < contours.size(); i++){
        if(contours[i].size() > sizeOfBiggestContour){
            sizeOfBiggestContour = contours[i].size();
            indexOfBiggestContour = i;
        }
    }
    return indexOfBiggestContour;
}

Answer

ArtemStorozhuk picture ArtemStorozhuk · Oct 19, 2012

You should use findContours to detect the biggest contour and after this draw founded contour with fill parameter -1 using method drawContours. Here's useful link: http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html