我们来详细讲解一下“基于OpenCV读取摄像头实现单个人脸验证MFC程序”的完整攻略。
1. 确定开发环境
首先,确定使用的开发环境和所需的库文件。本攻略选用以下开发环境:
- Windows 10 操作系统
- Visual Studio 2017 集成开发环境
- OpenCV 4.0.0 库文件
2. 创建MFC项目
接下来,创建一个MFC项目。在Visual Studio中选择“文件” > “新建” > “项目”,在弹出的“新建项目”对话框中选择“MFC应用程序”类型,填写项目名称和保存路径等信息,最后点击“确定”按钮即可。
3. 配置OpenCV库
在创建好MFC项目后,我们需要将OpenCV库文件添加到项目中。
-
下载OpenCV 4.0.0库文件,并解压到本地任意目录下。
-
在Visual Studio中,选择“项目” > “属性” > “VC++目录”,在“包含目录”中添加解压后的OpenCV库文件夹路径(如:D:\opencv\build\include),并在“库目录”中添加OpenCV库文件夹路径下lib文件夹的路径(如:D:\opencv\build\x64\vc14\lib)。
-
在“链接器” > “输入”中,添加需要链接的OpenCV库文件名称,包括opencv_world400.lib和opencv_world400d.lib两个文件(其中400表示OpenCV版本号),并在“忽略特定库”中添加“libcmt.lib”库。
4. 编写MFC程序
接下来,我们就可以开始编写MFC程序实现基于OpenCV读取摄像头实现单个人脸验证了。首先,在主界面上创建一个画布,用来显示摄像头捕获的画面。
// MFC程序主界面类
class CMyCameraDlg : public CDialogEx
{
public:
CMyCameraDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MYCAMERA_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 用于OpenCV读取摄像头
cv::VideoCapture m_cap;
// 显示画面的画布
CStatic m_frame;
// 确定ROI区域
cv::Rect m_roi;
bool m_draw = false;
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
};
接着,在OnInitDialog函数中,初始化摄像头和画布,并启动摄像头刷新线程循环读取画面,并通过opencv检测人脸,并选取ROI区域。
BOOL CMyCameraDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 初始化图标
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
// 初始化画布
m_frame.Attach(GetDlgItem(IDC_FRAME)->GetSafeHwnd());
// 初始化摄像头
m_cap.open(0);
if (!m_cap.isOpened())
AfxMessageBox(_T("无法打开摄像头!"));
else
{
// 启动摄像头线程
AfxBeginThread(CMyCameraDlg::ThreadProc, this, THREAD_PRIORITY_NORMAL);
}
return TRUE; // 返回 TRUE 以便进行聚焦设置
}
UINT CMyCameraDlg::ThreadProc(LPVOID lParam)
{
CMyCameraDlg* dlg = (CMyCameraDlg*)lParam;
cv::Mat frame;
cv::Mat gray;
// 调整摄像头分辨率
dlg->m_cap.set(cv::CAP_PROP_FRAME_WIDTH, 320);
dlg->m_cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240);
// 读取画面并进行处理
while (1)
{
dlg->m_cap.read(frame);
if (frame.empty())
break;
// 转为灰度图
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
// 检测人脸,选取ROI区域
if (dlg->m_draw)
{
cv::rectangle(frame, dlg->m_roi, cv::Scalar(0, 0, 255), 2);
gray(dlg->m_roi).copyTo(gray);
}
// 将检测到的图像显示到画面上
dlg->m_frame.SetBitmap(dlg->Mat2Bitmap(frame));
}
return 0;
}
通过以上代码,我们已经可以成功读取摄像头并在画面上实时显示了。接下来,我们添加单个人脸验证的代码。
void CMyCameraDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 缩小图标到客户区矩形中心。
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
// 在画面上显示检测结果
CString strResult = DetectFace()?_T("验证通过"):_T("验证失败");
CClientDC dc(&m_frame);
dc.TextOutW(10, 10, strResult);
}
}
最后,我们需要实现通过OpenCV检测人脸,并采用人脸关键点识别和模板匹配进行单个人脸验证的功能。
// 通过OpenCV检测人脸,并进行人脸关键点识别和模板匹配进行单个人脸验证
bool CMyCameraDlg::DetectFace()
{
cv::Mat frame;
cv::Mat gray;
cv::Mat face;
// 读取画面
m_cap.read(frame);
if (frame.empty())
return false;
// 转为灰度图
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
// 检测人脸
std::vector<cv::Rect> faces;
m_faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, cv::Size(30, 30), cv::Size(200, 200));
// 如果检测到多个人脸或没有检测到人脸则返回false
if (faces.size() != 1)
return false;
// 保存人脸ROI区域并进行人脸关键点识别
cv::Point2f src[4], dst[4];
src[0] = cv::Point2f(faces[0].x, faces[0].y);
src[1] = cv::Point2f(faces[0].x + faces[0].width, faces[0].y);
src[2] = cv::Point2f(faces[0].x, faces[0].y + faces[0].height);
src[3] = cv::Point2f(faces[0].x + faces[0].width, faces[0].y + faces[0].height);
dst[0] = cv::Point2f(0, 0);
dst[1] = cv::Point2f(70, 0);
dst[2] = cv::Point2f(0, 90);
dst[3] = cv::Point2f(70, 90);
cv::Mat map_matrix = cv::getPerspectiveTransform(src, dst);
cv::warpPerspective(gray, face, map_matrix, cv::Size(70, 90));
std::vector<cv::Point2f> landmarks = m_landmarkDetector.Detect(face);
// 通过模板匹配确定是否为指定人脸
cv::Mat feature = m_featureExtractor.Extract(face, landmarks);
double distance = m_faceDatabase.CalcDistance(feature, m_specifiedFaceFeature);
return distance < m_threshold;
}
以上就是基于OpenCV读取摄像头实现单个人脸验证MFC程序的完整攻略。其中,我们通过OpenCV读取摄像头并实时显示画面,并采用人脸关键点识别和模板匹配进行单个人脸验证的功能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于OpenCV读取摄像头实现单个人脸验证MFC程序 - Python技术站