人脸识别已经遇到好几年了(2013),在opencv中,今天终于抄过来了,发现不完美,但以后可以慢慢改进,家里先用上再说,干什么?开关灯呗,在工作上,程序驱动开关,已经不算什么,但对于家用,可以激活父母孩子的好奇心,时代嘛,应该是老百姓的嘛!电脑有了,摄像头有了,不可能再花个电脑的价钱买个开关吧(机器视觉的开关好贵啊!)?某宝淘到一个usb继电器开关(不到十五元),有硬件,有源代码,可以二次开发,可以尝试一把,走起!多好的一个时代啊!
电脑摄像头的代码有了!
opencv的人脸识别代码有了!
usb继电器开关代码也有了!
把他装起来,硬件和软件,diy(do it yourself!),看到这些字,一些青春年华做过的事,又从眼前飘过,多么熟悉啊!沉淀的岁月,就剩下这几个字,这种影响,成为习惯,深入骨髓,那么,借此,就继续发扬和传承下去!
这一次使用visual c++,关于c#,就剩opencv的人脸识别代码翻译工作了,等待完成,还是那句话,c++可以搞定的,c#不在话下!是不是有点那个?二!
vs2010用c++写程序都快吐了,函数一点提示都没有,还好完成了,vs2013使用c++好多了,就像又回到vs2005下的c++时代,我们废话少说,先上摄像头代码:
1,在stdafx.h中:
#include "cv.h"
#include"highgui.h"//以上使用opencv1.0人脸识别需要使用的
#include
#pragma comment(lib,"vfw32")
#include
using namespace Gdiplus;
#pragma comment(lib,"gdiplus")//以上是摄像头需要使用的库和头文件
#include "usb_relay_device.h"
#pragma comment(lib, "usb_relay_device.lib")//以上是usb继电器开关需要使用的库和头文件//
需要说明的是,你需要安装opencv1.0(网上下载一个,十几mbytes,很小),usb继电器开关的库和头文件,购买时会提供你下载地址(看似很多的代码,吓人一大跳!一只纸老虎,关键代码就几句,想起了那个opt的串口光源控制器,价格不菲啊!关键要学会读懂人家说明书!)。
2,摄像头取像:因为人脸识别时,会显示图像,所以设置图像显示为disabled,另外你传递给人脸识别的图像buffer,也有显示,为了验证这个图像buffer是否ok,他已经变换为灰度图:
BOOL CdetectFaceDlg::OnInitDialog()
{
CDialog::OnInitDialog();
.............省略了mfc自己生成的代码
CWnd *pCarryWnd=this->GetDlgItem(IDC_STATIC_ADD);//IDD_DETECTFACE_DIALOG
CRect rect;
pCarryWnd->GetClientRect(&rect);
this->m_hCamWnd=capCreateCaptureWindow("MY CAM",WS_CHILD|WS_DISABLED,0,0,rect.Width(),rect.Width(),pCarryWnd->GetSafeHwnd(),0);
if(!capDriverConnect(m_hCamWnd,0))//win7和win8.1下: while (capDriverConnect(m_hCamWnd,0)!=true)
{return true;}///////////////////////////////////////// win7和win8.1下: { continue;}
CAPDRIVERCAPS cpas;
capDriverGetCaps(m_hCamWnd,sizeof(cpas),&cpas);
if(cpas.fCaptureInitialized)
{
capPreviewRate(m_hCamWnd,25);
capPreview(m_hCamWnd,true);
SetTimer(1,100,0); ////计时器
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
3,在计时器中void CdetectFaceDlg::OnTimer(UINT_PTR nIDEvent),把图像buffer(byte*)取出来给人脸识别用(这里边使用了剪贴板技术,虽然笨,但通关了)(虽然现在进步了,曾经不敢忘):
if(1==nIDEvent)
if(capCaptureSingleFrameOpen(m_hCamWnd))
{
//成功则捕捉
if(capCaptureSingleFrame(m_hCamWnd))
{
//捕捉成功则关闭
if(capCaptureSingleFrameClose(m_hCamWnd))
{
if(capGrabFrameNoStop(m_hCamWnd))//////////////////////
{
capEditCopy(m_hCamWnd);
EmptyClipboard();
CloseClipboard();
if(IsClipboardFormatAvailable(CF_DIB))//vfw只能提供640*480的图像
{
if(OpenClipboard())
{
GLOBALHANDLE hGMem;
LPBITMAPINFO lpbi;
byte * pdibBits;
hGMem=GetClipboardData(CF_DIB);
lpbi=(LPBITMAPINFO)GlobalLock(hGMem);
pdibBits=(byte*)(lpbi+1);
for(int i=479;i>=0;i--)
{
for(int j=0;j<640;j++)
{
m_buffer[i*640*4+j*4]=*pdibBits;
pdibBits++;
m_buffer[i*640*4+j*4+1]=*pdibBits;
pdibBits++;
m_buffer[i*640*4+j*4+2]=*pdibBits;
pdibBits++;
m_buffer[i*640*4+j*4+3]=128;
}
}
for(int j=0;j<480;j++)//我电脑的摄像头是颠倒的图像,下面代码针对它,进行了翻转。
for(int i=0;i<640;i++)
{
int n=j*640+i;
int m=(480-j-1)*640+i;
byte tempbt=(byte)(m_buffer[4*m]*0.3+m_buffer[4*m+1]*0.59+m_buffer[4*m+2]*0.11);
m_buffer8org[n]=tempbt;
/*m_buffer8org[j*640+i]=pm->m_buffer[4*m];*/
//当初只取了蓝色通道,翻转了180度,图像出来了,8位图像在c++下很搞怪,想起曾经这样过。201911101838
m_buffer8dst[3*n]=tempbt;
m_buffer8dst[3*n+1]=tempbt;
m_buffer8dst[3*n+2]=tempbt;
}//正确的方法是,显示要大于24位,即使8位图像
this->m_bcopyed=true;
this->m_Pic.Invalidate();
GlobalUnlock(hGMem);
CloseClipboard();
}
}
}
}
}
}
摄像头技术讲完了,对比c#,真是繁琐复杂,困难重重。下一节我们使用人脸识别。
待续(慢慢来!...........)每天一点小改变☺
我的邮箱[email protected];[email protected]