具有背投影的OpenCV2皮肤分割

时间:2014-06-26 14:01:30

标签: c++ opencv computer-vision

我尝试使用反投影从我的网络摄像头检测视频中的人体皮肤。我使用一个OpenCV的haar级联分类器来检测面部,并使用前额区域生成背投影的直方图,以检测皮肤的其他区域。以下是我到目前为止的结果。下面的结果是我迄今为止最好的,它仍然有很多噪音。我想将整个脸部(以及检测到的所有其他皮肤区域)作为一个大型连接组件,这样我就可以在该区域周围绘制轮廓作为检测到的皮肤。我不知道如何继续,如果有人可以提供建议,代码片段等,我将非常感激。

以下是代码:

#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;


MatND getHistogram(Mat image);

int lowThreshold =  20;
int highThreshold = 20;

int channels[] = {0, 1};    // HUE & SATURATION

float h_range[] = {0, 179};
float s_range[] = {0, 255};

const float *ranges[] = {h_range, s_range};


Mat capturedFrame, flippedFrame, grayScaleFrame, hsvImage, hueImage, mask, backProjectedImage, grayForContour;
std::vector<    std::vector<cv::Point>   > contours;

int main(int argc, const char **argv){
     CascadeClassifier classifier;
     classifier.load("haarcascade_frontalface_alt2.xml");


VideoCapture captureDevice;
captureDevice.open(0);


namedWindow("Webcam Feed");


while(true){
    captureDevice >> capturedFrame;
    flip(capturedFrame, flippedFrame, 1);

    // gray scale for face detection
    cvtColor(flippedFrame, grayScaleFrame, CV_BGR2GRAY);
    equalizeHist(grayScaleFrame, grayScaleFrame);

    // hsv image conversion
    cvtColor(flippedFrame, hsvImage, CV_BGR2HSV);

    // separate only Hue channel to be used for the Histogram  in back projection
    hueImage.create(hsvImage.size(), hsvImage.depth());
    int ch[] = {0,0};
    mixChannels(&hsvImage, 1, &hueImage, 1, ch, 1);

    std::vector<Rect> faces;  // to store the face found

    //find faces and store them in the vector array
    classifier.detectMultiScale(grayScaleFrame, faces, 1.1, 3, CV_HAAR_FIND_BIGGEST_OBJECT|CV_HAAR_SCALE_IMAGE,  Size(30, 30) );

    if ( faces.size() > 0 ){
        for (int i = 0; i < faces.size(); i++){ 


            // /* BEGINNING BACKPROJECTION WITH FOREHEAD AS REGION OF INTERST */
            float topLeft_X = faces[i].x + faces[i].width/ 4;
            float topLeft_Y = faces[i].y + faces[i].height / 16;

            float bottomRight_X = topLeft_X + faces[i].width / 2;
            float bottomRight_Y = topLeft_Y + faces[i].height/6;

            Point roiPt1(  topLeft_X, topLeft_Y );
            Point roiPt2( bottomRight_X, bottomRight_Y  );

            Mat faceROI = flippedFrame(cv::Rect( topLeft_X , topLeft_Y, bottomRight_X - topLeft_X, bottomRight_Y - topLeft_Y  ));
            // namedWindow("ROI");
            // imshow("ROI", faceROI);

            //draw the rectangle of the region of interst
            rectangle(flippedFrame, roiPt1, roiPt2, Scalar(0, 0, 255), 1, 8, 0);


            //convert the forehead ROI to hsv
            Mat roiHSV;
            cvtColor(faceROI, roiHSV, CV_BGR2HSV);

            // Get a histogram of the HSV of the ROI
            MatND roiHist = getHistogram(roiHSV); 
            normalize(roiHist, roiHist, 0, 255, NORM_MINMAX, -1, Mat());                

            // now calculate a backprojection of the hue image
            calcBackProject(&hsvImage, 1, channels, roiHist, backProjectedImage, ranges, 1, true);
            /* ENDING NEW BACKPROJECTION ATTEMPT */


            // Threshold the back projected image
            Mat final;

            /* 
                APPLY GAUSSIAN FILTER BEFORE THRESHOLDING with OTSU
            */
            Mat blur;
            GaussianBlur(backProjectedImage, blur, Size(5, 5),0);
            threshold(blur, final, 0,255,THRESH_BINARY+THRESH_OTSU);

            // opening
            // erode(final, final, MORPH_RECT);
            // dilate(final, final, MORPH_RECT);


            //show the backprojected image
            // namedWindow("Back Projection");
            // imshow("Back Projection", backProjectedImage);

            namedWindow("Threshold Image after Back Projection");
            imshow("Threshold Image after Back Projection", final);


            //Drawing the rectangle around the found face
            Point facePt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
            Point facePt2( faces[i].x, faces[i].y );
            rectangle(flippedFrame, facePt1, facePt2, cvScalar(0, 255, 0), 1, 8, 0);

        }
    }

    imshow("Webcam Feed", flippedFrame);        

    if (waitKey(10) == 27){
        break;
    }

}   

return 0;

}

// Get a histogram of the forehead ROI using the hue and saturation only
MatND getHistogram(Mat image){
    MatND hist;
    int h_bins = 30;
    int s_bins = 32;
    int histSize[] = {h_bins, s_bins};
    cv::calcHist(&image, 1, channels, Mat(), hist, 2, histSize, ranges);
    return hist;
}

以下是我现在的结果:

result

0 个答案:

没有答案