OpenCV人脸检测与简单的距离计算

文章目录

  • 运行环境
  • 实验目的
  • 一、环境配置
  • 二、代码部分
    • 1.添加头文件
    • 2.代码部分
      • 1.Face_Detection()函数
      • 2.main()函数
  • 三、流程描述
  • 四、结果展示
  • 总结


运行环境

Windows10+VS2019+OpenCV4.4.0+C++


实验目的

利用OpenCV库对视频流进行分析,找到人脸位置并简单地计算人脸与屏幕的距离。

一、环境配置

使编译器能够检测并使用OpenCV库
B站OpenCV4+VS2019配置方法

二、代码部分

1.添加头文件

#include      
#include 
#include       //载入dnn模块
#include                 //用于数学计算(可不需要)
using namespace cv;
using namespace std;

void Face_Detection();          //人脸检测函数

2.代码部分

TIPS:对代码的解释都在注释之中,但是完全复制应该可以直接运行

分为Face_Detection()函数部分和main()函数部分


1.Face_Detection()函数

void Face_Detection()//人脸识别
//使用函数之前请确定头文件中是否加入     #include
{
	VideoCapture capture(0);//读取摄像头
	//也可以读取一段视频如:  "test.mp4"
	//还可以利用网络摄像头ip输入如: "http://admin:[email protected]:8081"
	
	Mat frame;                                 //输出的图像
	namedWindow("FACE", WINDOW_FREERATIO);     //显示结果的窗口
	
	int x1 = 0, x2 = 0,y1 = 0, y2 = 0;         //创建box用于选中人脸区域
	Rect box(x1,y1,x2-x1,y2-y1);               //box的重载类型为(顶点X坐标,顶点Y坐标,长,高)
	
	float  distance=0.0;                       //创建distance用于存放人脸到屏幕的距离
	


//博主将opencv_face_detector_uint8.pb 和 opencv_face_detector.pbtxt 复制进入了项目文件夹,所以使用的是绝对路径。
//而如果不复制文件则需要将下面三行写入代码重写。(第一行的省略标记为OpenCV的安装地址,每个人不相同使用”...“代替)

/*string root_dir("D:.../sources/samples/dnn/face_detector/");
dnn::Net net= cv::dnn::readNetFromTensorflow(root_dir +
"opencv_face_detector_uint8.pb",root_dir + "opencv_face_detector.pbtxt");*/


dnn::Net net = cv::dnn::readNetFromTensorflow("opencv_face_detector_uint8.pb", "opencv_face_detector.pbtxt");
//创建网络类net,将需要检测的模型输入net(本篇文章为opencv_face_detector即人脸模型)
//.pb文件是由Tensorflow生成的模型;  .pbtxt文件是为.pb文件的配置文件。这些都是由他人训练好的模型。
	while (1)
	{
		capture.read(frame); 
		
		if (frame.empty()) { break; }   //视频结束则退出
		
		//flip(frame, frame, 1);        //电脑摄像头镜像(未使用)
		
		Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300),
		 Scalar(104, 117, 123), false, false);
		//图像预处理:(,缩放值,学习是预设的大小,每个通道减去的值,RB通道是否交换,,)
		//处理具体要求前往D:...\sources\samples\dnn\model.yml  中查看

		net.setInput(blob);             //将处理的结果返回给网络文件
		
		Mat prob = net.forward();       //NCHW  
		/*向传播结果是一个四维矩阵prob,第一维是输入图像编号、第二维是输入图像数量、
		第三维是检测的每个目标、第四维是每个目标的信息,包含类别ID、置信度、
		目标框的左上角和右下角坐标点等,其中坐标是该点相对于图像宽高的比例。*/
	
	                            /*解析结果*/
		Mat detentionMat(prob.size[2], prob.size[3],CV_32F, prob.ptr<float>());
		/*这里我们只需要prob的后两个维度的数据就可以了,所以我们对其重构*/
		
		for (int i = 0; i < detentionMat.rows; i++)     //每一排就是一组信息
		{  
			float confidence = detentionMat.at<float>(i, 2);
				
			if (confidence> 0.8)//confidence的值代表这幅图像的得分,越接近1与模型越相似
			{    
			
			/* detentionMat.at(i, 3~6) 的生成值都为float型0~1之间的数,
			   想要求出框在图像中的大小就必需去乘以他们的宽高,
			   为了计算的方便利用static_cast标准转型将其转换为int型数值
			 */
				 x1 = static_cast<int>(detentionMat.at<float>(i, 3) * frame.cols);
				 y1 = static_cast<int>(detentionMat.at<float>(i, 4) * frame.rows);
				 x2 = static_cast<int>(detentionMat.at<float>(i, 5) * frame.cols);
				 y2 = static_cast<int>(detentionMat.at<float>(i, 6) * frame.rows);
				 
				 box.x = x1; box.y = y1; box.width =( x2 - x1); box.height= (y2 - y1);
				rectangle(frame, box, Scalar(0, 255, 0), 1,4);//将数据写入box中并绘制图像
				
				// 需要头文件才  #include  才可以写出以下式子
				distance = -64.39 * log(box.height) + 413.26;    //EXCEL生成的函数
				//距离与人脸像素的函数模型,对于不同的设备,参数都不一样,式子不可通用,
				//如需实际使用需自己计算
				//(这个式子在笔记本电脑的渣摄像头中 40~110cm距离下比较准确)
				
				std::cout << "\r" << "距离屏幕的的大致距离为:(cm)" <<  distance;
			}
		}
		imshow("FACE", frame);                            //显示结果
		int KEY = waitKey(1);
		if (KEY == 27|| KEY == 'e') { break; }            //按下键盘 E 或  ESC键退出
	}
	capture.release();                                  
}

2.main()函数

#include      
#include 
#include         //载入dnn模块
#include                  //用于数学计算(可不需要)
using namespace cv;
using namespace std;

void Face_Detection();           //人脸检测函数

int main()
{   
    Face_Detection();           //直接调用函数
	waitKey(0);
	destroyAllWindows;
	return 0;

}

三、流程描述

流程中的关键操作

OpenCV人脸检测与简单的距离计算_第1张图片

四、结果展示

笔记本摄像头的测试


转换为手机摄像头的测试OpenCV人脸检测与简单的距离计算_第2张图片
(相机的不同会导致距离计算结果的不同),如需使用需重新计算。

总结

由于人脸模型已经被训练好了,这个实验难度在于对过程的理解,学习这个项目只需要了解每个类在做什么,函数的输入和返回值,容器内部是什么,就可以完成目的。

你可能感兴趣的:(opencv,c++,人脸识别)