人脸识别
人脸识别的原理是采用了神经网络算法,先进行脸部识别,然后再在脸部识别的基础上,将人脸裁剪出来进行眼睛识别,这种方法只能说识别成功率不会特别高,而且受环境、角度影响较大。如果要达到人脸打卡的那种识别成功率,这种方法,肯定是不行的。
其中“haarcascade_frontalface_alt.xml”就是人脸识别的神经网络文件,“haarcascade_eye_tree_eyeglasses.xml”是眼睛识别的神经网络文件。
视频讲解如下:
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
C#版本
C#版本需要安装“OpenCvSharp4”、“OpenCvSharp4.runtime.win”两个库才行。不然会报错。
如果需要使用“ BitmapConverter.ToBitmap”操作,则需要追加安装“OpenCvSharp4.Extensions”库。
效果演示如下:

代码如下:
using OpenCvSharp;
using System;
namespace demo
{
internal class Program
{
public static CascadeClassifier face_cascade = new CascadeClassifier();
public static CascadeClassifier eyes_cascade = new CascadeClassifier();
// 打开摄像头
static void Main(string[] args)
{
// 加载xml文件
if (!face_cascade.Load(@"Files\haarcascade_frontalface_alt.xml"))
{
Console.WriteLine("load haarcascade_frontalface_alt.xml Error.");
Console.Read();
return;
}
if (!eyes_cascade.Load(@"Files\haarcascade_eye_tree_eyeglasses.xml"))
{
Console.WriteLine("load haarcascade_eye_tree_eyeglasses.xml Error.");
Console.Read();
return;
}
VideoCapture Cap = new VideoCapture();
// 打开ID为0的摄像头
Cap.Open(0);
// 判断摄像头是否成功打开
if (!Cap.IsOpened())
{
Console.WriteLine("摄像头打开失败.");
Console.Read();
return;
}
// opencv3
//Cap.Set(CaptureProperty.FrameWidth, 640); // 设置采集的图像尺寸为:640*480
//Cap.Set(CaptureProperty.FrameHeight, 480); // 设置采集的图像尺寸为:640*480
//Cap.Set(CaptureProperty.Exposure, -3); // 曝光
// opencv4
Cap.Set(VideoCaptureProperties.FrameWidth, 640); // 设置采集的图像尺寸为:640*480
Cap.Set(VideoCaptureProperties.FrameHeight, 480); // 设置采集的图像尺寸为:640*480
Cap.Set(VideoCaptureProperties.Exposure, -3); // 曝光
Mat frame = new Mat();
var window = new Window("frame");
while (true)
{
if (Cap.Read(frame))
{
// 人脸识别
frame = detectAndDisplay(frame);
// 在Window窗口中播放视频(方法1)
window.ShowImage(frame);
// 在Window窗口中播放视频(方法2)
//Cv2.ImShow("frame", frame);
// 在pictureBox1中显示效果图
//pictureBox1.Image = BitmapConverter.ToBitmap(frame);
if (Cv2.WaitKey(10) == 27)
break;
}
}
}
private static Mat detectAndDisplay(Mat frame)
{
// 将原图像转换为灰度图像
Mat frame_gray = new Mat();
Cv2.CvtColor(frame, frame_gray, ColorConversionCodes.BGR2GRAY);
// 直方图均衡化, 用于提高图像的质量
Cv2.EqualizeHist(frame_gray, frame_gray);
// 人脸检测
// opencv3:HaarDetectionType.ScaleImage
// opencv4:HaarDetectionTypes.ScaleImage
Rect[] faces = face_cascade.DetectMultiScale(frame_gray, 1.1, 2, 0 | HaarDetectionTypes.ScaleImage, new Size(30, 30));
for (int i = 0; i < faces.Length; i++)
{
// 绘制脸部区域
Point center = new Point() { X = (faces[i].X + faces[i].Width / 2), Y = (faces[i].Y + faces[i].Width / 2) };
Cv2.Ellipse(frame, center, new Size(faces[i].Width / 2, faces[i].Height / 2), 0, 0, 360, new Scalar(255, 0, 255), 2, LineTypes.Link8, 0);
// 绘制眼睛区域
Mat faceROI = new Mat(frame_gray, faces[i]);
Cv2.ImShow("faceROI", faceROI);
Rect[] eyes = eyes_cascade.DetectMultiScale(faceROI, 1.1, 2, 0 | HaarDetectionTypes.ScaleImage, new Size(30, 30));
for (int j = 0; j < eyes.Length; j++)
{
Point eye_center = new Point() { X = (faces[i].X + eyes[j].X + eyes[j].Width / 2), Y = (faces[i].Y + eyes[j].Y + eyes[j].Height / 2) };
int radius = (int)Math.Round((decimal)((eyes[j].Width + eyes[j].Height) * 0.25), 0, MidpointRounding.AwayFromZero);
Cv2.Circle(frame, eye_center.X, eye_center.Y, radius, new Scalar(0, 0, 255), 3, LineTypes.Link8, 0);
}
}
return frame;
}
}
}
C++版本
C++版本是毛星云的版本简化来的。
效果演示如下:

代码如下:
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
//--------------------------------【全局变量声明】----------------------------------------------
// 描述:声明全局变量
//-------------------------------------------------------------------------------------------------
//注意,需要把"haarcascade_frontalface_alt.xml"和"haarcascade_eye_tree_eyeglasses.xml"这两个文件复制到工程路径下
String face_cascade_name = "Files/haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "Files/haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(void)
{
VideoCapture capture;
Mat frame;
//-- 1. 加载级联(cascades)
if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading\n"); return -1; };
if (!eyes_cascade.load(eyes_cascade_name)) { printf("--(!)Error loading\n"); return -1; };
//-- 2. 读取视频
capture.open(0);
if (capture.isOpened())
{
for (;;)
{
capture >> frame;
//-- 3. 对当前帧使用分类器(Apply the classifier to the frame)
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
printf(" --(!) No captured frame -- Break!"); break;
}
int c = waitKey(10);
if ((char)c == 'c') { break; }
}
}
waitKey(10);
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//-- 人脸检测
//此句代码的OpenCV2版为:
//face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//此句代码的OpenCV3版为:
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
std::vector<Rect> eyes;
//-- 在脸中检测眼睛
//此句代码的OpenCV2版为:
//eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//此句代码的OpenCV3版为:
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t j = 0; j < eyes.size(); j++)
{
Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
circle(frame, eye_center, radius, Scalar(255, 0, 0), 3, 8, 0);
}
}
//-- 显示最终效果图
imshow(window_name, frame);
}
Python版本
效果演示如下:

代码如下:
import cv2
# 读取xml文件
face_cascade = cv2.CascadeClassifier('Files/haarcascade_frontalface_alt.xml')
eyes_cascade = cv2.CascadeClassifier('Files/haarcascade_eye_tree_eyeglasses.xml')
def detectAndDisplay(frame):
# 将原图像转换为灰度图像
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 直方图均衡化, 用于提高图像的质量
frame_gray = cv2.equalizeHist(frame_gray)
# 人脸检测
faces = face_cascade.detectMultiScale(frame_gray, scaleFactor=1.1,
minNeighbors=2, minSize=(20, 20),
flags=(0 | cv2.CASCADE_SCALE_IMAGE))
for (x, y, w, h) in faces:
# 绘制脸部区域
# 这里一定要转换成int,不然ellipse会提示:ellipse() takes at most 5 arguments (9 given)
center = (int(x + w / 2), int(y + w / 2)) # 中心点位置
axes = (int(w / 2), int(h / 2)) # 长轴半径、短轴半径
cv2.ellipse(frame, center, axes, 0, 0, 360, (255, 0, 255), thickness=2, lineType=8)
# 绘制眼睛区域
faceROI = frame_gray[y:y + h, x:x + w]
cv2.imshow('faceROI', faceROI)
eyes = eyes_cascade.detectMultiScale(faceROI, scaleFactor=1.1,
minNeighbors=2, minSize=(20, 20),
flags=(0 | cv2.CASCADE_SCALE_IMAGE))
for (x2, y2, w2, h2) in eyes:
sye_x = x + x2 + w2 / 2
sye_y = y + y2 + h2 / 2
radius = round((w2 + h2) * 0.25, 0)
frame = cv2.circle(frame, (int(sye_x), int(sye_y)), int(radius), (0, 0, 255), 3, 8, 0)
return frame
if __name__ == "__main__":
# 打开摄像头
Cap = cv2.VideoCapture(0)
# 判断视频是否打开
if (Cap.isOpened() == False):
print('Open Camera Error.')
else:
Cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 设置图像宽
Cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置图像高
Cap.set(cv2.CAP_PROP_EXPOSURE, -3) # 设置曝光值
# 读取图像
while True:
grabbed, frame = Cap.read()
if frame is None:
continue
frame = detectAndDisplay(frame)
cv2.imshow('frame', frame)
cv2.waitKey(30)
cv2.destroyAllWindows()