2015-04-18 4 views
1

Это мой код. Skin Detector - отдельный класс, который устанавливает порог HSV. Я его охватил.Как извлечь кожу из изображения, используя порог HSV и контур в OpenCv?

` 


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, он не дает мне ошибку, но также не показывает никаких изменений на картинке.

Пожалуйста, не обращайте внимания на чрезмерные переменные и плохое программирование. Его тестовая версия.

ответ

0

Насколько я понимаю, вы используете каскад и контур, чтобы получить лицо.

Затем выполните следующие действия,

  1. обнаружить самый большой контур, которые представляют собой, как лицо и удалить все другие мелкие контуры.

  2. наложить свое изображение на двоичную поверхность с оригинальным изображением, чтобы получить реальное лицо, а затем использовать другой порог, например Ostu Method.

  3. Для обнаружения глаз: используйте метод обнаружения круга, чтобы получить глазной шар, который будет представлять ваши глаза.

  4. Для обнаружения кожи: Используйте только оттенок, потому что цвет представлен оттенком и см. my paper для обнаружения кожи.

  5. И для других функций лица, таких как нос, попробуйте другие методы порога.

Надеется, что это помогает.

Cheers :)