C++课程设计日志(人脸识别+音视频播放器)

 这段代码实现了一个使用人脸识别进行登录的MFC(Microsoft Foundation Classes)对话框应用程序。应用程序通过摄像头捕获用户的面部图像,并与存储在本地的面部图像进行比较,以验证用户的身份。具体功能和工作流程如下:

### 主要功能

1. **界面初始化**:

   - 加载背景图片和按钮图片。

   - 初始化雪花动画效果。

   - 启动定时器以更新雪花动画。

2. **人脸识别**:

   - 使用 OpenCV 捕捉摄像头视频流。

   - 拍摄当前用户的照片并保存为临时文件 `tmp.jpg`。

   - 加载本地存储的用户面部图像,并与当前照片进行对比。

   - 如果识别成功,播放登录成功的声音,并提取用户信息。

3. **定时器事件**:

   - 处理雪花动画。

   - 定时刷新摄像头画面,进行拍照和人脸识别。

### 主要流程

1. **初始化对话框**(`OnInitDialog`):

   - 加载背景图片和按钮图片。

   - 初始化雪花效果并启动定时器。

2. **用户点击登录按钮**(`OnBnClickedButtonLogin`):

   - 停止雪花动画定时器。

   - 打开摄像头并启动捕捉画面。

   - 修改背景为幕布背景。

   - 启动定时器以捕捉摄像头画面。

3. **定时器事件处理**(`OnTimer`):

   - 更新雪花动画(ID 1)。

   - 捕捉摄像头画面并进行人脸识别(ID 2)。

4. **人脸识别(`faceCheck`)**:

   - 加载用户目录下的所有面部图像。

   - 与当前拍摄的照片进行比较。

   - 如果匹配度超过阈值(0.92),返回用户信息。

5. **处理识别结果**:

   - 如果识别成功,播放成功声音,提取并保存用户信息。

   - 如果识别失败,显示登录失败提示,并重新启动雪花动画定时器。

### 关键函数和代码块

- **`OnInitDialog`**:初始化对话框,加载图片和初始化控件。

- **`DoDataExchange`**:实现控件与数据成员之间的绑定。

- **`OnPaint`**:在对话框上绘制背景图片。

- **`faceCheck`**:进行人脸识别的核心函数。

- **`OnTimer`**:定时器事件处理函数,处理动画更新和人脸识别。

- **`OnBnClickedButtonLogin`**:处理登录按钮点击事件。

- **`OnStnClickedSnow` 和 `OnStnClickedPhotoReal`**:处理静态控件点击事件(未实现具体功能)。

这段代码通过摄像头捕捉用户面部图像,并与存储的面部图像进行比较,以实现人脸识别登录功能。同时,它还包含了定时器事件处理,用于动态更新界面效果(如雪花动画)。

下面是添加了详细注释的代码:

// WinLogin.cpp: 实现文件

#include "pch.h"
#include "MyFaceCheck.h"
#include "afxdialogex.h"
#include "WinLogin.h"
#include "opencv2/opencv.hpp"
#include "tools.h"
#include "mmsystem.h"
#pragma comment(lib, "winmm.lib")

#include "faceTool.h"
#include "WinWelcome.h"

#include <vector>
using namespace std;

extern MHandle faceModel; // 人脸识别模块

using namespace cv;

static VideoCapture cap; // 定义一个摄像头变量

// WinLogin 对话框

IMPLEMENT_DYNAMIC(WinLogin, CDialogEx)

WinLogin::WinLogin(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MYFACECHECK_LOGIN, pParent)
{

}

WinLogin::~WinLogin()
{
}

BOOL WinLogin::OnInitDialog()
{
	// 父类的初始化
	CDialogEx::OnInitDialog();

	// 自己的初始化
	LoadPicture(m_imgBG, IDB_PNG4); // 加载背景图片
	m_btnMouse.Init(IDB_PNG5, 4, BTN_TYPE_NORMAL); // 初始化登录按钮
	CString name;
	for (int i = 0; i < 16; i++) {
		// 加载雪花图片
		name.Format(L"res/snow/snow_%d.bmp", i);
		m_snows[i] = (HBITMAP)LoadImage(0, name, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	}

	// 启动定时器,用于更新雪花动画
	SetTimer(1, 30, NULL);

	// 移动雪花背景控件的位置和大小
	::MoveWindow(m_snowBG.m_hWnd, 440, 0, 640, 609, 1);

	return 0;
}

void WinLogin::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON_LOGIN, m_btnMouse); // 绑定登录按钮
	DDX_Control(pDX, IDC_SNOW, m_snowBG); // 绑定雪花背景控件
	DDX_Control(pDX, IDC_PHOTO_REAL, m_photo); // 绑定摄像头预览控件
}

BEGIN_MESSAGE_MAP(WinLogin, CDialogEx)
	ON_WM_PAINT() // 处理绘图消息
	ON_WM_TIMER() // 处理定时器消息
	ON_BN_CLICKED(IDC_BUTTON_LOGIN, &WinLogin::OnBnClickedButtonLogin) // 处理登录按钮点击事件
	ON_STN_CLICKED(IDC_SNOW, &WinLogin::OnStnClickedSnow) // 处理雪花背景点击事件
	ON_STN_CLICKED(IDC_PHOTO_REAL, &WinLogin::OnStnClickedPhotoReal) // 处理摄像头预览点击事件
END_MESSAGE_MAP()

// WinLogin 消息处理程序

void WinLogin::OnPaint()
{
	// 绘制背景图片
	drawPicOnPait(&m_imgBG, this, 0, 0);
}

bool faceCheck(const char* fileName, char* userName)
{
	vector<CString> vctPath;

	// 查找用户目录下所有.jpg文件
	WIN32_FIND_DATA fileData;
	HANDLE file = FindFirstFile(L"users/*.jpg", &fileData);
	if (file != INVALID_HANDLE_VALUE) {
		vctPath.push_back(fileData.cFileName);
		while (FindNextFile(file, &fileData)) {
			vctPath.push_back(fileData.cFileName);
		}
	}

	// 加载当前拍摄的照片
	IplImage* img1 = cvLoadImage(fileName);

	for (int i = 0; i < vctPath.size(); i++) {
		USES_CONVERSION;
		char* othername = T2A(vctPath[i]);
		char name[256];
		sprintf_s(name, sizeof(name), "users/%s", othername);
		IplImage* img2 = cvLoadImage(name);

		// 进行人脸比较
		float ret = faceCompare(faceModel, img1, img2);
		if (ret >= 0.92) {
			// 如果匹配成功,提取用户名
			string tmpStr = othername;
			string nameStr = tmpStr.substr(0, tmpStr.length() - 4); // 去掉.jpg
			strcpy(userName, nameStr.c_str());
			return true;
		}
	}

	return false;
}

void WinLogin::OnTimer(UINT_PTR nIDEvent)
{
	static int snowIndex = 0; // 雪花动画索引
	static int count = 0; // 计数器
	static char userName[256] = ""; // 用户名
	static bool success = false; // 登录成功标志

	if (nIDEvent == 1) {
		// 更新雪花动画
		m_snowBG.SetBitmap(m_snows[snowIndex]);
		snowIndex = (snowIndex + 1) % 16;
	}
	else if (nIDEvent == 2) {
		// 刷新摄像头画面
		refreshCamera(&cap, m_hWnd, IDC_PHOTO_REAL);
		count++;

		if (count == 10) {
			const char* fileName = "tmp.jpg";
			// 拍照并保存
			paiZhao(&cap, fileName);

			// 人脸识别
			if (faceCheck(fileName, userName)) {
				// 播放登录成功声音
				mciSendString(L"play res/login.mp3", 0, 0, 0);
				success = true;
			}
		}
		else if (count == 20) {
			count = 0;
			KillTimer(2); // 停止定时器
			cap.release(); // 释放摄像头

			if (success) {
				// 登录成功,提取用户信息
				strcpy(m_job, strtok(userName, "-"));
				strcpy(m_userName, strtok(NULL, "-"));
				m_yanZhi = atoi(strtok(NULL, "-"));
				m_logined = true;
				CDialogEx::OnOK(); // 关闭对话框
			}
			else {
				// 登录失败,显示提示信息
				MessageBox(L"登录失败!");
				SetTimer(1, 100, NULL); // 重新启动雪花动画定时器
				m_logined = false;
			}
		}
	}

	CDialogEx::OnTimer(nIDEvent); // 调用父类的定时器处理函数
}

void WinLogin::OnBnClickedButtonLogin()
{
	KillTimer(1); // 停止雪花动画定时器

	cap.open(0); // 打开摄像头

	// 修改雪花背景为幕布背景
	HBITMAP pic = (HBITMAP)LoadImage(0, L"res/wall.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
	m_snowBG.SetBitmap(pic);

	// 调整摄像头预览控件的位置和大小
	::MoveWindow(m_photo.m_hWnd, 440, 64, 640, 480, 1);

	SetTimer(2, 100, NULL); // 启动定时器以捕捉摄像头画面
}

void WinLogin::OnStnClickedSnow()
{
	// 空函数,用于处理雪花背景点击事件
}

void WinLogin::OnStnClickedPhotoReal()
{
	// 空函数,用于处理摄像头预览点击事件
}

### 注释内容

1. **头文件和全局变量**:简单介绍包含的头文件和定义的全局变量。

2. **`OnInitDialog` 函数**:对初始化对话框的操作进行详细注释,包括加载图片、初始化控件和启动定时器。

3. **`DoDataExchange` 函数**:注释数据交换绑定的控件。

4. **消息映射表**:说明各消息处理函数的用途。

5. **`OnPaint` 函数**:绘制背景图片。

6. **`faceCheck` 函数**:详细注释人脸识别的流程,包括加载本地图片、进行人脸比较和提取用户名。

7. **`OnTimer` 函数**:注释定时器事件处理的逻辑,包括更新动画和进行人脸识别。

8. **`OnBnClickedButtonLogin` 函数**:注释登录按钮点击后的操作,包括停止动画、打开摄像头和启动定时器。

9. **其他点击事件处理函数**:注释为空函数。

这样,所有关键步骤和函数都有详细的注释,便于阅读和理解代码的功能和流程。

  • 42
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值