如何在OpenCv中使用HSV阈值和轮廓从图像中提取皮肤?

时间:2015-04-18 22:57:55

标签: c++ opencv visual-studio-2012 hsv

这是我的代码。皮肤检测器是一个单独的类,可以进行HSV阈值处理。我已经覆盖了它。

`


using namespace std;
using namespace cv;


// Function Headers
void Display(String s);
void detectAndDisplay(Mat frame);

void drawStuff();
void showInputWindow();
void showCannyWindow();
void showContourWindow();
void FindContour(Mat skinMat);


// Global variables

 cv::Rect roi_b;
 cv::Rect roi_c;
 int thresh = 2;
 Mat img_rgb,img_gray,img_bw,canny_output,drawing;


// Copy this file from opencv/data/haarscascades to target folder

string face_cascade_name = "c:/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Face detection";
int filenumber; // Number of file to be saved
string filename;

// Function main

int main(void)
{


//  Display("3.jpg");


    // Load the cascade
    if (!face_cascade.load(face_cascade_name))
    {
        printf("--(!)Error loading\n");
        return (-1);
    };

    // Read the image file


    Mat frame = imread("c:/Emma.jpg");

 //   for (;;)
    {
        // Apply the classifier to the frame
        if (!frame.empty())
        {
            detectAndDisplay(frame);

            // detect skin
            SkinDetector mySkinDetector;
            Mat skinMat;
            skinMat= mySkinDetector.getSkin(frame);

            imshow("Skin Image",skinMat);

            // for contour detection

    img_rgb  = skinMat;
    blur( img_rgb, img_rgb, Size(3,3) );
    cvtColor(img_rgb,img_gray,CV_RGB2HSV);
  //  showInputWindow();

    drawStuff();
    cv::waitKey(0);


    }

        else
        {
            printf(" --(!) No captured frame -- Break!");
           // break;
        }

        int c = waitKey(10);

        if (27 == char(c))
        {
           // break;
        }





    /*for (int s=3 ; s>=0 ; s-- )
    {
        Display(+s+".jpg");
    }*/

    getchar();
    //waitKey(10);
    return 0;
}

}


// Function detectAndDisplay
void detectAndDisplay(Mat frame)

{
    std::vector<Rect> faces;
    Mat frame_gray;
    Mat crop;
    Mat res;
    Mat gray;
    string text;
    stringstream sstm;
    Mat Test1 = frame;

    cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
    equalizeHist(frame_gray, frame_gray);

    // Detect faces
    face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

    // Set Region of Interest
   /* cv::Rect roi_b;  we need them global
    cv::Rect roi_c;*/

    size_t ic = 0; // ic is index of current element
    int ac = 0; // ac is area of current element

    size_t ib = 0; // ib is index of biggest element
    int ab = 0; // ab is area of biggest element

    for (ic = 0; ic < faces.size(); ic++) // Iterate through all current elements (detected faces)

    {
        roi_c.x = faces[ic].x;
        cout<<roi_c.x<<"/n";;
        roi_c.y = faces[ic].y;
        cout<<roi_c.y<<"/n";
        roi_c.width = (faces[ic].width);
        roi_c.height = (faces[ic].height);

        ac = roi_c.width * roi_c.height; // Get the area of current element (detected face)

        roi_b.x = faces[ib].x;
        roi_b.y = faces[ib].y;
        roi_b.width = (faces[ib].width);
        roi_b.height = (faces[ib].height);

        ab = roi_b.width * roi_b.height; // Get the area of biggest element, at beginning it is same as "current" element

        //if (ac > ab)
        //{
        //    ib = ic;
        //    roi_b.x = faces[ib].x;
        //    roi_b.y = faces[ib].y;
        //    roi_b.width = (faces[ib].width);
        //    roi_b.height = (faces[ib].height);
        //}

        crop = frame(roi_b);
      //  resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR); // This will be needed later while saving images
      //  cvtColor(crop, gray, CV_BGR2HSV); // Convert cropped image to Grayscale

        // Form a filename
        filename = "";
        stringstream ssfn;
        ssfn << filenumber << ".jpg";
        filename = ssfn.str();
        filenumber++;

    //  Mat ArrayDetectedFaces [] 

        imwrite(filename, crop);

        Point pt1(faces[ic].x, faces[ic].y); // Display detected faces on main window - live stream from camera
        Point pt2((faces[ic].x + faces[ic].height), (faces[ic].y + faces[ic].width));
        rectangle(frame, pt1, pt2, Scalar(255, 0, 0), 2, 1, 0);

        FindContour(frame(roi_c));

    }

    // Show image
    sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
    text = sstm.str();

    putText(frame, text, cvPoint(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(0, 0, 255), 1, CV_AA);
    imshow("original", frame);



    Mat ccc = frame (roi_c);
    Mat bbb = frame (roi_b);
    Mat Img = frame;
    Mat destinationROI = frame( roi_c );



Size size(roi_c.width , roi_c.height);//the dst image size,e.g.100x100

Mat dst = bbb;//dst image
Mat src = ccc;//src image

cout<< dst.cols<<"\n";
cout<< dst.rows<<"\n";

resize(src,dst,size);//resize image

cout<< dst.cols<<"\n";
cout<< dst.rows<<"\n";

cout<< src.cols<<"\n";
cout<< src.rows<<"\n";


cout<< roi_b.width<<"\n";
cout<< roi_b.height<<"\n";

cout<< roi_c.width<<"\n";
cout<< roi_c.height<<"\n";

dst.copyTo(Img( roi_c ));

Mat FML;

//compare(dst,  Img(roi_c), FML , CMP_EQ );
    //cout<<FML;




    if (!crop.empty())
    {
    //  imshow("c", Test1(roi_c));

    //    imshow("b", bbb);
    //  imshow("result", Img(roi_c));
    }
    else
        destroyWindow("detected");
}




void Display(String s)

{
    Mat I = imread(s);
if (I.empty())
{
    std::cout << "!!! Failed imread(): image not found" << std::endl;
    // don't let the execution continue, else imshow() will crash.
}

namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Display window", I ); 

}




void drawStuff(){
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    Canny( img_gray, canny_output, thresh, thresh*2, 3 );
    cv::dilate(canny_output, canny_output, cv::Mat(), cv::Point(-1,-1));
  //  showCannyWindow();

    findContours( canny_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    drawing = Mat::zeros( canny_output.size(), CV_8UC3 );

    vector<Point> approxShape;
    for(size_t i = 0; i < contours.size(); i++){
        approxPolyDP(contours[i], approxShape, arcLength(Mat(contours[i]), true)*0.04, true);
        drawContours(drawing, contours, i, Scalar(255, 255, 255), CV_FILLED);   // fill BLUE
    }

    showContourWindow();
}

void showContourWindow()
{
    cv::namedWindow("Fill");
    cv::imshow("Fill",drawing);
}

void FindContour(Mat skinMat)

{
img_rgb  = skinMat;
    blur( img_rgb, img_rgb, Size(3,3) );
    cvtColor(img_rgb,img_gray,CV_RGB2HSV);
  //  showInputWindow();

    drawStuff();
    cv::waitKey(0);
}`

在阈值和轮廓之后,输出就像这样。!

  http://postimg.org/image/5ri87c2r5/

我的问题是,如何使用此图像仅提取脸部(皮肤,眼睛,鼻子,嘴唇)的特征并将其放在另一个图像上。它会起作用吗?有没有更简单的方法呢?

如果有更简单的方法,请解释。

非常重要所以请帮助我。

此外,当我使用copyto功能时,它并没有给我一个错误,但它也没有显示图片中的任何变化。

请不要注意过多的变量和错误的编程。它是一个测试版本。

1 个答案:

答案 0 :(得分:0)

据我所知,你使用级联和轮廓来获得面子。

然后尝试这些步骤,

  
      
  1. 检测最大轮廓,表示为脸部并移除所有其他小轮廓。

  2.   
  3. 将二进制面部图像与原始图像重叠以获得真实面部,然后使用其他阈值,例如Ostu Method

  4.   
  5. 用于眼睛检测:使用圆形检测方法获取眼球,这将代表您的眼睛。

  6.   
  7. 对于皮肤检测:仅使用色调,因为颜色用色调表示,并参考my paper来检测皮肤。

  8.   
  9. 对于鼻子等其他脸部特征,请尝试其他阈值方法。

  10.   

希望这有帮助。

干杯:)