通过AI写一个人脸识别并裁剪压缩的程序

前段时间出了一个结合了 ChatGPT 与搜索引擎的 New bing,恰巧最近有个大量人脸数据统一化裁剪需求,就尝试了一下让它写代码,我按照一个需求进行描述 “把图像信息进行人脸识别并裁剪,如果大于 200KB 则压缩到 200KB 以下”,它提供了一段 Python 代码如下:

# 导入所需的库
import cv2
import numpy as np
import os

# 定义目标图片大小(单位为字节)
target_size = 200 * 1024

# 读取图片文件
img = cv2.imread("image.jpg")

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 加载人脸检测器
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

# 检测人脸区域
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

# 如果没有检测到人脸,打印提示信息并退出
if len(faces) == 0:
    print("No faces detected.")
    exit()

# 如果检测到多个人脸,打印提示信息并退出
if len(faces) > 1:
    print("Multiple faces detected.")
    exit()

# 获取第一个(也是唯一一个)人脸区域的坐标和尺寸
x, y, w, h = faces[0]

# 根据人脸区域,计算裁剪区域的坐标和尺寸(可以根据需要调整比例和边距)
crop_x = max(0, x - int(w * 0.1))
crop_y = max(0, y - int(h * 0.2))
crop_w = min(img.shape[1], x + w + int(w * 0.1)) - crop_x
crop_h = min(img.shape[0], y + h + int(h * 0.4)) - crop_y

# 裁剪图片并保存为新文件
cropped_img = img[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w]
cv2.imwrite("cropped_image.jpg", cropped_img)

# 获取裁剪后图片的大小(单位为字节)
cropped_size = os.path.getsize("cropped_image.jpg")

# 如果裁剪后图片的大小超过目标大小,进行压缩操作
if cropped_size > target_size:
    # 计算压缩比例(假设图片大小与质量成线性关系)
    ratio = target_size / cropped_size

    # 设置压缩参数(JPEG格式,质量范围为0-100)
    params = [cv2.IMWRITE_JPEG_QUALITY, int(ratio * 100)]

    # 压缩图片并覆盖原文件
    cv2.imwrite("cropped_image.jpg", cropped_img, params)

从代码来看,用到了 opencv 库,还贴心的附上了注释,方便了我们后期修改。

运行前把需要的库安装上,找了几张照片运行,第一次运行报找不到 haarcascade_frontalface_default.xml 错误,在库中找到后把该文件放在代码统一目录下,第二次运行,生成的照片效果还不错,但不支持中文字符。

然后我修改了代码,让它支持中文字符,并且把结果形成日志输出到 log.txt,把所有裁剪完成以及输出日志放在一个 output 文件夹里。


# -*- coding: utf-8 -*-
# 导入所需的库
import cv2
import numpy as np
import os
import sys
import configparser
import datetime

# 输入参数
args = sys.argv
input_path = args[1]
filename = os.path.basename(input_path)
dir_name = os.path.dirname(input_path)
output_path = f'{dir_name}\\output\\{filename}'

# 配置文件
xml_path = r'D:\Python\AIFace\haarcascade_frontalface_default.xml'

# 创建output文件夹
folder = f'{dir_name}\\output' # 想要检查或创建的文件夹名
if not os.path.exists(folder): # 如果文件夹不存在
    os.makedirs(folder) # 创建文件夹

# 创建日志文件
log_filename = f'{dir_name}\\output\\log.txt'
if not os.path.exists(log_filename):
    f = open(log_filename,'w')
    f.close();

# 定义目标图片大小(单位为字节)
target_size = 200 * 1024

# 读取图片文件
img = cv2.imdecode(np.fromfile(input_path,dtype=np.uint8),cv2.IMREAD_COLOR)

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 加载人脸检测器
face_cascade = cv2.CascadeClassifier(xml_path)

# 检测人脸区域
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

# 如果没有检测到人脸,打印提示信息并退出
if len(faces) == 0:
    print("没有检测到人脸。")
    f = open(log_filename, 'a', encoding='utf-8')
    f.write(f'{datetime.datetime.now()}>> {filename}\t - 失败:没有检测到人脸。\n')
    f.close()
    exit()

# 如果检测到多个人脸,打印提示信息并退出
if len(faces) > 1:
    print("检测到多个人脸。")
    f = open(log_filename, 'a', encoding='utf-8')
    f.write(f'{datetime.datetime.now()}>> {filename}\t - 失败:检测到多个人脸。\n')
    f.close()
    exit()

# 获取第一个(也是唯一一个)人脸区域的坐标和尺寸
x, y, w, h = faces[0]

# 根据人脸区域,计算裁剪区域的坐标和尺寸(可以根据需要调整比例和边距)
crop_x = max(0, x - int(w * 0.1))
crop_y = max(0, y - int(h * 0.2))
crop_w = min(img.shape[1], x + w + int(w * 0.1)) - crop_x
crop_h = min(img.shape[0], y + h + int(h * 0.4)) - crop_y

# 裁剪图片并保存为新文件
cropped_img = img[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w]
cv2.imencode('.jpg', cropped_img)[1].tofile(output_path)
print(f'已生成:{output_path}')
f = open(log_filename, 'a', encoding='utf-8')
f.write(f'{datetime.datetime.now()}>> {filename}\t - 成功。\n')
f.close()

# 获取裁剪后图片的大小(单位为字节)
cropped_size = os.path.getsize(output_path)

# 如果裁剪后图片的大小超过目标大小,进行压缩操作
if cropped_size > target_size:
    # 计算压缩比例(假设图片大小与质量成线性关系)
    ratio = target_size / cropped_size

    # 设置压缩参数(JPEG格式,质量范围为0-100)
    params = [cv2.IMWRITE_JPEG_QUALITY, int(ratio * 100)]

    # 压缩图片并覆盖原文件
    cv2.imencode('.jpg', cropped_img,params )[1].tofile(output_path)
    print(f'已压缩:{output_path}')

在 Windows 下,批量处理可以结合 DOS 命令,把所有 jpg 图片拖到这个批处理执行文件,就可以进行大批量人脸数据自动裁剪。

for %%i in (%*) do Python X:\Python\AIFace\AIFace.py %%~dpnxi
pause

至此就完成了一个简约的桌面小工具,代码还有很多需要完善的地方,如部分图片识别不出人脸、图片格式只能识别 jpg 等等,这些可以通过 ffmpeg 等来优化。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至feicyblog@hotmail.com