当前位置:首页 > Software > Python > 正文内容

(原创)ClassImgsByFace 根据人脸对大量照片进行分类 利用 MTCNN 和 OpenCV 实现人脸识别和分类的 Python 程序

chanra1n12个月前 (01-03)Python1121

需求分析

这个Python程序旨在从输入文件夹中读取照片,使用 MTCNN 和 OpenCV 进行人脸检测,比对已有的人脸库,并根据相似度阈值将照片分类到不同的输出文件夹中。同时,程序还会将检测到的人脸保存到人脸库中。

方法和思路

  1. 读取配置文件,设置路径和参数。

  2. 使用 MTCNN 和 OpenCV 进行人脸检测和特征提取。

  3. 比对检测到的人脸与已有人脸库中的人脸相似度。

  4. 根据相似度阈值分类照片到不同的输出文件夹,同时将人脸保存到人脸库。

  5. 记录日志以便追踪处理过程。

方法评价

  • MTCNN 和 OpenCV 是常用的人脸检测和特征提取工具,能够有效地进行人脸识别。

  • 结合结构相似性指数(SSIM)进行人脸比对,提高了准确性。

  • 多线程实现全局计数器,确保人脸保存到人脸库时的唯一性。

  • 通过日志记录,方便追踪处理过程中的错误和信息。

选择最适合的方法

综合考虑了 MTCNN 和 OpenCV 的人脸检测特性、SSIM 的准确性以及多线程的性能,认为当前的实现方法是较为合理和全面的。

代码实现

# -*- coding: utf-8 -*-
# 版本唯一标识 V1_1
import os
import cv2
from mtcnn.mtcnn import MTCNN
from shutil import copyfile
from skimage.metrics import structural_similarity as ssim
import logging
import threading
import configparser

# 读取配置文件
config = configparser.ConfigParser()
config.read('ClassImgsByFace.cfg')

# 设置路径
input_folder = config.get('Paths', 'input_folder')
output_folder = config.get('Paths', 'output_folder')
face_library_folder = config.get('Paths', 'face_library_folder')
similarity_threshold = float(config.get('Settings', 'similarity_threshold'))

# 初始化 MTCNN
mtcnn = MTCNN()

# 初始化 logging
logging.basicConfig(filename='ClassImgsByFace.log', level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s')

# 日志记录函数
def log_info(message):
    logging.info(message)

# 全局计数器和锁
global_face_counter = 0
counter_lock = threading.Lock()

# 人脸检测和特征提取(MTCNN)
def detect_faces_mtcnn(image_path):
    try:
        image = cv2.imread(image_path)
        result = mtcnn.detect_faces(image)
        faces = [(image[y:y+h, x:x+w], f"face{idx}") for idx, (x, y, w, h) in enumerate([face['box'] for face in result])]
        return faces
    except Exception as e:
        log_info(f"Error processing image {image_path} with MTCNN: {e}")
        return []

# 人脸检测和特征提取(OpenCV)
def detect_faces_opencv(image_path):
    try:
        image = cv2.imread(image_path)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        faces = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml').detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
        faces = [(image[y:y+h, x:x+w], f"face{idx}") for idx, (x, y, w, h) in enumerate(faces)]
        return faces
    except Exception as e:
        log_info(f"Error processing image {image_path} with OpenCV: {e}")
        return []

# 人脸比对
def compare_faces(face1, face2):
    face1 = cv2.resize(face1, (face2.shape[1], face2.shape[0]))
    gray1 = cv2.cvtColor(face1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(face2, cv2.COLOR_BGR2GRAY)
    _, diff = cv2.threshold(cv2.absdiff(gray1, gray2), 30, 255, cv2.THRESH_BINARY)
    score = ssim(gray1, gray2)
    return score

# 保存人脸到人脸库
def save_to_face_library(face, face_library_folder):
    global global_face_counter
    with counter_lock:
        face_id = f"face{global_face_counter}"
        global_face_counter += 1
    cv2.imwrite(os.path.join(face_library_folder, f"{face_id}.jpg"), face)
    return face_id

# 保存完整照片到输出文件夹
def save_full_photo(image_path, output_folder, name, face_id):
    output_path = os.path.join(output_folder, face_id)
    if not os.path.exists(output_path):
        os.makedirs(output_path)
    copyfile(image_path, os.path.join(output_path, name + ".jpg"))

# 人脸匹配和处理
def process_image(image_path):
    try:
        faces_mtcnn = detect_faces_mtcnn(image_path)
        faces_opencv = detect_faces_opencv(image_path)

        if not faces_mtcnn and not faces_opencv:
            log_info(f"No faces detected in image: {image_path}")
            return

        for face_mtcnn, face_id in faces_mtcnn:
            for face_opencv, _ in faces_opencv:
                similarity_scores = [compare_faces(face_mtcnn, face_opencv), compare_faces(face_opencv, face_mtcnn)]
                min_similarity_score = min(similarity_scores)
                log_info(f"Similarity Scores - {similarity_scores}")

                if min_similarity_score > similarity_threshold:
                    log_info("Similar face found!")
                    saved_face_id = save_to_face_library(face_mtcnn, face_library_folder)
                    save_full_photo(image_path, output_folder, os.path.basename(image_path).split('.')[0], saved_face_id)
                    return

        log_info("No similar face found. Adding to face library.")
        saved_face_id = save_to_face_library(faces_mtcnn[0][0], face_library_folder)
        save_full_photo(image_path, output_folder, os.path.basename(image_path).split('.')[0], saved_face_id)
    except Exception as e:
        log_info(f"Error processing image {image_path}: {e}")

# 主流程
def main():
    for root, dirs, files in os.walk(input_folder):
        for file in files:
            image_path = os.path.join(root, file)
            log_info(f"\nProcessing image: {file}")
            process_image(image_path)

if __name__ == "__main__":
    main()

分析结果

  • 功能完成情况:程序能够正确地检测人脸,进行比对,并根据相似度阈值分类照片到不同的输出文件夹。同时,人脸也被保存到人脸库中。

  • 安全性:程序在人脸保存时使用了全局计数器和锁,确保人脸库中的人脸 ID 唯一性。

  • 异常处理:程序通过日志记录了处理过程中的错误,方便追踪问题。

综上所述,该程序能够有效地完成人脸识别和分类的任务,同时具备较好的安全性和异常处理能力。


cfg文件示例

[Paths]
input_folder = C:/Users/ChanRa1n/Desktop
output_folder = C:/Users/ChanRa1n/Desktop/OutPut
face_library_folder = C:/Users/ChanRa1n/Desktop/DataSet/FaceLibrary

[Settings]
similarity_threshold = 0.5
Debug_Mode = True


扫描二维码推送至手机访问。

版权声明:本文由我的FPGA发布,如需转载请注明出处。

本文链接:http://myfpga.cn/index.php/post/344.html

分享给朋友:

“(原创)ClassImgsByFace 根据人脸对大量照片进行分类 利用 MTCNN 和 OpenCV 实现人脸识别和分类的 Python 程序” 的相关文章

for循环

for循环

range()函数range(start,end,step)range()函数返回一个可迭代对象(可理解为一个序列,序列中的数包括start,不包括end)例如range(1,101),返回1-100的序列。range(101),范围0-100的序列。range(1,100,2),返回1,3,5.....

搜索字符串

搜索字符串

常用搜索字符串中子串的方法str.count(substring)      返回str中substring子串出现的无覆盖的次数str.find(s1)                    返回s1在这个字符串的最低下标,如果字符串中不存在s1,则返回-1str.rfind(s1)       ...

anaconda打不开的解决方法

anaconda打不开的解决方法

报错内容Navigator Error An unexpected error occurred on Navigator start-up Report Please report this ...

Python自动清理错误图片,深度学习训练数据集准备

Python自动清理错误图片,深度学习训练数据集准备

使用python运行from PIL import Image from pathlib import Path import os   path = r'.'  ...

(原创)使用Python对任意网站图片进行爬取,仅用于学习

(原创)使用Python对任意网站图片进行爬取,仅用于学习

import os import time import argparse import requests import re import io from urllib.parse import ...