Ubuntu下的Opencv识别人脸#采用百度智能云平台方案#人脸识别考勤机#C++

#简介:这是在ubuntu22.04里面使用opencv打开摄像头,通过摄像头获取图像并截取人脸图像,再将人脸图像转换成百度智能云平台所能接受的base64格式(当然也有其他格式),将base64格式的人脸图像发送给百度智能云,通过智能云平台的计算得到图像的匹配信息,本机接收到信息后对信息做处理。代码用C++格式,即人脸打卡考勤机的软件部分。

参考资料:

opencv官方在线文档:OpenCV documentation index

百度智能云——人脸识别:人脸识别_人脸识别_准确率99.99%_免费试用-百度AI开放平台

零、Opencv及百度智能云平台简介

1.Opencv简介

        opencv是一个开源的计算机视觉库,基于里面的代码可以轻松的处理各种图像,比如在本文中我们会用到opencv的代码来打开摄像头、拍摄图片、识别人脸、截取人脸区域、转换图像格式等。opencv兼容多个平台多种语言,这里我们将会在ubuntu中配置opencv并使用它。

2.百度智能云平台

        人脸识别是一个牵扯到人工智能的功能,需要的计算量十分庞大,而一个人脸识别考勤机没必要配置强大的硬件配置,于是可以借助云平台来处理AI相关的计算,通过云平台,我们的考勤机只需联网即可完成人脸识别的功能。

        AI相关计算既可以在云上进行,也可以离线部署,两种方式各有优劣。云计算可节省硬件成本,但有信息泄露的风险。离线部署虽然安全,但搭建成本高。

一、ubuntu下安装opencv

1.打开终端,输入指令。

sudo apt-get install libopencv-dev

 2.使用dpkg检查opencv安装状态。

dpkg -s libopencv-dev

3.新建文件夹

我这里在home下创建了一个All_Project用来存放项目代码。

4.安装图形化编辑器

有一个图形化编辑器写代码会方便很多,这里我使用的是Gedit

sudo apt-get install gedit

二、使用opencv打开摄像头

1.让摄像头连接到ubuntu中,在VMware中可管理设备的连接。

确保有摄像头连接到Ubuntu。

 在Ubuntu中可通过指令检查摄像头是否连接成功:

ls /dev

基于linux的万物皆文件的特性,dev这个文件夹存放的是设备文件,我们通过查看dev中是否有video文件来辨别摄像头的连接情况。图中的video0即是我的笔记本电脑的摄像头

2.写一个.cpp文件来打开摄像头

先进入项目文件夹

cd home/All_Project/Opencv_Project/Project1_testCamera

创建一个.cpp文件

touch main.cpp

双击打开main.cpp即可开始编写代码。第一个main文件是编译后生成的.exe文件。

最重要的代码会用注释“<<*>>”标出

//这个代码实现opencv打开摄像头并拍摄图片使其连续播放变成视频,加入了帧数的监测,会在终端里面打印出帧数
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	
	VideoCapture cap(0); //打开摄像头,即使用vedio0  <<*>>
	
	if(!cap.isOpened())//检查摄像头打开
	{
		cout << "Camera open failed " << endl;
		return 0;
	}
	cout << "Camera open success" << endl;
	
	double fps, total_fps = 0; //帧数相关的变量
    	int frame_count = 0;  //帧数的计数变量
	
	
	for( ; ; ) //让图片连续显示就变成了视频
	{
		// 获取当前时间戳
        double start_time = static_cast<double>(cv::getTickCount());
	
		Mat ColorImage; //实例化一个对象 <<*>>
		cap >> ColorImage; //令摄像头进行拍照 <<*>>
		
		if (ColorImage.empty())  //若图像为空则退出循环
		{
            	cerr << "Error: Couldn't capture a frame." << endl;
            	break;  // 退出循环
        	}
        	
        	// 在这里进行帧处理
        	 // 计算帧速率
		double end_time = static_cast<double>(cv::getTickCount());
		double elapsed_time = (end_time - start_time) / cv::getTickFrequency();
		fps = 1.0 / elapsed_time;

		// 累计帧速率和帧数
		total_fps += fps;
		frame_count++;

		// 输出平均帧速率
		if (frame_count % 30 == 0) {  // 每30帧输出一次
		    double avg_fps = total_fps / frame_count;
		    std::cout << "Average FPS: " << avg_fps << std::endl;
		}
        	
        	
		
		imshow("video",ColorImage); //显示最终的图像 <<*>>
		//waitKey(0);
		
		char key = waitKey(30);  // 等待按键,每帧间隔30毫秒

       		if (key == 27) {
            	// 如果按下ESC键,退出循环
            	break;
			
		}
	
	
	}
	return 0;
}

//g++ main.cpp -o main `pkg-config --cflags --libs opencv4`

 代码编写完成后还需要编译才能在计算机上运行,在当前文件夹中右键打开终端进行编译,这里使用g++编译,编译时容易出现报错,除了代码语法错误外,大多是没有连相关库一起编译

g++ main.cpp -o main `pkg-config --cflags --libs opencv4`

 编译完后会发现生成了一个.exe可执行文件。通过指令或双击即可看见图像

./main

 

三、使用opencv处理摄像头拍摄的图像

        在计算机图像处理中,摄像头拍摄得到的原图并不容易直接处理,我们需要将图像进行多种变换才方便计算机进行计算。

        拿到原图后,先转换为灰度图,再转换为均衡图,原因是灰度图不容易识别出人脸轮廓,将其均衡化后更容易检测到人脸轮廓。再使用级连分类器调用opencv中自带训练好的人脸模型对均衡图进行识别,识别到人脸后,会返回人脸列表,我们在人脸的位置画一个矩形方框,这样就实现了opencv识别人脸。


#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
///opencv.hpp
using namespace std;
using namespace cv;


int main()
{
	VideoCapture cap(0); //打开摄像头 <<*>>
	
	if(!cap.isOpened()) //检测摄像头是否打开
	{
		cout << "Camera open failed" << endl;
		return 0;
	}
	cout << "Camera open succed " << endl;
	
	CascadeClassifier Classifier("/usr/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml");  //级联分类器,输入人脸的训练模型  <<*>>
	
	Mat ColorImage;//原图
	Mat GrayImage;//灰度图
	Mat EqualImage;//均衡图
	vector<Rect> AllFace;//创建承载人脸列表的容器
	
	for( ; ; )
	{
		cap >> ColorImage;
		cvtColor(ColorImage,GrayImage,COLOR_BGR2GRAY); //将原图转换为灰度图 <<*>>
		equalizeHist(GrayImage,EqualImage);//将灰度图均值化,均值化后的图像更易检测人脸轮廓 <<*>>
		Classifier.detectMultiScale(EqualImage,AllFace);//检测人脸,返回识别出人脸的矩形列表<<*>>
		if(AllFace.size()) //当检测到人脸的时候才画框
		{
				rectangle(GrayImage,AllFace[0],Scalar(255,255,0));//通过rectang将人脸的矩形画在显示图像上	<<*>>							
		}
		
		imshow("video",GrayImage);//显示图像 <<*>>
		waitKey(40);
	}
}

//g++ main.cpp -o main -I/usr/include/opencv4 `pkg-config --cflags --libs opencv4`





通过编译后即可运行得到结果

g++ main.cpp -o main -I/usr/include/opencv4 `pkg-config --cflags --libs opencv4`

 

        现在我们就是使用了VideoCapture cap(0)来开启摄像头,用cap >> ColorImage让摄像头拍照,并通过opencv训练好的人脸库haarcascade_frontalface_alt2.xml和Classifier.detectMultiScale()获取图像中人脸的位置,然后我们用rectangle()在人脸位置画了个框。

        到目前为止,opencv的任务已经完成了,我们已经得到了人脸图像,就差将人脸上传到云进行AI匹配计算了,将人脸图像上传到云后,云会把我们上传的图像与其人脸库中的图像进行对比,并返回相似度最高的人脸信息。

四、配置百度智能云平台

1.配置云

        使用云平台给我们进行AI计算,需要在百度智能云平台申请资源并输入人脸库的数据,这样云平台在接收到我们拍摄到的人脸才能进行比对。百度智能云平台的业务很多,人脸识别考勤机只使用到了人脸识别业务。百度智能云现在有开放免费的计算资源,直接可以领取使用。

 根据操作指引的提示即可在网页内完成云的配置。

 

在创建完应用后,需要录入人脸库。这里显示了AppID、APIKey、Secret Key,我们正是通过这三个关键信息来让ubuntu和云进行匹配的。

 

 

2.配置ubuntu

         配置好云后,在我们自己的ubuntu上也需要进行配置,这样才能兼容到智能云的API,即在ubuntu上搭建SDK,SDK是软件开发工具包,在ubuntu里面搭建后才能往代码里写上与云平台有关的代码。

下载即得到一个压缩包,我们把压缩包解压后放入我们的项目文件夹,确保我们的main在这个文件夹里面。

        百度云的SDK也依赖一些其他的库,我们也要把这些库安装上。

sudo apt-get install libcurl4-openssl-dev
sudo apt-get install openssl
sudo apt-get install libjson-dev
sudo apt-get install libssl-dev

 

五、将百度智能云的API接入代码


#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstdlib>
#include <cstddef>
#include "face.h"
///opencv.hpp
using namespace std;
using namespace cv;
using namespace aip;

int main()
{
	VideoCapture cap(0);
	
	if(!cap.isOpened()) //检测摄像头是否打开
	{
		cout << "Camera open failed" << endl;
		return 0;
	}
	cout << "Camera open succed " << endl;
	
	CascadeClassifier Classifier("/usr/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml");  //集联分类器,输入人脸的训练模型
	
	string app_id = "你的app_id ";
	string api_key = "你的api_key ";
	string secret_key = "你的secret_key ";
	
	aip::Face client(app_id,api_key,secret_key);//智能云的API,通过这个建立Ubuntu和云的联系 <<*>>
	
	Mat ColorImage;//原图
	Mat GrayImage;//灰度图
	Mat EqualImage;//均衡图
	vector<Rect> AllFace;//创建承载人脸列表的容器
	Mat MatFace;//人脸图
	vector<uchar> JpgFace;//用来存储.jpg形式的变量
	string Base64Face;//用来存储base64格式的变量
	Json::Value result;//用来存储百度智能云返回的结果
	time_t sec;
	
	for( ; ; )
	{
		cap >> ColorImage;
		cvtColor(ColorImage,GrayImage,COLOR_BGR2GRAY); //将原图转换为灰度图
		equalizeHist(GrayImage,EqualImage);//将灰度图均值化,均值化后的图像更易检测人脸轮廓
		Classifier.detectMultiScale(EqualImage,AllFace);//检测人脸,返回识别出人脸的矩形列表
		if(AllFace.size()) //当检测到人脸的时候才画框
		{
			//for(int i = 0;i < std::size(AllFace);i++) //size(AllFace)
			//{
				rectangle(GrayImage,AllFace[0],Scalar(255,255,0));//通过rectang将人脸的矩形画在显示图像上
				MatFace = GrayImage(AllFace[0]);//将人脸图取出
				imencode(".jpg",MatFace,JpgFace);//将Mat格式转为.jpg
				Base64Face = base64_encode((char *)JpgFace.data(),JpgFace.size());//将.jpg格式的图片转换为base64格式 <<*>>
				result = client.search(Base64Face,"BASE64","User",aip::null);//将本机截取的人脸发给百度智能云并获取结果 <<*>>
				cout << result << endl;//在本机上打印结果
				
			//}
		}
		
		imshow("video",GrayImage);//显示图像
		waitKey(40);
	}
}

//g++ main.cpp -o main -I/usr/include/opencv4 `pkg-config --cflags --libs opencv4`  -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection/base -std=c++11 -lcurl -lcrypto -ljsoncpp




 使用智能云需要加的代码:

#include "face.h"  //头文件包含
using namespace aip; //命名空间

string app_id = "你的app_id ";
string api_key = "你的api_key ";
string secret_key = "你的secret_key ";

aip::Face client(app_id,api_key,secret_key);//智能云的API,通过这个建立Ubuntu和云的联系 <<*>>

string Base64Face;//用来存储base64格式的变量
Json::Value result;//用来存储百度智能云返回的结果

Base64Face = base64_encode((char *)JpgFace.data(),JpgFace.size());//将.jpg格式的图片转换为base64格式 <<*>>
				
result = client.search(Base64Face,"BASE64","User",aip::null);//将本机截取的人脸发给百度智能云并获取结果 <<*>>

根据智能云的文档进行编译:

g++ main.cpp -o main -I/usr/include/opencv4 `pkg-config --cflags --libs opencv4`  -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection/base -std=c++11 -lcurl -lcrypto -ljsoncpp

 若http.h和json.h出现报错,按图片进行更改。

可以在终端里面看到云反馈回来的信息

六、信息处理

这是云返回给我们的信息

{
	"cached" : 0,
	"error_code" : 0,
	"error_msg" : "SUCCESS",
	"log_id" : 319**,
	"result" : 
	{
		"face_token" : "a177cce0d03e85ca3**",
		"user_list" : 
		[
			{
				"group_id" : "User",
				"score" : 79.587699890137003,
				"user_id" : "ChenGuanXi",
				"user_info" : ""
			}
		]
	},
	"timestamp" : 170**
}

里面包含了很多内容,如识别的人脸库ID,人脸ID,相似度等,我们使用的时候不需要显示那么多信息,于是可以用json库来处理这些信息,当识别的相似度大于80时,我们才让显示人们和当前时间。

if( !result["result"].isNull() ) //如果接受到的result不为空,则开始判断相似度
{
		if(result["result"]["user_list"][0]["score"].asInt() > 80) //当相似度大于80时才显示信息
		{
			cout << result["result"]["user_list"][0]["user_id"] << endl; //显示人脸名
			sec = time(NULL);
			cout << ctime(&sec) << endl;  //获取时间并显示
		}
}

这样终端就会显示人脸名和时间了

 同时这些信息也需要记录备案,且我们想要将信息直接打印到图像上,opencv库有一个函数putText()可以直接将信息放在图像上;而在启动程序的时候"./mian >> log.txt"这样会使终端的输出重定向到log.txt文件里面,便记录了这些信息。

全部代码:


#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cstdlib>
#include <cstddef>
#include "face.h"
///opencv.hpp
using namespace std;
using namespace cv;
using namespace aip;

int main()
{
	VideoCapture cap(0);
	
	if(!cap.isOpened()) //检测摄像头是否打开
	{
		cout << "Camera open failed" << endl;
		return 0;
	}
	cout << "Camera open succed " << endl;
	
	CascadeClassifier Classifier("/usr/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml");  //集联分类器,输入人脸的训练模型
	
	string app_id = "47744549";
	string api_key = "O1TaEInKKMgYLPutwExB3jhM";
	string secret_key = "yoTdKymLxTTn5U1f2iZtwpZkIkLgpVwi";
	
	aip::Face client(app_id,api_key,secret_key);
	
	Mat ColorImage;//原图
	Mat GrayImage;//灰度图
	Mat EqualImage;//均衡图
	vector<Rect> AllFace;//创建承载人脸列表的容器
	Mat MatFace;//人脸图
	vector<uchar> JpgFace;//用来存储.jpg形式的变量
	string Base64Face;//用来存储base64格式的变量
	Json::Value result;//用来存储百度智能云返回的结果
	time_t sec;
	
	for( ; ; )
	{
		cap >> ColorImage;
		cvtColor(ColorImage,GrayImage,COLOR_BGR2GRAY); //将原图转换为灰度图
		equalizeHist(GrayImage,EqualImage);//将灰度图均值化,均值化后的图像更易检测人脸轮廓
		Classifier.detectMultiScale(EqualImage,AllFace);//检测人脸,返回识别出人脸的矩形列表
		if(AllFace.size()) //当检测到人脸的时候才画框
		{
			//for(int i = 0;i < std::size(AllFace);i++) //size(AllFace)
			//{
				rectangle(GrayImage,AllFace[0],Scalar(255,255,0));//通过rectang将人脸的矩形画在显示图像上
				MatFace = GrayImage(AllFace[0]);//将人脸图取出
				imencode(".jpg",MatFace,JpgFace);//将Mat格式转为.jpg
				Base64Face = base64_encode((char *)JpgFace.data(),JpgFace.size());//将.jpg格式的图片转换为base64格式
				result = client.search(Base64Face,"BASE64","User",aip::null);//将本机截取的人脸发给百度智能云并获取结果
				//cout << result << endl;//在本机上打印结果
				
				if( !result["result"].isNull() )
				{
					if(result["result"]["user_list"][0]["score"].asInt() > 80)
					{
						cout << result["result"]["user_list"][0]["user_id"] << endl;
						sec = time(NULL);
						cout << ctime(&sec) << endl;
						putText(GrayImage,result["result"]["user_list"][0]["user_id"].asString(),Point(0,50),FONT_HERSHEY_SIMPLEX,1,Scalar(255,255,255));
						putText(GrayImage,ctime(&sec),Point(0,100),FONT_HERSHEY_SIMPLEX,1,Scalar(255,255,255));
					}
				}
			//}
		}
		
		imshow("video",GrayImage);//显示图像
		waitKey(40);
	}
}

//g++ main.cpp -o main -I/usr/include/opencv4 `pkg-config --cflags --libs opencv4`  -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection -I/home/newnew/All_Project/OpenCV_Project/project2_FaceDetection/base -std=c++11 -lcurl -lcrypto -ljsoncpp




 效果:

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值