python opencv 人体/人脸识别 简易demo

Posted Love丶伊卡洛斯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python opencv 人体/人脸识别 简易demo相关的知识,希望对你有一定的参考价值。

前言

参考文章:
pythonopencv检测行人_【图像处理】使用OpenCV实现人脸和行人检测
Python如何实现行人识别-人体识别

本文主要讲述关于opencv官方提供的现成模型,采取Hog特征和SVM分类器的方式,实现对图片、视频进行人体/人脸的识别,并用不同颜色框出识别的矩形区域。
ps:测试图片源于网络,如有侵权,可私聊立删。

开发环境:pycharm-2020.1.5, python-3.8.5,opencv-python-4.5.4.58,opencv-4.2.0-vc14_vc15
cascade的xml数据路径:opencv\\sources\\data\\haarcascades
相关数据用途可参考:使用OpenCV,Haar级联检测器进行面部、眼睛、嘴部检测

效果图



视频素材来自:https://wedistill.io/categories/people

相关函数解释

参考文档:
https://docs.opencv.org/2.4/modules/core/doc/intro.html#api-concepts
https://docs.opencv.org/4.1.2/d7/dbd/group__imgproc.html

HOG::detectMultiScale

HOGDescriptor::setSVMDetector

CascadeClassifier::CascadeClassifier

CascadeClassifier::detectMultiScale

VideoCapture::isOpened

VideoCapture::read

源码

import cv2
import sys, os

# 判断框中框
def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih


# 框出人 传入图片 矩形参数 BGR
def draw_person(image, person, bgr):
    x, y, w, h = person
    cv2.rectangle(image, (x, y), (x + w, y + h), bgr, 2)


# 筛选识别出的人矩形数据
def screen_found(found):
    for ri, r in enumerate(found):
        for qi, q, in enumerate(found):
            if ri != qi and is_inside(r, q):
                break
            else:
                found_filtered.append(r)


# 等比缩放 参考:https://blog.csdn.net/JulyLi2019/article/details/120720752
def resize_keep_aspectratio(image_src, dst_size):
    src_h, src_w = image_src.shape[:2]
    # print(src_h, src_w)
    dst_h, dst_w = dst_size

    # 判断应该按哪个边做等比缩放
    h = dst_w * (float(src_h) / src_w)  # 按照w做等比缩放
    w = dst_h * (float(src_w) / src_h)  # 按照h做等比缩放

    h = int(h)
    w = int(w)

    if h <= dst_h:
        image_dst = cv2.resize(image_src, (dst_w, int(h)))
    else:
        image_dst = cv2.resize(image_src, (int(w), dst_h))

    h_, w_ = image_dst.shape[:2]
    # print(h_, w_)
    print('等比缩放完毕')

    return image_dst


# cascade图片人体识别和绘制边框 参数 需要识别的图片 输出绘制的图片 xml路径 bgr颜色 目标的最小尺寸 目标的最大尺寸
def cascade_img_person_detect_draw(src_img, dst_img, xml_path, bgr, min_size, max_size):
    detector = cv2.CascadeClassifier(xml_path)
    # image表示的是要检测的输入图像
    # objects表示检测到的人脸目标序列
    # scaleFactor表示每次图像尺寸减小的比例
    # minNeighbors表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸)
    # flag 对于旧级联具有与函数cvHaarDetectObjects相同的含义。它不用于新的级联。
    # minSize为目标的最小尺寸
    # maxSize为目标的最大尺寸
    # found = detector.detectMultiScale(src_img)
    found = detector.detectMultiScale(src_img, 1.1, 3, cv2.CASCADE_SCALE_IMAGE, (0, 0), (500, 500))

    # 筛选识别出的人矩形数据
    screen_found(found)

    for person in found_filtered:
        draw_person(dst_img, person, bgr)

    found_filtered.clear()

    print(xml_path + " 识别出:" + str(len(found)) + "个结果。")

# 参考文章:https://blog.csdn.net/www_16302_com/article/details/103817612
# cascade视频人体识别和绘制边框 参数 需要识别的视频路径 xml路径 bgr颜色 目标的最小尺寸 目标的最大尺寸
# 按 Q 键退出函数
def cascade_video_person_detect_draw(video_path, xml_path, bgr, min_size, max_size):
    cap = cv2.VideoCapture(video_path)

    # 告诉OpenCV使用什么识别分类器
    classfier = cv2.CascadeClassifier(xml_path)

    while cap.isOpened():
        # 读取一帧数据
        ret, frame = cap.read()
        # 抓取不到视频帧,则退出循环
        if not ret:
            break
        # 显示方向
        frame = cv2.flip(frame, 1)

        # 将当前帧转换成灰度图像
        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 检测结果
        # 第一个参数是灰度图像
        # 第而个参数scaleFactor表示每次图像尺寸减小的比例
        # 第三个参数是人脸检测次数,设置越高,误检率越低,但是对于迷糊图片,我们设置越高,越不易检测出来
        # minSize为目标的最小尺寸
        # maxSize为目标的最大尺寸
        found = classfier.detectMultiScale(grey, scaleFactor=1.1, minNeighbors=4, minSize=min_size, maxSize=max_size)

        # 框出识别结果
        if len(found) > 0:
            for foundRect in found:
                x, y, w, h = foundRect
                cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), bgr, 1)

        # 显示图像
        cv2.imshow('person detection', frame)
        # 键盘Q键结束
        c = cv2.waitKey(10)
        if c & 0xFF == ord('q'):
            break

    # 释放摄像头并销毁所有窗口
    cap.release()
    cv2.destroyAllWindows()

    print("视频识别结束。")


# 读取图片,修改为自己的路径即可
img = cv2.imread("img/people_detection/4.jpg")
# 等比缩放至500*500
img = resize_keep_aspectratio(img, [500, 500])
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 存储所有识别出的坐标集
found_filtered = []

hog = cv2.HOGDescriptor()
# 加载SVM模型 行人识别
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

# 对图像进行多尺度目标检测 返回检测到区域的坐标
found, w = hog.detectMultiScale(gray)
# print(found)

# 筛选识别出的人矩形数据
screen_found(found)

# 在原图上绘出识别出的所有矩形 蓝色
for person in found_filtered:
    draw_person(img, person, (255, 0, 0))

# 清空列表
found_filtered.clear()

print("HOGDescriptor_getDefaultPeopleDetector 识别出:" + str(len(found)) + "个结果。")

# 正脸识别 绿色
cascade_img_person_detect_draw(gray, img, "data/haarcascade_frontalface_default.xml", (0, 255, 0), (0, 0), (500, 500))

# 侧脸识别 红色
cascade_img_person_detect_draw(gray, img, "data/haarcascade_profileface.xml", (0, 0, 255), (0, 0), (500, 500))

# 全身识别 青色
cascade_img_person_detect_draw(gray, img, "data/haarcascade_fullbody.xml", (255, 255, 0), (0, 0), (500, 500))

# 上半身识别 洋红
cascade_img_person_detect_draw(gray, img, "data/haarcascade_upperbody.xml", (255, 0, 255), (0, 0), (500, 500))

# 下半身识别 黄色
cascade_img_person_detect_draw(gray, img, "data/haarcascade_lowerbody.xml", (0, 255, 255), (0, 0), (500, 500))


cv2.imshow("people detection", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 视频素材来自:https://wedistill.io/categories/people
# 参数 需要识别的视频路径 xml路径 bgr颜色 目标的最小尺寸 目标的最大尺寸
cascade_video_person_detect_draw("video/1.mp4", "data/haarcascade_upperbody.xml", (0, 255, 0), (50, 50), (1000, 3000))


以上是关于python opencv 人体/人脸识别 简易demo的主要内容,如果未能解决你的问题,请参考以下文章

python opencv 人体/人脸识别 简易demo

人脸识别 python调用face++ 功能测试

OpenCV人脸识别--detectMultiScale函数

OpenCV4.5.4 DNN人脸识别模块使用介绍--如何快速搭建一个人脸识别系统

python之OpenCv---人脸识别

Python+OpenCV实现AI人脸识别身份认证系统—人脸识别原理