admin 发表于 2022-5-22 10:09:03

python用于检查照片是否符合人脸识别使用要求

# -*- coding: utf-8 -*-
import os
import ab as ab
import cv2
import openpyxl
from openpyxl import Workbook
from PIL import Image
import numpy as np

# 注意:haarcascade文件位置与opencv环境配置有关
face_cascade = cv2.CascadeClassifier('C:/Users/Administrator/AppData/Local/Programs/Python/Python39/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml')
# face_cascade = cv2.CascadeClassifier('./data/haarcascade_frontalface_default.xml')

"""图片人脸检测及返回相关信息
face_img:照片文件路径
返回值
resolution:分辨率;   dpi1:文件DPI信息;n_photo:照片是否存在人脸;blur:人脸模糊指数;"""
def ImgDetect(face_img):
    # imgDPI = cv2.imread(face_img)

    img = cv2.imdecode(np.fromfile(face_img, dtype=np.uint8), cv2.IMREAD_COLOR)# 解决上面函数中文路径及中文文件名报错问题
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 人脸检测
    faces = face_cascade.detectMultiScale(gray, 1.3, 9, minSize=(50, 50))
    faces_ratio = 0
    faces_size = 0

    if len(faces):                              # 判断照片是否存在人脸信息
      im = Image.open(face_img)
      n_photo="人物照片"

      # 此方法为文件头检查法检测文件是否为JPG文件,有时会出错
      # print(im.info)
      # if im.info=={}:                                                      #判断是否为JPG文件,一般PNG文件无info信息
      #    print("请转换成jpg文件")
      # else:
      #   if 'dpi' in im.info.keys():                                    #判断dpi信息的key是否存在
      #      print("DPI:", im.info['dpi'])                                 #打印dpi信息
      #   else:
      #         print("无DPI信息")

      if 'dpi' in im.info.keys():             # 判断dpi信息的key是否存在
            dpi1=im.info['dpi']
            # print("DPI:", im.info['dpi'])   # 打印dpi信息
      else:
            dpi1=()
            # print("无DPI信息")

      resolution=im.size                      # 分辨率值
      faces_ratio=format(round(faces/resolution,4),'.2%')# 人脸占比
      faces_size=faces

      # 测试数据代码:
      print("人脸位置:", faces)
      print("分辨率:", im.size)# 打印分辨率信息
      print("人脸图像占比:", faces_ratio)
      print("人脸分辨率:",faces_size)
      # print('模糊指数:', cv2.Laplacian(gray, cv2.CV_64F).var())# 拉普拉斯方差算法获取拉普拉斯卷积值(越大越清晰)
      # print("原照片【宽:",img.shape,"照片高:",img.shape,"】\r\n")    # 获取图片分辨率信息(高,宽,bgr层)
      # print(img.dtype)

      photo_blur=Blur_photo(img,faces,gray)         # 获取模糊指数值
      blur=photo_blur
      photo_t=photo_blur

    else:
      n_photo="照片无人脸"
      resolution=()
      dpi1=()
      blur = cv2.Laplacian(gray, cv2.CV_64F).var()
      photo_t = "异常照片"

    return


"""历遍文件夹文件"""
def getListFiles(path):
    ret = []
    for root, dirs, files in os.walk(path):
      for filespath in files:
            ret.append(os.path.join(root, filespath))
    return ret


""" 读取图片 """
def get_file_content(filePath):
    with open(filePath, 'rb') as fp:
      return fp.read()


"""JPG文件判断"""
def is_jpg(filename):
    try:
      i = Image.open(filename)
      return i.format == 'JPEG'
    except IOError:
      return False


"""差分法照片人脸清晰度检查模块
1、人脸检测框选需优化或跟换算法;
2、部分照片模糊指数错误成因需关注(低分辨率小尺寸照片模糊指数很高);"""
def Blur_photo(img,rect,gray):
    """
    img:原图片数据
    rect:人脸检测位置数据
    gray:图片转换灰度数据
    """

    # save_path = 'D:/程序测试素材/'

    box_data = gray:(rect + rect), (rect):(rect + rect)]# 取矩形目标区域


    # 参数测试用代码:
    # print("传入参数有效性检测")
    # print("原图:", img)
    # print("灰度图:", gray)
    # print("人脸框:", rect)
    # print("计算参数:", box_data)
    # print("人脸图像占比:", rect / img.shape)
    print("模糊指数:", cv2.Laplacian(box_data, cv2.CV_64F).var())       # 拉普拉斯方差算法获取拉普拉斯卷积值(越大越清晰)

    """加权调整模糊指数
    有误差,待解决
    """
    # print("加权模糊指数:", cv2.Laplacian(box_data, cv2.CV_64F).var() * img.shape/500)
    # zhishu=cv2.Laplacian(box_data, cv2.CV_64F).var()/(cv2.Laplacian(box_data, cv2.CV_64F).var() * img.shape/500)
    # if zhishu>2 or zhishu<0.5:
    #   print("异常照片")
    # else:
    #   print("正常照片")

    """找出存在低分辨率且高模糊指数的照片,判定照片是否需要人工检查"""
    if img.shape<300 and cv2.Laplacian(box_data, cv2.CV_64F).var()>90:
      photo_T="照片异常"
    else:
      photo_T="照片正常"


    while True:
      img1 = cv2.rectangle(img, (rect, rect), (rect + rect, rect + rect),(255, 0, 0), 2)
      cv2.namedWindow('frame',cv2.WINDOW_NORMAL)
      cv2.resizeWindow('frame',600,800)
      cv2.namedWindow('cat', cv2.WINDOW_NORMAL)
      cv2.resizeWindow('cat', 600, 800)
      cv2.imshow('frame', img1)
      cv2.imshow('cat', box_data)
      if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # cap.release()
    cv2.destroyAllWindows()
    return cv2.Laplacian(box_data, cv2.CV_64F).var(),photo_T


"""创建信息检索输出表"""
def C_workbook(Photo_Path):
    f = Workbook()# 创建工作表

    """表改名"""
    sh = f['Sheet']
    sh.title = "照片信息"

    """定义表头"""
    H_report = ["文件名", "文件路径", "人像", "分辨率", "宽", "高", "DPI", "水平", "垂直", "人脸占比","人脸px","模糊指数","照片状态"]

    # # tableTitle = ['userName', 'Phone', 'age', 'Remark']
    #
    # # 维护表头
    # #if row < 1 or column < 1:
    # #   raise ValueError("Row or column values must be at least 1")
    # # 如上,openpyxl 的首行、首列 是 (1,1)而不是(0,0),如果坐标输入含有小于1的值,提示 :Row or column values must be at least 1,即最小值为1.

    """创建表头"""
    for col in range(len(H_report)):
      sh.cell(row=1, column=col + 1).value = H_report

    # 格式化列

    sh.column_dimensions["A"].width = 20
    sh.column_dimensions["B"].width = 50
    sh.column_dimensions["C"].width = 10
    sh.column_dimensions["D"].width = 10
    sh.column_dimensions["E"].width = 8
    sh.column_dimensions["F"].width = 8
    sh.column_dimensions["G"].width = 10
    sh.column_dimensions["H"].width = 8
    sh.column_dimensions["I"].width = 8
    sh.column_dimensions["J"].width = 15
    sh.column_dimensions["K"].width = 10

    Sfile = Photo_Path + '/照片信息检索.xlsx'
    f.save(Sfile)
    f.close()
    return Sfile


if __name__ == '__main__':
    # 检索目录
    # "E:\工作\我的文档\工作\Project\正宇软件\黑龙江\大庆\人大\2018\照片"
    # "D:\程序测试素材"
    # "D:\程序测试素材\照片"

    Photo_Path=input()                  # 输入检索文件夹路径

    file_name=C_workbook(Photo_Path)    # 创建信息输出表,返回表文件路径

    ret = getListFiles(Photo_Path)      # 检索目录文件

    Ex_file = openpyxl.load_workbook(file_name)   # 加载Excel表
    sheet=Ex_file["照片信息"]                         # 激活工作表

    for each in ret:                        # each为检索目录返回值
      print("文件位置:",each)

      file_n=each.replace(Photo_Path,"").replace("\\","")   # 获取文件名
      print("文件名:", file_n)

      if is_jpg(each):                            # 判断是否为JPG照片
            ab=ImgDetect(each)                      # 比对照片,返回照片参数
            print(ab)
      else:                                       # 非JPG文件处理
            ab=['非JPG照片',(),(),"","",0,'异常照片']
            print("请转换为JPG文件!")

      # 整理数据
      photo_data=
      for i in range(len(ab)):
            # 提取元组数据
            if isinstance(ab, tuple):                # 检测是否为元组
                if len(ab) == 0:                     # 检测是否为空
                  # print("数据为空")
                  for n in range(3):                  # 插入3个空值
                        # print(n)
                        photo_data.append("")
                else:                                 # 提取数据
                  xl = ""
                  for n in range(len(ab)):
                        if n<(len(ab)-1):
                            xl=xl+str(int(ab))+"*"
                        else:
                            xl=xl+str(int(ab))
                  photo_data.append(xl)
                  for n in range(len(ab)):
                        photo_data.append(int(ab))
            else:
                photo_data.append(ab)
      print(photo_data)
      print()
      sheet.append(photo_data)                            # 追加一条数据进Excel文件
      Ex_file.save(Photo_Path + '/照片信息检索.xlsx')       # 保存Excel文件

    Ex_file.close()                                       # 关闭Excel文件

    # file_object=open(Photo_Path + '/照片信息检索.xlsx')
    files_object = os.system(Photo_Path + '/照片信息检索.xlsx')
页: [1]
查看完整版本: python用于检查照片是否符合人脸识别使用要求