Python 检测人脸筛选指定尺寸人脸图片

主要功能是处理一个指定文件夹中的所有图像文件(.jpg.png),并根据图像中检测到的人脸特征,筛选和移动符合条件的图像。具体步骤如下:

  1. 人脸检测和关键点检测 : 使用 dlib 的预训练人脸检测器(frontal_face_detector)和 68 个关键点预测器来检测图像中的人脸及其关键点(如眼睛、嘴巴等)。

  2. 条件判断: 对每张图像,如果检测到的人脸宽度小于 130 像素且两眼之间的距离小于 60 像素,则将该图片移动到指定的目标文件夹中,并保持源文件夹的目录结构不变。

  3. 目录结构保持: 在移动符合条件的图片时,保持源文件夹的目录层级结构,即原始文件夹的子目录在目标文件夹中会被保留。

  4. 无效图像处理: 如果一张图像中未检测到人脸或人脸太小,则该图像也会被移动到目标文件夹,并打印相应的提示信息。

  5. 依赖库

    • 使用 dlib 进行人脸检测和关键点识别。
    • 使用 opencv 进行图像处理。
    • 使用 osshutil 处理文件和目录操作。

主要流程:

  • 加载模型 :通过 dlib 加载人脸检测器和 68 个关键点检测模型。
  • 处理文件夹:递归遍历指定源文件夹,处理所有符合条件的图像。
  • 人脸检测与筛选:对于每张图像,检测人脸并计算人脸宽度和双眼之间的距离,符合条件的图像会被移动到目标文件夹。
  • 文件移动 :使用 shutil 进行文件的移动操作,并在目标文件夹中保持与源文件夹一致的目录结构。

这个代码可以用于图像筛选工作,尤其是基于人脸特征的筛选任务,比如选择图像中人脸较小或两眼之间距离较近的图像进行进一步处理。

复制代码
import cv2
import dlib
import math
import os
import shutil

# https://www.anaconda.com/download/success
# https://github.com/sachadee/Dlib/blob/main/dlib-19.22.99-cp38-cp38-win_amd64.whl
# https://github.com/italojs/facial-landmarks-recognition/blob/master/shape_predictor_68_face_landmarks.dat

# conda create -n python38 python=3.8
# conda activate python38
# pip install dlib-19.22.99-cp38-cp38-win_amd64.whl
# pip install opencv-python

# 加载dlib的人脸检测器和68个关键点预测模型
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(r'c:\python38\shape_predictor_68_face_landmarks.dat')

# 指定源文件夹和目标文件夹
source_folder = r'c:\python38\face'
target_folder = r'c:\python38\face60'

# 创建目标文件夹,如果不存在的话
if not os.path.exists(target_folder):
    os.makedirs(target_folder)

def process_image(img_path, relative_path):
    # 加载图片
    img = cv2.imread(img_path)

    if img is None:
        print(f"无法读取文件:{img_path}")
        return

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

    # 检测人脸
    faces = detector(gray)

    if len(faces) == 0:
        print(f"未检测到人脸或人脸太小:{img_path}")
        # 将无效人脸或没有检测到人脸的图片移动到目标文件夹
        target_subdir = os.path.join(target_folder, relative_path)
        if not os.path.exists(target_subdir):
            os.makedirs(target_subdir)
        shutil.move(img_path, os.path.join(target_subdir, os.path.basename(img_path)))
        print(f"移动文件 {img_path} 到 {target_subdir}")
        return

    for face in faces:
        # 获取人脸的边界框坐标
        x1 = face.left()
        y1 = face.top()
        x2 = face.right()
        y2 = face.bottom()

        # 计算人脸宽度
        face_width = x2 - x1

        # 打印人脸宽度
        print(f"文件: {img_path} 人脸宽度: {face_width} 像素")

        # 使用预测模型预测人脸的68个关键点
        landmarks = predictor(gray, face)

        # 获取左右眼的关键点(左眼36-41,右眼42-47)
        left_eye_x = (landmarks.part(36).x + landmarks.part(39).x) // 2
        left_eye_y = (landmarks.part(36).y + landmarks.part(39).y) // 2
        right_eye_x = (landmarks.part(42).x + landmarks.part(45).x) // 2
        right_eye_y = (landmarks.part(42).y + landmarks.part(45).y) // 2

        # 计算双眼之间的距离
        eye_distance = math.sqrt((right_eye_x - left_eye_x) ** 2 + (right_eye_y - left_eye_y) ** 2)

        # 如果人脸宽度小于130且双眼距离小于60,移动文件
        if face_width < 130 and eye_distance < 60:
            # 目标文件夹保持目录结构
            target_subdir = os.path.join(target_folder, relative_path)
            if not os.path.exists(target_subdir):
                os.makedirs(target_subdir)
            
            # 移动文件
            shutil.move(img_path, os.path.join(target_subdir, os.path.basename(img_path)))
            print(f"移动文件 {img_path} 到 {target_subdir}")

def process_folder(source_folder):
    for root, dirs, files in os.walk(source_folder):
        for file in files:
            if file.endswith('.jpg') or file.endswith('.png'):
                img_path = os.path.join(root, file)
                # 获取相对路径以保持目录结构
                relative_path = os.path.relpath(root, source_folder)
                process_image(img_path, relative_path)

# 处理整个文件夹
process_folder(source_folder)
相关推荐
上海安当技术11 分钟前
单点登录 SSO 怎么选协议?SAML 2.0 / OAuth 2.0 / OIDC / CAS 对比与 ERP、OA、CRM 接入实战
java·开发语言
不才不才不不才27 分钟前
Spring 源码系列(14): JDK 动态代理 vs CGLIB,以及拦截器责任链
java·开发语言·spring
mifengxing29 分钟前
计算机组成原理——存储器系统
开发语言·考研·计算机组成原理·复习笔记·计算机408
起司喵喵37 分钟前
推荐一款基于 Python 和 Rust 开发的跨平台 GUI 自动化库!
python·rust·自动化
过期的秋刀鱼!40 分钟前
学习曲线-过拟合和欠拟合要做什么以及原因
人工智能·python·深度学习·算法·机器学习·模型评估
Yolanda_20221 小时前
Python学习-第九部分-错误处理与异常处理
开发语言·python·学习
郝学胜-神的一滴1 小时前
Qt 高级编程 037:QSS按钮样式封神指南
开发语言·c++·qt·软件工程·用户界面
DFT计算杂谈1 小时前
SCIENTIFIC REPORTS 非 van der Waals可调二维磁性材料设计平台
开发语言·php
库拉库拉里2 小时前
深入理解 C# 异步编程:同步、Task.Wait () 与 await 的本质区别及实践指南
开发语言·c#
霍霍的袁2 小时前
【C++】string类 从 入门使用 到 底层深浅拷贝模拟实现
开发语言·c++·visual studio