MFC button click to open file selection dialog and get picture

Face detection based on Opencv and MFC-based face-changing applet

1. Background

Opencv has been in contact for a while, whether it is Python or C++, it runs in the console, and uses Opencv's imshow to observe the results. I'm learning MFC recently, and I want to combine face detection and MFC to make a simple face-changing applet.

2. Design

Using a simple button-event mechanism, each button implements a different function. The design of the program panel is as follows:

3. Problems solved

1. The problem of displaying pictures

When Opencv1 is used, it can support drawing directly in the Pic control control of MFC. But after Opencv2, it is no longer supported. For convenience, I found this code from the Internet and directly imported it into the project.

2. The problem of opening the picture

I hope the program can be more friendly, so I abandoned the original way of manually editing the image path in the code, and used the CfileDialog class in MFC to create a new file selection dialog, so as to obtain the file path friendly and easy to operate.

3. String format conversion problem

Cstring to char* can only be converted by the WideCharToMultiByte() function in a Unicode encoding project.

CStringfileinfo=filepathname;

    intlen=WideCharToMultiByte(CP_ACP,0,fileinfo,-1,NULL,0,NULL,NULL); 

    char * path = new char [ len + 1 ]; 

    WideCharToMultiByte(CP_ACP,0,fileinfo,-1,path,len,NULL,NULL); 

4. The use of IplImage and Mat

IplImage is a pointer, and Mat is an object, so the assignment of these two types should be noted that the assignment to the IplImage type is actually still the original Image, and defining a new Mat and then assigning it is actually a copy between objects. operate.

5. The use of the sprintf_s function

sprintf_s(result,"Havefound %d faces",faces.size());

If it contains Chinese, there will be garbled characters in the MessageBox, which is related to the encoding. In the Unicode project, try to use English to avoid garbled characters.

6. Vertex coordinate problem of Vector<Rect> type

.tl() is the upper left corner coordinate, type Point

.br() is the coordinate of the lower right corner, and the type is also Point

Note that this is a function call, if you don't add (), you will get an error when compiling

such as error " .x " must have class / struct / union on the left side"

7. Image coordinate system problem

8. CascadeClassifier problem

I don't know if it is related to the version. The cvHarrDetect program under cvCascadeClassifier crashes, but the detectMultiScale under CascadeClassifier runs normally.

4. Operation effect




5. Code

1. See the previous blog post for CvvImage.cpp and CvvImage.h

2. Each button responds to events

voidCChangeFaceDlg::OnBnClickedButton1()
{
        // TODO: Add control notification handler code here
        CString filter;
        filter="(file type)(*.*)|*.*||";
        CFileDialogdlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,filter,NULL);
        if(dlg.DoModal()==IDOK)
        {
 
                 filename = dlg.GetFileName();
                 fileext = dlg.GetFileExt();//File extension
                 filepathname =dlg.GetPathName();
                 //MessageBox(str);
        }
        CString fileinfo = filepathname;
        int len=WideCharToMultiByte(CP_ACP,0,fileinfo,-1,NULL,0,NULL,NULL);
        char *path =new char[len +1];
        WideCharToMultiByte(CP_ACP,0,fileinfo,-1,path,len,NULL,NULL);
        //MessageBox(fileinfo);
        if(image) cvReleaseImage(&image);
        image = cvLoadImage(path,1); //Display image
        gray_img = cvLoadImage(path,1);
        delete[] path;
        DrawPicToHDC(gray_img, IDC_PIC1);
}
 
 
voidCChangeFaceDlg::OnBnClickedButton2()
{
 
        DrawPicToHDC(gray_img, IDC_PIC2);
}
voidCChangeFaceDlg::Facedetect(IplImage *img)
{
        // load the classifier
        CascadeClassifier face_cascade;
        face_cascade.load("haarcascade_frontalface_alt.xml");
        Mat gray = Mat (img);
 
        face_cascade.detectMultiScale(gray,faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
        char result[200]={0};
        sprintf_s(result,"Have found %dfaces",faces.size());
        CString str(result);
        MessageBox(str);
        //Store the center point of the two faces, only two faces
        for(unsigned int i=0;i <faces.size();i++)
        {
                 rectangle(gray,faces[i],RGB(0,255,0),2);
        }
 
}
 
 
voidCChangeFaceDlg::OnBnClickedButton3()
{
        // TODO: Add control notification handler code here
        gray = Mat(gray_img);
        draw = Mat(image);
        cvtColor(gray,gray,CV_BGR2GRAY);
        //imshow("gray",gray);
        //waitKey(0);
        *gray_img = IplImage(gray);
        Facedetect(gray_img);
}
 
 
voidCChangeFaceDlg::OnBnClickedButton4()
{
        // TODO: Add control notification handler code here
        Point centers[2];
        if(faces.size()==2)
        {
                 int h[2]={0,0};int w[2]={0,0};
                 Mat tmp_img[2];
                 for(unsigned int i=0;i <faces.size();i++)
                 {
                         /*rectangle(draw,faces[i],RGB(0,255,0),2);*/
                         centers[i] =(Point((faces[i].tl().x+faces[i].br().x)/2,(faces[i].tl().y+faces[i].br().y)/2));
                         h[i] =-faces[i].tl().y+faces[i].br().y;
                         w[i] =-faces[i].tl().x+faces[i].br().x;
                         tmp_img[i] =Mat::zeros(h[i],w[i],draw.type());
                 }
                 double x1[2],y1[2];
                 x1[0] = centers[1].x-w[0]/2.0;
                 y1[0] = centers[1].y-h[0]/2.0;
                 x1[1] = centers[0].x-w[1]/2.0;
                 y1[1] = centers[0].y-h[1]/2.0;
 
                 for(int i=0;i<2;i++)
                 {
                         for(intk=0,n=y1[i];k<tmp_img[i].rows;k++,n++)
                         {
                                  for(intl=0,m=x1[i];l<tmp_img[i].cols;l++,m++)
                                  {
                                          for(intc=0;c<3;c++)
                                          {
                                                  tmp_img[i].at<Vec3b>(k,l)[c]= draw.at<Vec3b>(n,m)[c];
                                          }
                                  }
                         }
                 }
                 for(int i=0,j=1;i<2;i++,j--)
                 {
                         for(intk=0,n=y1[i];k<tmp_img[j].rows;k++,n++)
                         {
                                  for(intl=0,m=x1[i];l<tmp_img[j].cols;l++,m++)
                                  {
                                          for(intc=0;c<3;c++)
                                          {
                                                  draw.at<Vec3b>(n,m)[c]= tmp_img[j].at<Vec3b>(k,l)[c];
                                          }
                                  }
                         }
                 }
                 /*imshow("one",tmp_img[0]);
                 imshow("two",tmp_img[1]);
                 waitKey(0);*/
                 *image = IplImage(draw);
                 DrawPicToHDC(image, IDC_PIC2);
        }else
        {
                 MessageBox(L"Please make sure two faces are detected");
        }
}


6. All codes and projects have been uploaded for review

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325063508&siteId=291194637