接着上一节,显示我们得到的灰度图像buffer(byte*),并且传递给人脸识别代码:
一,显示灰度图像buffer(byte*)
1,要显示,就要用gdi,头文件和库已经加载了,下面是在detectFace.h下声明:
public:
GdiplusStartupInput gdiplusInput;
ULONG_PTR gdiplusToken;
2,在detectFace.cpp的BOOL CdetectFaceApp::InitInstance()函数中启动gdi:
/////////////////////////
::GdiplusStartup(&gdiplusToken,&gdiplusInput,NULL);
3,在detectFace.cpp的int CdetectFaceApp::ExitInstance()函数中关闭gdi://程序退出时
/////////////////
GdiplusShutdown(gdiplusToken);
4,在IDC_STATIC_PIC控件中显示灰度图像buffer(byte*)
a,使用这样一个类class CPicZoom : public CWnd{......省略了mfc自己生成的代码}
b,新添加一个IDC_STATIC_PIC控件()变量(默认),如此替换他://vs2010 vc++
public: CPicZoom m_Pic;// public: CStatic m_Pic;
void CdetectFaceDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_PIC, m_Pic);
}
5,在m_pic的onpaint函数中显示图像:
void CPicZoom::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CWnd::OnPaint()
CdetectFaceDlg *pm=(CdetectFaceDlg *)::AfxGetMainWnd ();
if(pm->m_bcopyed)
{
Graphics graph(dc.m_hDC);
Bitmap bitmap(640,
480,
640*3 ,
PixelFormat24bppRGB,
pm->m_buffer8dst);
graph.DrawImage(&bitmap,0, 0);
}
}
二,传递给人脸识别代码:
1,人脸识别的头文件和库要拷贝到项目目录下,stdafx.h已经正确加载。
2,人脸识别需要加载的.xml文件,opencv有提供,拷贝过来放在目录下,声明为全局变量。
const char* cascade_name = "haarcascade_frontalface_alt.xml";
const char* nested_cascade_name =
"C:\\Program Files\\OpenCV\\data\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml";
3,人脸识别代码:
使用timer定时器调用它:void CdetectFaceDlg::OnTimer(UINT_PTR nIDEvent)
{
if(2==nIDEvent)//程序初始化时,启动timer2.
{
OnBnClickedBtFacedetect2();
if(b_isface){
//这里可以打开继电器了201911102109
// usb_relay_init();//放到程序初始化中去
// struct usb_relay_device_info *device_info = usb_relay_device_enumerate();//放到程序初始化中去
m_hCurDevice= usb_relay_device_open(device_info); //打开继电器
usb_relay_device_open_one_relay_channel(m_hCurDevice, 1); //打开继电1
b_isface=false;
}
}
}
////////////////////////////////////
void CdetectFaceDlg::OnBnClickedBtFacedetect2()
{
// TODO: 在此添加控件通知处理程序代码
nestedCascade = (CvHaarClassifierCascade*)cvLoad( nested_cascade_name, 0, 0, 0 );
Cascade=(CvHaarClassifierCascade*) cvLoad( cascade_name, 0,0,0);
////////////
pTest24byte=cvCreateImage(cvSize(640,480),8,3);//使用了24位灰度图像
cvSetData(pTest24byte,m_buffer8dst,640*3);//测试成功ok201911101905
//////////////////pTestgrey
pTestgrey = cvCreateImage( cvSize(pTest24byte->width,pTest24byte->height),
IPL_DEPTH_8U, pTest24byte->nChannels );
cvCopy( pTest24byte, pTestgrey, 0 );
if(Cascade)
{
//CvMemStorage*
storage=cvCreateMemStorage(0);
cvNamedWindow("人脸检测",1);
if(pTestgrey)
{
detect_and_drawSE(pTestgrey);//最后一句opencv异常,使用24位图像后正常
}
cvReleaseImage(&pTestgrey);
cvReleaseMemStorage(&storage);
}
cvReleaseHaarClassifierCascade(&Cascade);
}
/////////////////////////////////
void CdetectFaceDlg::detect_and_drawSE(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}}
};
double scale=1.3;
IplImage* gray=cvCreateImage(cvSize(img->width,img->height),8,1);
IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1);
int i;
cvCvtColor(img,gray,CV_BGR2GRAY);//变为opencv自己想要的灰度图像
cvResize(gray,small_img,CV_INTER_LINEAR);
cvEqualizeHist(small_img,small_img);//直方图均衡化
cvClearMemStorage(storage);
if(Cascade)
{
//CvSeq* faces=cvHaarDetectObjects(small_img,Cascade,storage,1.1,2,0,cvSize(640,480));
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//可以坎尼(canny)
// |CV_HAAR_SCALE_IMAGE
,
cvSize(30, 30) );
if(faces->total>=1){b_isface=true;}//找到人脸
for(i=0;i<(faces?faces->total:0);i++)//脸上画圆
{
CvRect* r=(CvRect*)cvGetSeqElem(faces,i);
CvPoint centre;
int radius;
centre.x=cvRound((r->x+r->width*0.5)*scale);
centre.y=cvRound((r->y+r->height*0.5)*scale);
radius=cvRound((r->width+r->height)*0.25*scale);
cvCircle(img,centre,radius,colors[i%8],3,8,0);
}
cvShowImage("人脸检测",img);
cvReleaseImage(&gray);
cvReleaseImage(&small_img);
}
}
三,usb免驱继电器开关不再列篇介绍了,这里顺便说明一下:
1,拷贝usb_relay_device.lib和usb_relay_device.dll及usb_relay_device.h三个文件到项目目录下。
2,stdafx.h已经加载,你也看到,在前一篇。
3,然后在oninitdialog()中初始化继电器:
usb_relay_init();//放到程序初始化中去
struct usb_relay_device_info *device_info = usb_relay_device_enumerate();//放到程序初始化中去
4,有人脸时,bool值为true,打开继电器。代码上面有,已经写入。
5,程序退出或者没有人脸时bool值为false,关闭继电器。
usb_relay_device_close_one_relay_channel(m_hCurDevice, 1);//关闭继电器1
usb_relay_device_close(m_hCurDevice);
6,m_hCurDevice是int类型的。
加油,c#代码也快了,期待中..........
待续(慢慢来!...........)每天一点小改变☺