一、OpenCv人脸与笑容检测

import cv2 as cv
import matplotlib.pyplot as plt
import os

print("=== 开始人脸和笑容检测 ===")

# 1. 读取图片
img = cv.imread("zrn.jpg")
if img is None:
    print("错误:无法读取 zrn.jpg 文件")
    print("当前目录文件:", os.listdir('.'))
    exit()

# 转换为灰度图
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
print("图片读取成功")

# 2. 加载分类器
face_cas = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml')
smile_cas = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_smile.xml')

# 检查分类器是否加载成功
if face_cas.empty():
    print("错误:人脸分类器加载失败")
    exit()

if smile_cas.empty():
    print("错误:笑容分类器加载失败")
    exit()

print("分类器加载成功")

# 3. 检测人脸
faceRects = face_cas.detectMultiScale(
    gray,
    scaleFactor=1.1,
    minNeighbors=5,
    minSize=(30, 30)
)

print(f"检测到 {len(faceRects)} 张人脸")

for (x, y, w, h) in faceRects:
    # 框出人脸 - 绿色矩形
    cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 3)
    cv.putText(img, 'Face', (x, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

    # 在人脸区域检测笑容
    roi_gray = gray[y:y + h, x:x + w]
    roi_color = img[y:y + h, x:x + w]

    # 笑容检测参数需要更宽松一些
    smiles = smile_cas.detectMultiScale(
        roi_gray,
        scaleFactor=1.8,  # 笑容检测需要更大的缩放因子
        minNeighbors=20,  # 需要更多的邻居确认
        minSize=(25, 25)  # 笑容的最小尺寸
    )

    # 绘制笑容区域 - 红色矩形
    for (sx, sy, sw, sh) in smiles:
        cv.rectangle(roi_color, (sx, sy), (sx + sw, sy + sh), (0, 0, 255), 2)
        cv.putText(roi_color, 'Smile', (sx, sy - 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
        print(f"检测到笑容在位置: ({sx}, {sy})")

# 4. 显示结果
plt.figure(figsize=(10, 8))
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.title(f'人脸和笑容检测 - 找到 {len(faceRects)} 张人脸')
plt.axis('off')
plt.tight_layout()
plt.show()

# 保存结果
cv.imwrite('face_smile_result.jpg', img)
print("结果已保存为 'face_smile_result.jpg'")

这里的问题还是会误判人脸。下面是设计的知识点:

1.1图像读取与显示
import cv2 as cv
import matplotlib.pyplot as plt

# 图像读取
img = cv.imread("zrn.jpg")

# 图像显示(使用matplotlib)
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB))
plt.show()
  • cv.imread(): 读取图像文件,返回numpy数组

  • 支持多种格式:JPG、PNG、BMP等

  • OpenCV使用BGR色彩空间,matplotlib使用RGB,需要转换

1.2色彩空间转换
# BGR转灰度图
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# BGR转RGB(用于matplotlib显示)
rgb_img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
  • cv.cvtColor(): 色彩空间转换函数

  • 常用转换:BGR2GRAY、BGR2RGB、BGR2HSV

  • 灰度图减少计算复杂度,提高检测速度

二、Haar级联分类器

Haar级联分类器是一种基于机器学习的目标检测方法。

2.1分类器加载与初始化
# 加载预训练的分类器
face_cas = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml')
smile_cas = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_smile.xml')

# 检查分类器是否加载成功
if face_cas.empty():
    print("分类器加载失败")
  • CascadeClassifier: Haar特征级联分类器

  • OpenCV提供多种预训练模型:人脸、眼睛、笑容、身体等

  • cv.data.haarcascades: OpenCV内置分类器路径

2.2目标检测详解

faces = face_cas.detectMultiScale(
    gray,                    # 输入灰度图像
    scaleFactor=1.1,         # 图像缩放比例
    minNeighbors=5,          # 检测框最小邻居数
    minSize=(30, 30)         # 目标最小尺寸
)
  • scaleFactor=1.1: 每次图像缩放10%,值越小检测越精确但速度越慢

  • minNeighbors=5: 候选框需要5个邻居才能确认,值越大检测越严格

  • minSize=(30,30): 忽略小于30x30像素的检测

三.图像处理与标注

3.1绘制几何图形
# 绘制矩形框
cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 3)

# 添加文本标注
cv.putText(img, 'Face', (x, y-10), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
  • (x, y): 矩形左上角坐标

  • (x+w, y+h): 矩形右下角坐标

  • (0, 255, 0): BGR颜色值(绿色)

  • 3: 线条粗细

  • cv.FONT_HERSHEY_SIMPLEX: 字体类型
3.2 ROI(Region of Interest)区域处理
# 提取人脸区域
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]

# 在ROI区域内进行笑容检测
smiles = smile_cas.detectMultiScale(roi_gray, 1.8, 20, minSize=(25, 25))
  • ROI操作提高检测效率和准确性

  • numpy数组切片语法提取特定区域

  • 分层检测:先检测大人脸,再在脸内检测小特征

下周开始学习yolo的原理以及初步搭建项目结构。

Logo

助力合肥开发者学习交流的技术社区,不定期举办线上线下活动,欢迎大家的加入

更多推荐