【问题标题】:How to extract skin from an image using HSV thresholding and contouring in OpenCv?如何使用 OpenCv 中的 HSV 阈值和轮廓从图像中提取皮肤?
【发布时间】:2015-04-18 22:57:55
【问题描述】:

这是我的代码。 Skin Detector 是一个单独的类,它执行 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 功能时,它不会给我一个错误,但它也没有显示图片中的任何变化。

请不要介意过多的变量和糟糕的编程。它是一个测试版本。

【问题讨论】:

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


    【解决方案1】:

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

    然后尝试这些步骤,

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

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

    3. 对于眼睛检测:使用圆形检测方法获取眼球,它将代表您的眼睛。

    4. 对于皮肤检测:仅使用色调,因为颜色由色调表示,请参阅my paper 以检测皮肤。

    5. 对于鼻子等其他面部特征,尝试其他阈值方法。

    希望这会有所帮助。

    干杯:)

    【讨论】:

      猜你喜欢
      • 2020-05-08
      • 1970-01-01
      • 2020-03-29
      • 2013-12-17
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      相关资源
      最近更新 更多