目标检测笔记(六):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)

本文介绍了如何利用OpenCV在项目中结合特定区域进行目标检测,包括在网络处理前后两种方式,以及通过鼠标事件动态划分检测区域,显著降低计算复杂度,实现实时视频中人脸的局部检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️

背景

由于我们在做项目的时候可能会涉及到某个指定区域进行目标检测或者人脸识别等任务,所以这篇博客是为了探究如何在传统目标检测的基础上来结合特定区域进行检测,以OpenCV自带的包为例。

一般来说有两种方式实现区域指定:

  • 第一种:在网络处理之前,将特定区域划分出来,然后在送入到神经网络进行检测
  • 第二种:在网络处理之后,直接来划分区域的坐标对网络处理后目标进行判定,判定此目标是否在这个区域中,如果在则show,否则则略过

很明显通过第一种方式,网络可以减少很大的计算复杂度,因为不用将整张图片送入到网络中进行处理。

代码分析

以下是对这两段代码的详细分析:

第一段代码:

  • 导入必要库import cv2 导入 OpenCV 库,用于图像处理和视频捕获。
  • 加载人脸检测器face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') 加载了 OpenCV 自带的正面人脸检测器。
  • 初始化视频捕获和感兴趣区域(ROI)cap = cv2.VideoCapture(0) 打开默认摄像头进行视频捕获。定义了 roi_xroi_yroi_widthroi_height 来确定感兴趣区域的坐标和大小。
  • 循环处理每一帧:在循环中,首先读取一帧图像 ret, frame = cap.read(),若读取失败则退出循环。然后获取感兴趣区域 roi = frame[roi_y:roi_y+roi_height, roi_x:roi_x+roi_width],并将其转换为灰度图像 gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)。接着使用人脸检测器在灰度的感兴趣区域中检测人脸 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))。之后在原始图像上绘制感兴趣区域矩形 cv2.rectangle(frame, (roi_x, roi_y), (roi_x+roi_width, roi_y+roi_height), (255, 0, 0), 2),并在感兴趣区域上绘制检测到的人脸矩形 for (x, y, w, h) in faces: cv2.rectangle(roi, (x, y), (x+w, y+h), (0, 255, 0), 2)。最后在窗口中显示图像 cv2.imshow("Camera", frame),并通过 cv2.waitKey(1) 等待按键事件,若按下 ESC 键(键值为 27)则退出循环。

第二段代码:

  • 导入必要库和定义全局变量:同样导入 cv2 库。定义了 draw_roi 函数来处理鼠标事件,还定义了全局变量 roi_xroi_yroi_widthroi_height 用于存储感兴趣区域的坐标和大小,以及 drawing 变量用于标记是否正在绘制感兴趣区域。
  • 初始化视频捕获和鼠标事件绑定:打开默认摄像头 cap = cv2.VideoCapture(0),创建窗口并绑定鼠标事件 cv2.namedWindow("Camera"); cv2.setMouseCallback("Camera", draw_roi),加载人脸检测器 face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
  • 循环处理每一帧:在循环中,首先读取一帧图像 ret, frame = cap.read(),若读取失败则退出循环。然后根据鼠标事件确定的感兴趣区域获取 roi,并在原始图像上绘制感兴趣区域矩形 cv2.rectangle(frame, (roi_x, roi_y), (roi_x + roi_width, roi_y + roi_height), (255, 0, 0), 2)。如果 drawing 为 True,表示用户已经绘制了感兴趣区域,则对该区域进行灰度转换和人脸检测,并在感兴趣区域上绘制检测到的人脸矩形;否则对整个图像进行灰度转换和人脸检测,并在原始图像上绘制检测到的人脸矩形。最后在窗口中显示图像 cv2.imshow("Camera", frame),并通过 cv2.waitKey(1) 等待按键事件,若按下 ESC 键(键值为 27)则退出循环。

总体而言,第一段代码实现了在固定的感兴趣区域内进行人脸检测并显示结果的功能。第二段代码在第一段的基础上增加了鼠标交互功能,允许用户通过鼠标点击和拖动来定义感兴趣区域,从而实现更灵活的人脸检测操作。这两段代码在人脸检测应用中具有一定的实用价值,可用于简单的视频监控或人脸识别系统的前端处理。

完整代码

这个代码是直接通过对特定区域结合OpenCV自带人脸检测器来进行人脸检测。若区域内,目标则被检测,超过区域则不被记录。

import cv2

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0)
# 定义感兴趣区域的坐标和大小
roi_x = 200
roi_y = 100
roi_width = 300
roi_height = 300

while True:
    # 读取一帧图像
    ret, frame = cap.read()
    if not ret:
        print("无法读取摄像头图像")
        break

    # 获取感兴趣区域
    roi = frame[roi_y:roi_y+roi_height, roi_x:roi_x+roi_width]

    # 将感兴趣区域转换为灰度图像
    gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

    # 使用人脸检测器检测人脸区域
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

    # 在原始图像上绘制感兴趣区域矩形
    cv2.rectangle(frame, (roi_x, roi_y), (roi_x+roi_width, roi_y+roi_height), (255, 0, 0), 2)

    # 在感兴趣区域上绘制人脸区域矩形
    for (x, y, w, h) in faces:
        cv2.rectangle(roi, (x, y), (x+w, y+h), (0, 255, 0), 2)

    # 在窗口中显示图像
    cv2.imshow("Camera", frame)

    if cv2.waitKey(1) == 27:
        break

cap.release()
cv2.destroyAllWindows()

这个代码在上面代码的基础上,加入了鼠标点击事件,用户可以通过自己来划分特定检测区域,划分之后将从整张图片的检测转换为特定区域的检测。

import cv2

def draw_roi(event, x, y, flags, param):
    global roi_x, roi_y, roi_width, roi_height, drawing
    if event == cv2.EVENT_LBUTTONDOWN:
        # 鼠标按下,开始绘制
        roi_x, roi_y = x, y

    elif event == cv2.EVENT_LBUTTONUP:
        # 鼠标释放,结束绘制
        roi_width, roi_height = x - roi_x, y - roi_y
        drawing = True


if __name__ == '__main__':
    # 创建一个全局变量来存储感兴趣区域的坐标和大小
    roi_x, roi_y, roi_width, roi_height = 0, 0, 0, 0
    drawing = False
    over = 0
    cap = cv2.VideoCapture(0)
    # 创建窗口并绑定鼠标事件
    cv2.namedWindow("Camera")
    cv2.setMouseCallback("Camera", draw_roi)
    # 加载人脸检测器
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    while True:
        ret, frame = cap.read()
        if not ret:
            print("无法读取摄像头图像")
            break

        # 如果触发了鼠标事件,则在感兴趣区域上运行人脸检测器
        roi = frame[roi_y:roi_y + roi_height, roi_x:roi_x + roi_width]

        # 在原始图像上绘制感兴趣区域矩形
        cv2.rectangle(frame, (roi_x, roi_y), (roi_x + roi_width, roi_y + roi_height), (255, 0, 0), 2)
        if drawing:
            gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
            for (x, y, w, h) in faces:
                cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 255, 0), 2)
        else:
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
            for (x, y, w, h) in faces:
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

        cv2.imshow("Camera", frame)
        if cv2.waitKey(1) == 27:
            break

    cap.release()
    cv2.destroyAllWindows()

结果

在这里插入图片描述
在这里插入图片描述
✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️▶️➡️🌿🍀🍄🌟⭐❄️✅💖⚠️

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZZY_dl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值