与上一篇博客类似,这篇博客介绍使用OpenCV实现的MFC程序,可以实现单个人脸的验证,并在图像和界面给出识别结果。效果图如下:
置信度一栏可以填写判定的阈值,默认为70。打开摄像头才能进行验证或拍照,拍照之前可以清除之前拍摄的训练图片,可以拍摄多张用于识别。其中mfc中的图像显示需要用到CvImage.cpp和CvImage.h两个文件,该代码在比较新的OpenCV内已经没有了,所以可以直接用我代码里的。
有人说代码的检测率不高,其实可以归结为两方面的原因,第一人脸检测率不高,这个可以通过嵌套检测嘴角、眼睛等来降低,或者背景、光照固定的话可以通过图像差分来解决;第二是识别方法本身的问题,如果想提高识别率,可以添加多张不同姿态、光照下的人脸作为训练的样本,如果有时间的话可以在采集图像时给出一个人脸框,引导用户对齐人脸进行采集,三星手机解除锁屏就有这么一个功能。
下面贴一下主要的代码:
VideoMFCDlg.cpp
// VideoMFCDlg.cpp : implementation file // #include "stdafx.h" #include "VideoMFC.h" #include "VideoMFCDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif CvCapture* capture; CRect rect; CDC *pDC; HDC hDC; CWnd *pwnd; CvVideoWriter* writer = 0; IplImage *resizeRes;//存放检测到的人脸 IplImage* faceGray;//存放检测到的人脸 灰度图像 bool bool_cameOpen = false;//全局变量 标志摄像头是否打开 bool bool_picNum = false;//全局变量 标志训练图片是否为空 bool bool_detec_reco = false;//全局变量 double dConfidence = 0;//置信度 int predictedLabel = 100000; CvMemStorage* storage = 0; CvHaarClassifierCascade* cascade = 0; CvHaarClassifierCascade* nested_cascade = 0; int use_nested_cascade = 0; const char* cascade_name = "../data/haarcascades/haarcascade_frontalface_alt.xml"; const char* nested_cascade_name = "../data/haarcascade_eye_tree_eyeglasses.xml"; double scale = 1; int num_components = 9; double facethreshold = 9.0; //cv::Ptr<cv::FaceRecognizer> model = cv::createFisherFaceRecognizer(); cv::Ptr<cv::FaceRecognizer> model = cv::createLBPHFaceRecognizer();//LBP的这个方法在单个人脸验证方面效果最好 //cv::Ptr<cv::FaceRecognizer> model = cv::createEigenFaceRecognizer(); vector<Mat> images; vector<int> labels; IplImage *frame, *frame_copy = 0; IplImage *image = 0; const char* scale_opt = "--scale="; // 分类器选项指示符号 int scale_opt_len = (int)strlen(scale_opt); const char* cascade_opt = "--cascade="; int cascade_opt_len = (int)strlen(cascade_opt); const char* nested_cascade_opt = "--nested-cascade"; int nested_cascade_opt_len = (int)strlen(nested_cascade_opt); int i; const char* input_name = 0; // CAboutDlg dialog used for App About CString strConfidence = "70"; CEdit* pEdtConfidence; CString strTip = ""; CEdit* pTip; class CAboutDlg : public CDialogEx { public: CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CVideoMFCDlg dialog CVideoMFCDlg::CVideoMFCDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CVideoMFCDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CVideoMFCDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CVideoMFCDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CVideoMFCDlg::OnBnClickedButton1) ON_WM_TIMER() ON_BN_CLICKED(IDC_BUTTON2, &CVideoMFCDlg::OnBnClickedButton2) ON_WM_CLOSE() ON_EN_CHANGE(IDC_EdtConfidence, &CVideoMFCDlg::OnEnChangeEdtconfidence) ON_BN_CLICKED(IDC_Photograph, &CVideoMFCDlg::OnBnClickedPhotograph) ON_BN_CLICKED(IDC_Recognize, &CVideoMFCDlg::OnBnClickedRecognize) ON_BN_CLICKED(IDC_ClearPictures, &CVideoMFCDlg::OnBnClickedClearpictures) END_MESSAGE_MAP() // CVideoMFCDlg message handlers BOOL CVideoMFCDlg::OnDestroy() { cvReleaseImage( &resizeRes ); cvReleaseImage( &faceGray ); return TRUE; } BOOL CVideoMFCDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here pwnd = GetDlgItem(IDC_ShowImage); //pwnd->MoveWindow(35,30,352,288); pDC =pwnd->GetDC(); //pDC =GetDC(); hDC= pDC->GetSafeHdc(); pwnd->GetClientRect(&rect); GetDlgItem(IDC_BUTTON2)->EnableWindow(false); GetDlgItem(IDC_Photograph)->EnableWindow(false); GetDlgItem(IDC_Recognize)->EnableWindow(false); pEdtConfidence = (CEdit*) GetDlgItem(IDC_EdtConfidence); pTip = (CEdit*) GetDlgItem(IDC_Tip); pEdtConfidence->SetWindowText("70"); pEdtConfidence->GetWindowText(strConfidence); pTip->SetWindowText( strTip ); if(read_img_number()>0) bool_picNum = true; else bool_picNum = false; return TRUE; // return TRUE unless you set the focus to a control } void CVideoMFCDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CVideoMFCDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CVideoMFCDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } /*****************************************打开摄像头*******************************************/ void CVideoMFCDlg::OnBnClickedButton1() { // TODO: Add your control notification handler code here //AfxMessageBox("OK"); if(!capture) { capture = cvCaptureFromCAM(0); //AfxMessageBox("OK"); } if (!capture) { AfxMessageBox("无法打开摄像头"); return; } //writer=cvCreateVideoWriter("MyVideo.avi",CV_FOURCC('x','v','I','D'),25,cvSize(640,480)); // 测试 IplImage* m_Frame; m_Frame=cvQueryFrame(capture); CvvImage m_CvvImage; m_CvvImage.CopyOf(m_Frame,1); if (true) { m_CvvImage.DrawToHDC(hDC, &rect); //cvWaitKey(10); } // 设置计时器,每10ms触发一次事件 SetTimer(1,10,NULL); cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); // 加载分类器 if( !cascade ) { MessageBox("无法加载分类器文件,请确认!"); } storage = cvCreateMemStorage(0); // 创建内存存储器 //if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') ) // 判断输入参数是视频序号,还是文件 capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' ); // 创建视频读取结构 /* else if( input_name ) { image = cvLoadImage( input_name, 1 ); // 如果是图像则加载 if( !image ) { capture = cvCaptureFromAVI( input_name ); // 不是图像则尝试视频读取 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640); cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480); //////////////////////////////////////////////////////////////////// } }*/ //else // image = cvLoadImage( "lena.bmp", 1 ); //都没有则调用程序所在目录的lena.jpg图片 //cvNamedWindow( "result", 1 ); GetDlgItem(IDC_BUTTON1)->EnableWindow(false); GetDlgItem(IDC_BUTTON2)->EnableWindow(true); GetDlgItem(IDC_Photograph)->EnableWindow(true); GetDlgItem(IDC_Recognize)->EnableWindow(true); bool_detec_reco = false; bool_cameOpen = true; } /********************************************设置定时器*********************************************/ void CVideoMFCDlg::OnTimer(UINT_PTR nIDEvent) { //显示摄像头 IplImage* m_Frame; m_Frame=cvQueryFrame(capture); //AllocConsole(); //判断是检测还是识别人脸 if(bool_cameOpen) { if(!bool_detec_reco)//false只为识别 { detect_and_draw(m_Frame);//检测人脸 //_cprintf("%s\n", "jiance"); } else if(bool_picNum)//false代表训练图片为空 recog_and_draw(m_Frame);//检测和识别人脸 } CvvImage m_CvvImage; m_CvvImage.CopyOf(m_Frame,1); if (true) { m_CvvImage.DrawToHDC(hDC, &rect); //cvWriteFrame(writer,m_Frame); //将帧图像通过writer写入文件 //cvWaitKey(10); } if(bool_detec_reco) { if(predictedLabel <= dConfidence) { CString tipPhoto = strTip + "\r\n验证成功!!"; pTip->SetWindowText( tipPhoto ); } else { CString tipPhoto = strTip + "\r\n验证失败!!"; pTip->SetWindowText( tipPhoto ); } } CDialogEx::OnTimer(nIDEvent); } //关闭摄像头按钮 void CVideoMFCDlg::OnBnClickedButton2() { // TODO: Add your control notification handler code here cvReleaseVideoWriter(&writer); cvReleaseCapture(&capture); CDC MemDC; CBitmap m_Bitmap1; m_Bitmap1.LoadBitmap(IDB_BITMAP1); MemDC.CreateCompatibleDC(NULL); MemDC.SelectObject(&m_Bitmap1); pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,0,0,48,48,SRCCOPY); GetDlgItem(IDC_BUTTON1)->EnableWindow(true); GetDlgItem(IDC_BUTTON2)->EnableWindow(false); GetDlgItem(IDC_Photograph)->EnableWindow(false); GetDlgItem(IDC_Recognize)->EnableWindow(false); bool_cameOpen = false; } //关闭窗体 void CVideoMFCDlg::OnClose() { // TODO: Add your message handler code here and/or call default cvReleaseCapture(&capture); CDialogEx::OnClose(); } void CVideoMFCDlg::OnEnChangeEdtconfidence() { } //拍照按钮 void CVideoMFCDlg::OnBnClickedPhotograph() { // TODO: 在此添加控件通知处理程序代码 if (!faceGray) { pTip->GetWindowText(strTip); CString tipPhoto = strTip + "\r\n拍照失败,请将摄像头对准人脸"; pTip->SetWindowText( tipPhoto ); return; } Mat img(faceGray,0); stringstream ss; ss << (read_img_number()+1); string faceImgName = "..//einfacedata//trainingdata//"+ss.str()+".jpg"; imwrite(faceImgName,img); //pTip->GetWindowText(strTip); CString tipPhoto = strTip + "\r\n拍照成功!已存为" + ("/einfacedata/trainingdata/"+ss.str()+".jpg").c_str(); pTip->SetWindowText( tipPhoto ); //MessageBox("OK"); } //开始验证按钮 void CVideoMFCDlg::OnBnClickedRecognize() { // TODO: 在此添加控件通知处理程序代码 images.clear(); labels.clear(); pEdtConfidence->GetWindowText(strConfidence); try { dConfidence = atoi((const char *)strConfidence); } catch(cv::Exception &e) { MessageBox("置信度请输入整数!"); return; } model->set("threshold", dConfidence); //string output_folder; //output_folder = string("../einfacedata"); //读取你的CSV文件路径 //string fn_csv = string("../einfacedata/at.txt"); //两个容器来存放图像数据和对应的标签 /* try { read_csv(fn_csv, images, labels); } catch(cv::Exception &e) { cerr<<"Error opening file "<<fn_csv<<". Reason: "<<e.msg<<endl; exit(1); } */ if(!read_img(images, labels)) { AfxMessageBox("Error in reading images!"); //MessageBox("Error in reading images!"); images.clear(); labels.clear(); return; } //如果没有读到足够的图片,就退出 if(images.size() < 1) { MessageBox("This demo needs at least 1 images to work!"); return; } //training model->train(images, labels); bool_detec_reco = true; bool_picNum = true; } //清除训练图片 void CVideoMFCDlg::OnBnClickedClearpictures() { // TODO: 在此添加控件通知处理程序代码 if(delete_img()) { //pTip->GetWindowText(strTip); CString tipPhoto = strTip + "\r\n删除成功!"; pTip->SetWindowText( tipPhoto ); bool_detec_reco = false; bool_picNum = false; } else { //pTip->GetWindowText(strTip); CString tipPhoto = strTip + "\r\n删除失败!"; pTip->SetWindowText( tipPhoto ); } }
detect_recog.cpp和上一篇博客类似
#include "stdafx.h" #include "cv.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <math.h> #include <float.h> #include <limits.h> #include <time.h> #include <ctype.h> #include "detect_recog.h" #include <opencv2\contrib\contrib.hpp> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <iostream> #include <fstream> #include <sstream> #include <stdio.h> #include <io.h> #include <direct.h> #include <sys/types.h> #include <conio.h> using namespace std; using namespace cv; void detect_and_draw( IplImage* img ) // 只是检测,并圈出人脸 { static CvScalar colors[] = { {{0,0,255}}, {{0,128,255}}, {{0,255,255}}, {{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}} }; IplImage *gray, *small_img; int i, j; gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); cvCvtColor( img, gray, CV_BGR2GRAY ); // 彩色RGB图像转为灰度图像 cvResize( gray, small_img, CV_INTER_LINEAR ); cvEqualizeHist( small_img, small_img ); // 直方图均衡化 cvClearMemStorage( storage ); if( cascade ) { double t = (double)cvGetTickCount(); CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT |CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(30, 30) ); t = (double)cvGetTickCount() - t; // 统计检测使用时间 //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); // 将faces数据从CvSeq转为CvRect CvMat small_img_roi; CvSeq* nested_objects; CvPoint center,recPt1,recPt2; CvScalar color = colors[i%8]; // 使用不同颜色绘制各个face,共八种色 int radius; center.x = cvRound((r->x + r->width*0.5)*scale); // 找出faces中心 center.y = cvRound((r->y + r->height*0.5)*scale); recPt1.x = cvRound((r->x)*scale); recPt1.y = cvRound((r->y)*scale); recPt2.x = cvRound((r->x + r->width)*scale); recPt2.y = cvRound((r->y + r->height)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvGetSubRect( small_img, &small_img_roi, *r ); IplImage *result; CvRect roi; roi = *r; result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels ); cvSetImageROI(img,roi); // 创建子图像 cvCopy(img,result); cvResetImageROI(img); //IplImage *resizeRes; CvSize dst_cvsize; dst_cvsize.width=(int)(100); dst_cvsize.height=(int)(100); resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels); cvResize(result,resizeRes,CV_INTER_NN); faceGray = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);//创建目标图像 cvCvtColor(resizeRes,faceGray,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY) cvShowImage( "resize", resizeRes ); cvRectangle(img,recPt1,recPt2,color,1, 8,0); //rectangle(img,recPt1,recPt2,color,1,8,0); //cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域 if( !nested_cascade ) continue; nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(0, 0) ); for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ ) { CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j ); center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); radius = cvRound((nr->width + nr->height)*0.25*scale); cvCircle( img, center, radius, color, 3, 8, 0 ); } } } //cvShowImage( "result", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img ); } //检测并识别人脸,并在每帧图片上写入结果 void recog_and_draw( IplImage* img ) { static CvScalar colors[] = { {{0,0,255}}, {{0,128,255}}, {{0,255,255}}, {{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}} }; IplImage *gray, *small_img; int i, j; gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); cvCvtColor( img, gray, CV_BGR2GRAY ); // 彩色RGB图像转为灰度图像 cvResize( gray, small_img, CV_INTER_LINEAR ); cvEqualizeHist( small_img, small_img ); // 直方图均衡化 cvClearMemStorage( storage ); if( cascade ) { double t = (double)cvGetTickCount(); CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH |CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(30, 30) ); t = (double)cvGetTickCount() - t; // 统计检测使用时间 //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); // 将faces数据从CvSeq转为CvRect CvMat small_img_roi; CvSeq* nested_objects; CvPoint center,recPt1,recPt2; CvScalar color = colors[i%8]; // 使用不同颜色绘制各个face,共八种色 int radius; center.x = cvRound((r->x + r->width*0.5)*scale); // 找出faces中心 center.y = cvRound((r->y + r->height*0.5)*scale); recPt1.x = cvRound((r->x)*scale); recPt1.y = cvRound((r->y)*scale); recPt2.x = cvRound((r->x + r->width)*scale); recPt2.y = cvRound((r->y + r->height)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvGetSubRect( small_img, &small_img_roi, *r ); IplImage *result; CvRect roi; roi = *r; result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels ); cvSetImageROI(img,roi); // 创建子图像 cvCopy(img,result); cvResetImageROI(img); //IplImage *resizeRes; CvSize dst_cvsize; dst_cvsize.width=(int)(100); dst_cvsize.height=(int)(100); resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels); cvResize(result,resizeRes,CV_INTER_NN); faceGray = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);//创建目标图像 cvCvtColor(resizeRes,faceGray,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY) cvShowImage( "resize", resizeRes ); cvRectangle(img,recPt1,recPt2,color,3, 8,0); //cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域 Mat test = faceGray; //images[images.size() - 1] = test; model->train(images, labels); //predictedLabel = model->predict(test); double predicted_confidence = 0.0; model->predict(test,predictedLabel,predicted_confidence); stringstream strStream; strStream<<predicted_confidence; string ss = strStream.str(); cvText(img, ss.c_str(), r->x+r->width*0.5, r->y); if(predicted_confidence <= dConfidence) cvText(img, "Result:YES", 0, 30); else cvText(img, "Result:NO", 0, 30); //cout << "predict:"<<model->predict(test) << endl; //cout << "predict:"<< predictedLabel << "\nconfidence:" << predicted_confidence << endl; if( !nested_cascade ) continue; nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage, 1.1, 2, 0 //|CV_HAAR_FIND_BIGGEST_OBJECT //|CV_HAAR_DO_ROUGH_SEARCH //|CV_HAAR_DO_CANNY_PRUNING //|CV_HAAR_SCALE_IMAGE , cvSize(0, 0) ); for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ ) { CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j ); center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); radius = cvRound((nr->width + nr->height)*0.25*scale); cvCircle( img, center, radius, color, 3, 8, 0 ); } } } //cvShowImage( "result", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img ); } void cvText(IplImage* img, const char* text, int x, int y) { CvFont font; double hscale = 1.0; double vscale = 1.0; int linewidth = 2; cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,hscale,vscale,0,linewidth); CvScalar textColor =cvScalar(0,255,255); CvPoint textPos =cvPoint(x, y); cvPutText(img, text, textPos, &font,textColor); } Mat norm_0_255(cv::InputArray _src) { Mat src = _src.getMat(); Mat dst; switch(src.channels()) { case 1: cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1); break; case 3: cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3); break; default: src.copyTo(dst); break; } return dst; } void read_csv(const string &filename, vector<Mat> &images, vector<int> &labels, char separator) { std::ifstream file(filename.c_str(), ifstream::in); if(!file) { string error_message = "No valid input file was given."; CV_Error(CV_StsBadArg, error_message); } string line, path, classlabel; while(getline(file, line)) { stringstream liness(line); getline(liness, path, separator); //遇到分号就结束 getline(liness, classlabel); //继续从分号后面开始,遇到换行结束 if(!path.empty() && !classlabel.empty()) { images.push_back(imread(path, 0)); labels.push_back(atoi(classlabel.c_str())); } } } //实现了从trainningdata 目录下直接读取jpg文件作为训练集 bool read_img(vector<Mat> &images, vector<int> &labels) { long file; struct _finddata_t find; //AllocConsole(); string path = "..//einfacedata//trainingdata/"; char filepath[60]; //_chdir("..//einfacedata//trainingdata"); if((file=_findfirst("..//einfacedata//trainingdata/*.jpg", &find))==-1L) { AfxMessageBox("Cannot find the dir"); return false; } int i = 0; images.push_back(imread(path+find.name, 0)); labels.push_back(0); while(_findnext(file, &find)==0) { //_cprintf("%s\n", path+find.name); //_cprintf("%d\n", i++); images.push_back(imread(path+find.name, 0)); labels.push_back(0); } _findclose(file); return true; } //实现了从trainningdata 目录下读取jpg文件数目 int read_img_number() { long file; int i = 0; struct _finddata_t find; //AllocConsole(); string path = "..//einfacedata//trainingdata/"; char filepath[60]; if((file=_findfirst("..//einfacedata//trainingdata/*.jpg", &find))==-1L) return i; i++; while(_findnext(file, &find)==0) { i++; } _findclose(file); return i; } bool delete_img() { system( "del ..\\einfacedata\\trainingdata\\" ); return true; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持亿速云。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。