Python快速实现人脸检测

文章目录

  • 问题描述
  • 解决方案
  • 戴圣诞帽
  • 参考文献

本文代码及图片下载地址

问题描述

1.jpg

Python快速实现人脸检测_第1张图片
2.jpg
Python快速实现人脸检测_第2张图片




解决方案

使用 OpenCV 的级联分类器 CascadeClassifier 加载人脸识别预训练模型 haarcascade_frontalface_default.xml,该模型使用 AdaBoost 算法,运行速度十分快,在2013年12月19日上传。

安装库

pip install opencv-python

PS:该分类器仅适用于正面人脸

import cv2

# 读取文件
image = '1.jpg'
model = 'haarcascade_frontalface_default.xml'
image = cv2.imread(image)  # 读取图片
model = cv2.CascadeClassifier(model)  # 加载模型

# 人脸检测
faces = model.detectMultiScale(image)
for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), thickness=2)  # 画出人脸矩形框

# 显示和保存图片
cv2.imshow('result', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('result.jpg', image)
print('已保存')

效果
Python快速实现人脸检测_第3张图片
Python快速实现人脸检测_第4张图片




戴圣诞帽

图片尺寸会被统一,仍需优化

Python快速实现人脸检测_第5张图片

import cv2
import numpy
import random
from PIL import Image
from pathlib import Path

# 参数
HAT_PATH = './hat/'  # 圣诞帽图像路径
MODEL_PATH = 'haarcascade_frontalface_default.xml'  # 人脸识别预训练模型路径

# 读取
model = cv2.CascadeClassifier(MODEL_PATH)

# 读取圣诞帽
hats = []  # 圣诞帽
hats_portion = []  # 圣诞帽宽高比
for i in Path(HAT_PATH).glob('*.png'):
    hat = Image.open(i)
    width, height = hat.size
    hats.append(hat)
    hats_portion.append(width / height)


def std_size(imagePath):
    '''转标准尺寸'''
    pic = Image.open(imagePath)
    width, height = pic.size
    portion = width / height

    if portion < 1:  # 肖像
        if portion <= 0.75:
            pic_w = 960
            pic_h = round(960 / portion)
            box = (0, round((pic_h - 1280) / 2), 960, round(pic_h / 2 + 640))

        if portion > 0.75:
            pic_h = 1280
            pic_w = round(1280 * portion)
            box = (round((pic_w - 960) / 2), 0, round(pic_w / 2 + 480), 1280)

    elif portion > 1:  # 风景
        if portion >= 1.3333:
            pic_h = 960
            pic_w = round(960 * portion)
            box = (round((pic_w - 1280) / 2), 0, round(pic_w / 2 + 640), 960)

        if portion < 1.3333:
            pic_w = 1280
            pic_h = round(1280 / portion)
            box = (0, round((pic_h - 960) / 2), 1280, round(pic_h / 2 + 480))

    elif portion == 1:  # 正方形
        (pic_w, pic_h) = (960, 960)
        box = (0, 0, 960, 960)

    pic = pic.resize((pic_w, pic_h))
    pic = pic.crop(box)
    return pic


def face_detect(pil_image):
    '''人脸检测

    :param pil_image: PIL读取的图片
    '''
    image = cv2.cvtColor(numpy.array(pil_image), cv2.COLOR_RGB2BGR)  # PIL转cv
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces = model.detectMultiScale(
        gray,
        scaleFactor=1.2,
        minNeighbors=5,
        minSize=(50, 60),
        flags=cv2.CASCADE_SCALE_IMAGE
    )
    return faces


def get_hat(x, y, w, h):
    # 设定每个帽子的概率
    num = random.randint(1, 100)
    if num in range(1, 17):
        hat_num, offset1, offset2, offset3 = (0, 1.2, .05, .67)  # hat1
    elif num in range(17, 33):
        hat_num, offset1, offset2, offset3 = (1, 1.3, -.4, .62)  # hat2
    elif num in range(33, 49):
        hat_num, offset1, offset2, offset3 = (2, .9, .05, .8)  # hat3
    elif num in range(91, 101):
        hat_num, offset1, offset2, offset3 = (3, 1.2, .05, .67)  # green hat
    elif num in range(49, 65):
        hat_num, offset1, offset2, offset3 = (4, 1.2, -.1, 1.2)  # jiao1
    elif num in range(65, 81):
        hat_num, offset1, offset2, offset3 = (5, 1, 0, 1.2)  # jiao2
    elif num in range(81, 91):
        hat_num, offset1, offset2, offset3 = (6, .9, .05, 1)  # tree

    hat_portion = hats_portion[hat_num]
    (hat_w, hat_h) = (int(w * offset1), int(w * offset1 / hat_portion))
    # print('hat size:', hat_w, hat_h)
    hatter = hats[hat_num].resize((hat_w, hat_h))

    (hat_x, hat_y) = (int(x + w * offset2), int(y - hat_h * offset3))
    hat_pos = (hat_x, hat_y)
    # print('hat at:', hat_x, hat_y)

    return (hatter, hat_pos)


def wear_hat(imagePath, output, show=False):
    '''戴圣诞帽

    :param imagePath: 图片路径
    :param output: 保存路径
    :param show: 是否显示中间过程
    :return:
    '''
    # 人脸检测
    image = std_size(imagePath)
    faces = face_detect(image)

    if show:
        temp_image = image.copy()

    # 戴圣诞帽
    for (x, y, w, h) in faces:
        # print('face at:', x, y, w, h)
        (hatter, hat_pos) = get_hat(x, y, w, h)
        image.paste(hatter, hat_pos, hatter)
    image.save(output)

    if show:
        # 原图
        temp_image = cv2.cvtColor(numpy.array(temp_image), cv2.COLOR_RGB2BGR)
        cv2.imshow('1', temp_image)
        cv2.waitKey(0)

        # 人脸检测框
        for (x, y, w, h) in faces:
            cv2.rectangle(temp_image, (x, y), (x + w, y + h), (0, 255, 0), thickness=2)
        cv2.imshow('1', temp_image)
        cv2.waitKey(0)

        # 戴圣诞帽
        temp_image = Image.fromarray(cv2.cvtColor(temp_image, cv2.COLOR_BGR2RGB))
        for (x, y, w, h) in faces:
            (hatter, hat_pos) = get_hat(x, y, w, h)
            temp_image.paste(hatter, hat_pos, hatter)
        temp_image = cv2.cvtColor(numpy.array(temp_image), cv2.COLOR_RGB2BGR)  # PIL转cv
        cv2.imshow('1', temp_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()


if __name__ == '__main__':
    wear_hat('2.jpg', 'result.jpg', show=True)




参考文献

  1. opencv haarcascades 预训练模型
  2. OpenCV Document
  3. wx-fancy-pic: 微信公众号服务,根据用户发来的照片自动生成海报或有趣的照片

你可能感兴趣的:(Python,OpenCV,PIL)