基于OpenCV的Haar级联+LBPH模型的人脸识别

系列文章目录

第二章:基于深度学习的学生课堂专注度检测系统设计与实现之基于OpenCV的人脸识别。



前言

通过实现人脸识别功能,辅助课堂签到。这里使用的是一种较为普通的办法,基于OpenCV Haar级联进行人脸识别。此前,我也做过一个基于face_recognition的人脸识别,但是效果太差。后续我也将继续完善,使用Dlib去进行人脸识别。


一、OpenCV介绍及安装

1.1 OpenCV简介

OpenCV 的全称是OpenSourceComputerVision Library,是一个跨平台的计算机视觉库。OpenCV 是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的IPP进行加速处理。
OpenCV 用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语
言接口。该库也有大量的Python、JavaandMATLAB/OCTAVE(版本2.5)的接口。这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#、Ch、Ruby、GO的支持。

1.2 安装OpenCV模块

OpenCV 已经支持python的模块了,直接使用pip就可以进行安装,命令如下:

pip install opencv-python

二、OpenCV的基本使用

2.1 读取图片

显示图像是OpenCV最基本的操作之一,imshow()函数可以实现该操作。如果使用过其他GUI框架背景,就会很自然第调用imshow()来显示一幅图像。
imshow()函数有两个参数:显示图像的帧名称以及要显示的图像本身。直接调用imshow()函数图像确实会显示,但随即会消失。要保证图片一直在窗口上显示,要通过waitKey()函数。waitKey()函数的参数为等待键盘触发的时间,单位为毫秒,其返回值是-1(表示没有键被按下)

import cv2 as cv
img=cv.imread('lena.jpg') #注意读取图片的路径不能有中文,不然数据读取不出来
cv.imshow('input image',img)
cv.waitKey(0) #等待键盘的输入 单位是毫秒 传入0 无限等待
cv.destroyAllWindows() #C++语言 使用完内存必须释放

2.2 图片灰度转换

OpenCV 中有数百种关于在不同色彩空间之间转换的方法。当前,在计算机视觉中有三种常用的色彩空间:灰度、BGR、以及HSV(Hue,Saturation,Value)。
(1)灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,比如人脸识别。
(2)BGR及蓝、绿、红色彩空间,每一个像素点都由一个三元数组来表示,分别代表蓝、绿、红三种颜色。网页开发者可能熟悉另一个与之相似的颜色空间:RGB它们只是颜色顺序上不同。
(3)HSV,H(Hue)是色调,S(Saturation)是饱和度,V(Value)表示黑暗的程度(或光谱另一端的明亮程度)。
灰度转换的作用就是:转换成灰度的图片的计算强度得以降低。示例如下:

import cv2 as cv
src=cv.imread('lena.jpg')
cv.imshow('inputimage',src)
#cv2读取图片的通道是BGR(蓝绿红)
#PIL读取图片的通道是RGB
gray_img=cv.cvtColor(src,code=cv.COLOR_BGR2GRAY)
cv.imshow('gray_image',gray_img)
cv.waitKey(0)
cv.destroyAllWindows()
#保存图片
cv.imwrite('gray_lena.jpg',gray_img)

2.3 修改图片尺寸

import cv2 as cv
img=cv.imread('lena.jpg')
cv.imshow('inputimage',img)
#修改图片的尺寸
#resize_img=cv.resize(img,dsize=(110,160))
resize_img=cv.resize(img,dsize=(400,360))
print(resize_img.shape)
cv.imshow('resize_img',resize_img)
#如果键盘输入的是q时候退出
whileTrue:
	if ord('q')==cv.waitKey(0):
	break
cv.destroyAllWindows()

2.4 画图

OpenCV 的强大之处的一个体现就是其可以对图片进行任意编辑,处理。 下面的这个函数最后一个参数指定的就是画笔的大小。

import cv2 as cv
img=cv.imread('lena.jpg')
#画矩形
x,y,w,h=50,50,80,80
cv.rectangle(img,(x,y,x+w,y+h),color=(0,255,0),thickness=2) #color=BGR
cv.imshow('result image',img)
cv.waitKey(0)
cv.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,0,255),thickness=2)
cv.destroyAllWindows()

三、Haar级联介绍及获取

3.1Haar级联概念

Haar级联是一种基于机器学习的对象检测方法,由Paul Viola和Michael Jones在2001年提出。它通过训练大量的正样本(包含目标对象的图像)和负样本(不包含目标对象的图像)来创建分类器。Haar级联检测器在OpenCV中非常流行,主要优点是速度快,适用于资源受限的设备。
基本原理:
Haar级联检测器使用Haar特征来检测对象。Haar特征类似于卷积核,通过计算黑色矩形区域下的像素总和与白色矩形区域下的像素总和的差值来获得特征值。为了加速计算,使用了积分图像(也称为求和面积表),使得计算类似Haar的特征非常快。
使用预训练模型:
OpenCV提供了多种预训练的Haar级联模型,包括面部、眼睛和嘴部检测等。可以使用cv2.CascadeClassifier类从磁盘加载预训练的Haar级联检测器,并使用detectMultiScale方法进行检测

3.2 获取Haar级联数据

首先我们要进入OpenCV官网:https://opencv.org/releases/,由于OpenCV支持好多平台,比如Windows,Android,Maemo,FreeBSD, OpenBSD, iOS,Linux 和 Mac OS,一般初学者都是用windows,点击Windows。如下图所示:

在这里插入图片描述
点击Windows下载文件,然后双击下载的文件,进行安装,实质就是解压一下,解压完出来一个文件夹,其他什
么也没发生。安装完后的目录结构如下。其中build是OpenCV使用时要用到的一些库文件,而sources 中则是OpenCV官方为我们提供的一些demo示例源码。
在这里插入图片描述
在sources 的一个文件夹data/haarcascades。该文件夹包含了所有OpenCV的人脸检测的XML文件,这些可用于检测静止图像、视频和摄像头所得到图像中的人脸。
在这里插入图片描述
人脸检测器(默认):haarcascade_frontalface_default.xml
人脸检测器(快速Harr):haarcascade_frontalface_alt2.xml
人脸检测器(侧视):haarcascade_profileface.xml
眼部检测器(左眼):haarcascade_lefteye_2splits.xml
眼部检测器(右眼):haarcascade_righteye_2splits.xml
嘴部检测器:haarcascade_mcs_mouth.xml
鼻子检测器:haarcascade_mcs_nose.xml
身体检测器:haarcascade_fullbody.xml
人脸检测器(快速LBP):lbpcascade_frontalface.xm

四、使用OpenCV进行人脸检测

4.1 静态图像中单张人脸检测

人脸检测首先是加载图像并检测人脸,这也是最基本的一步。为了使所得到的结果有意义,可在原始图像的人脸周围绘制矩形框。
示例代码:

# @Time   : 2025/1/10 0010 10:49
# @Author :sjsflyqy
import cv2 as cv


def face_detect_demo():
    # 将图片灰度
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv.CascadeClassifier('D:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml')
    faces = face_detector.detectMultiScale(gray)
    for x, y, w, h in faces:
        cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 255, 0), thickness=2)
    cv.imshow('result', img)


# 加载图片
img = cv.imread('face01.jpg')

# 人脸检测
face_detect_demo()


cv.waitKey(0)
cv.destroyAllWindows()

效果:
在这里插入图片描述

4.2 静态图像中多张人脸检测

示例代码:

# @Time   : 2025/1/10 0010 11:04
# @Author :sjsflyqy

import cv2 as cv


def face_detect_demo():
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv.CascadeClassifier('D:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml')
    # detectMultiScale()中有很多参数用于调整框选范围。
    faces = face_detector.detectMultiScale(gray)

    for x, y, w, h in faces:
        cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 0, 255), thickness=2)
        cv.circle(img, center=(x+w//2, y+h//2), radius=w//2, color=(0, 255, 0), thickness=2)
    cv.imshow('result', img)


# 加载图片
img = cv.imread('face3.jpg')

# 调用人脸检测方法
face_detect_demo()

cv.waitKey(0)
cv.destroyAllWindows()

效果:

在这里插入图片描述

4.3 视频中的人脸检测

视频是一张一张图片组成的,在视频的帧上重复这个过程就能完成视频中的人脸检测。
示例代码:

# @Time   : 2025/1/10 0010 15:48
# @Author :sjsflyqy

import cv2 as cv


def face_detect_demo(img):
    # 将图片灰度
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv.CascadeClassifier('D:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml')
    # detectMultiScale()中有很多参数用于调整框选范围。
    faces = face_detector.detectMultiScale(gray)
    for x, y, w, h in faces:
        cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 0, 255), thickness=2)

    cv.imshow('result', img)


cap = cv.VideoCapture(0)

while True:
    flag, frame = cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if ord('q') == cv.waitKey(10):
        break
    # cv.imshow('video', frame)

cv.destroyAllWindows()
cap.release()

五、人脸识别

5.1 介绍

人脸检测是OpenCV的一个很不错的功能,它是人脸识别的基础。什么是人脸识别呢?
其实就是一个程序能识别给定图像或视频中的人脸。实现这一目标的方法之一是用一系列分好类的图像来“训练”程序,并基于这些图像来进行识别。这就是OpenCV及其人脸识别模块进行人脸识别的过程。人脸识别模块的另外一个重要特征是:每个识别都具有转置信(confidence)评分,因此可在实际应用中通过对其设置阈值来进行筛选。人脸识别所需要的人脸可以通过两种方式来得到:自己获得图像或从人脸数据库免费获得可用的人脸图像。互联网上有许多人脸数据库:https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
为了对这些样本进行人脸识别,必须要在包含人脸的样本图像上进行人脸识别。这是一个学习的过程,但并不像自己提供的图像那样令人满意。

5.2 训练数据

有了数据,需要将这些样本图像加载到人脸识别算法中。所有的人脸识别算法在它们的train()函数中都有两个参数:图像数组和标签数组。这些标签表示进行识别时候某人人脸的ID,因此根据ID可以知道被识别的人是谁。要做到这一点,将在「trainer/」目录中保存为.yml文件。
在使用Python3&OpenCV3.0.0 进行人脸识别训练时发现异常:
AttributeError: ‘module’ object has no attribute ‘LBPHFaceRecognizer_create’OpenCV
需要安装opencv-contrib-python 模块,直接使用 pip就可以进行安装,命令如下:

pip install opencv-contrib-python

示例代码:

# @Time   : 2025/1/10 0010 17:56
# @Author :sjsflyqy

import os
import cv2
import numpy as np
import sys
from PIL import Image

recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier('D:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml')
def getImagesAndLabels(path):
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
    faceSamples=[]
    ids = []
    for imagePath in imagePaths:
        PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
        img_numpy = np.array(PIL_img,'uint8')
        id = int(os.path.split(imagePath)[-1].split(".")[0])
        faces = detector.detectMultiScale(img_numpy)
        for (x, y, w, h) in faces:
            faceSamples.append(img_numpy[y:y + h, x:x + w])
        ids.append(id)
    return faceSamples, ids

if __name__=='__main__':
    path='./data/jm/'
    faces,ids=getImagesAndLabels(path)
    recognizer.train(faces,np.array(ids))
    #Savethemodelintotrainer/trainer.yml
    recognizer.write('trainer/trainer.yml')

5.3 基于LBPH模型的人脸识别

LBPH(LocalBinaryPatternHistogram)将检测到的人脸分为小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。由于这种方法的灵活性,LBPH是唯一允许模型样本人脸和检测到的人脸在形状、大小上可以不同的人脸识别算法。调整后的区域中调用predict()函数,该函数返回两个元素的数组:第一个元素是所识别个体的标签,第二个是置信度评分。所有的算法都有一个置信度评分阈值,置信度评分用来衡量所识别人脸与原模型的差距,0表示完全匹配。可能有时不想保留所有的识别结果,则需要进一步处理,因此可用自己的算法来估算识别的置信度评分。LBPH一个好的识别参考值要低于50,任何高于80的参考值都会被认为是低的置信度评分。
示例代码:

import cv2
import numpy as np
import os
recognizer=cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')

def face_detect_demo(img):
    # 将图片灰度
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv2.CascadeClassifier('D:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml')
    # detectMultiScale()中有很多参数用于调整框选范围。
    faces = face_detector.detectMultiScale(gray)
    for x, y, w, h in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), color=(0, 0, 255), thickness=2)
        id, confidence = recognizer.predict(gray[y:y + h, x:x + w])
        font = cv2.FONT_HERSHEY_DUPLEX
        color = (0, 255, 0)
        cv2.putText(frame, str(id), (x, y - 10), font, 0.5, color, 1)
        print(id, confidence)

    cv2.imshow('result', img)

cap = cv2.VideoCapture(0)

while True:
    flag, frame = cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if ord('q') == cv2.waitKey(10):
        break
    # cv.imshow('video', frame)

cv2.destroyAllWindows()
cap.release()

六、DeepSeek对上述代码的解析与修改建议

6.1 第一部分:训练模型代码

1.导入库

import os
import cv2
import numpy as np
import sys
from PIL import Image
  • 作用:导入必要的库,包括文件操作(os)、图像处理(cv2, PIL)、数值计算(numpy)等。

2. 初始化识别器和检测器

recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier('D:\\opencv\\..._frontalface_default.xml')
  • 作用
    • LBPHFaceRecognizer:基于局部二值模式直方图(LBPH)的人脸识别模型。
    • CascadeClassifier:Haar级联分类器,用于检测人脸位置。

3. 数据加载函数 getImagesAndLabels

def getImagesAndLabels(path):
    imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
    faceSamples, ids = [], []
    for imagePath in imagePaths:
        PIL_img = Image.open(imagePath).convert('L')  # 转为灰度图
        img_numpy = np.array(PIL_img, 'uint8')
        id = int(os.path.split(imagePath)[-1].split(".")[0])  # 从文件名提取ID
        faces = detector.detectMultiScale(img_numpy)
        for (x, y, w, h) in faces:
            faceSamples.append(img_numpy[y:y+h, x:x+w])
            ids.append(id)  # 修正:每检测到一个人脸添加一次ID
    return faceSamples, ids
  • 作用:遍历指定路径下的所有图像,检测人脸并提取对应ID。
  • 问题
    • 原代码中ids.append(id)的位置错误,会导致标签数量与样本数量不匹配(已修正)。
    • 假设每个图像仅包含单个人脸,否则需确保文件名与多个人脸对应。

4. 主程序

if __name__ == '__main__':
    path = './data/jm/'
    faces, ids = getImagesAndLabels(path)
    recognizer.train(faces, np.array(ids))
    recognizer.write('trainer/trainer.yml')
  • 作用:加载数据、训练模型并保存到trainer.yml

6.2 第二部分:实时检测代码

1. 加载模型和检测器

recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
face_detector = cv2.CascadeClassifier('D:\\opencv\\..._frontalface_default.xml')
  • 作用:加载训练好的模型和人脸检测器。

2. 检测函数 face_detect_demo

def face_detect_demo(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 修正变量名错误
    faces = face_detector.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
    for x, y, w, h in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 2)
        id, confidence = recognizer.predict(gray[y:y+h, x:x+w])
        label = str(id) if confidence < 70 else "Unknown"  # 添加置信度阈值
        cv2.putText(img, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
    cv2.imshow('result', img)
  • 改进
    • 修正了frameimg的变量名错误。
    • 添加了置信度阈值判断,避免误识别未知人脸。

3. 摄像头实时检测

cap = cv2.VideoCapture(0)
while True:
    flag, frame = cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
  • 作用:打开摄像头,逐帧处理并显示结果,按q退出。

潜在问题与改进建议

  1. 训练数据标签错误(已修正):

    • 每个检测到的人脸需对应一个ID标签。
  2. 变量名错误(已修正):

    • 实时检测函数中的frame应改为img
  3. 未知人脸处理(已改进):

    • 通过置信度阈值过滤低置信度识别结果。
  4. 路径硬编码

    • 建议将haarcascade_frontalface_default.xml放在项目目录中,使用相对路径。
  5. 多张人脸的处理

    • 训练时需确保每张图像仅包含单个人脸,或文件名与多张人脸对应。

总结

  • 训练代码:从指定路径加载图像,检测人脸并训练LBPH模型。
  • 实时检测代码:调用摄像头实时检测人脸,并用训练好的模型识别。
  • 关键改进:修正标签匹配、变量名错误,添加置信度阈值提升鲁棒性。

七、总结

以上就是今天要讲的内容,本文仅仅简单介绍了借助OpenCV的Haar级联进行简单的人脸检测并训练LBPH模型,还有许多需要完善,希望大家多多指点。另外,希望大家不要吝啬点赞 收藏(●’◡’●)!

<think>好的,我现在需要帮助用户找到关于如何使用OpenCV进行Java人脸检测与识别的示例代码和教程。根据用户提供的引用内容,他们提到了OpenCVPython中的实时人脸检测和Java的示例代码位置。首先,我需要确保回答结构清晰,分步骤说明,并且正确引用提供的资料。 首先,用户需要Java版的示例,而引用中有一个关于Java+OpenCV+IntelliJ IDEA的引用,其中提到了jar包的位置。这可能对用户配置环境有帮助。同时,另一个引用是关于Python中使用Haar级联分类器的,但用户需要Java版本,所以可能需要调整代码示例。 接下来,我需要检查是否有现成的Java代码示例。用户提供的引用[2]提到了示例代码的位置,但具体代码可能需要进一步查找或构造。考虑到用户可能需要基础的人脸检测代码,我应该提供一个简单的Java示例,使用Haar级联分类器,并指导如何配置项目。 此外,用户可能需要教程链接,所以需要寻找可靠的资源,比如OpenCV官方文档或GitHub上的Java示例。同时,引用中提到的人脸识别方法,如特征向量比较,可能需要更复杂的实现,但基础的人脸检测可以先用Haar级联实现。 需要注意的是,用户可能已经安装了OpenCV,但需要确认Java库的配置步骤,包括添加jar包和本地库路径(如.dll或.so文件)。这可能涉及到在IDE中设置依赖项,比如在IntelliJ IDEA中添加库。 最后,生成的相关问题需要与Java人脸检测和识别相关,例如优化方法、不同分类器的比较、实时视频处理以及人脸识别步骤。确保问题覆盖用户可能感兴趣的扩展话题。</think>以下是使用OpenCV进行Java人脸检测与识别的详细步骤说明和示例代码: ### 环境配置步骤 1. **下载OpenCV SDK** 访问[OpenCV官网](https://opencv.org/releases/)下载包含Java支持的Windows/MacOS/Linux版本 2. **添加依赖到项目** - 将`opencv-4xx.jar`添加到项目库(路径:`opencv/build/java`) - 配置本地库路径:`-Djava.library.path=opencv/build/java/x64` ### 人脸检测示例代码 ```java import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; public class FaceDetector { public static void main(String[] args) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 加载分类器(文件路径需替换为实际路径) CascadeClassifier faceDetector = new CascadeClassifier("haarcascade_frontalface_alt.xml"); // 读取图像 Mat image = Imgcodecs.imread("test.jpg"); // 检测人脸 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image, faceDetections); // 绘制检测框 for (Rect rect : faceDetections.toArray()) { Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 3); } // 保存结果 Imgcodecs.imwrite("output.jpg", image); } } ``` ### 关键组件说明 1. **Haar级联分类器** 使用预训练的XML模型文件(如`haarcascade_frontalface_alt.xml`)进行特征识别[^1] 2. **本地库加载** `System.loadLibrary(Core.NATIVE_LIBRARY_NAME)`用于加载OpenCV本地库 3. **检测参数优化** 可通过调整`detectMultiScale`的scaleFactor/minNeighbors参数优化检测精度 ### 人脸识别扩展建议 1. **特征提取** 使用LBPH/FisherFace算法进行人脸特征编码 2. **相似度比对** 计算特征向量之间的欧氏距离进行身份验证 ### 推荐学习资源 - 官方Java教程:https://docs.opencv.org/4.x/d9/d52/tutorial_java_dev_intro.html - GitHub示例库:https://github.com/opencv/opencv/tree/master/samples/java
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sjsflyqy10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值