python - 如何在python中使用MTCNN从文件夹中的图像中提取人脸?

Posted

技术标签:

【中文标题】python - 如何在python中使用MTCNN从文件夹中的图像中提取人脸?【英文标题】:How to face extraction from images in a folder with MTCNN in python? 【发布时间】:2021-03-14 06:26:32 【问题描述】:

我想用 Python 中的 mtcnn 从文件夹中的图像(大约有 8000 张图像)中提取人脸。我还必须将新图像保存到文件中。我怎么能这样做?我在 GPU 上使用 Jupyter 笔记本。 如果图像中有多个人脸,我应该遵循什么样的路径?

【问题讨论】:

【参考方案1】:

要添加到我之前的答案,这里是一个完整的解决方案。您必须安装 mtcnn、cv2 和 tensorflow。

from mtcnn import MTCNN
import cv2
import os
def crop_image(source_dir, dest_dir, mode):
    if os.path.isdir(dest_dir)==False:
        os.mkdir(dest_dir)
    detector = MTCNN()
    source_list=os.listdir(source_dir)
    uncropped_file_list=[]
    for f in source_list:
        f_path=os.path.join(source_dir, f)
        dest_path=os.path.join(dest_dir,f)
        img=cv2.imread(f_path)
        data=detector.detect_faces(img)
        if data ==[]:
            uncropped_file_list.append(f_path)
        else:
            if mode==1:  #detect the box with the largest area
                for i, faces in enumerate(data): # iterate through all the faces found
                    box=faces['box']  # get the box for each face                
                    biggest=0                    
                    area = box[3]  * box[2]
                    if area>biggest:
                        biggest=area
                        bbox=box 
                bbox[0]= 0 if bbox[0]<0 else bbox[0]
                bbox[1]= 0 if bbox[1]<0 else bbox[1]
                img=img[bbox[1]: bbox[1]+bbox[3],bbox[0]: bbox[0]+ bbox[2]] 
                cv2.imwrite(dest_path, img)
            else:
                for i, faces in enumerate(data): # iterate through all the faces found
                    box=faces['box']
                    if box !=[]:
                        # return all faces found in the image
                        box[0]= 0 if box[0]<0 else box[0]
                        box[1]= 0 if box[1]<0 else box[1]
                        cropped_img=img[box[1]: box[1]+box[3],box[0]: box[0]+ box[2]]
                        fname=os.path.splitext(f)[0]
                        fext=os.path.splitext(f)[1]
                        fname=fname + str(i) + fext
                        save_path=os.path.join(dest_dir,fname )
                        cv2.imwrite(save_path, cropped_img)  
       
    return uncropped_file_list

source_dir 是包含要裁剪的图像文件的目录的完整路径。 dest_dir 是要存储裁剪图像的完整路径。如果它不存在,该函数会为您创建它。模式如果设置为 1,则仅将图像文件中单个最大的人脸裁剪图像保存到 dest_dir。如果模式未设置为 1,则对于每个图像,如果图像中有多个人脸,则图像中所有裁剪的人脸都将保存到 dest_dir。在这种情况下,dest_dir 中保存的文件名具有附加了数字值的原始文件名。例如,如果图像文件名为护士,并且图像中有 3 个面孔,那么在 dest_dir 中将有 3 个名为护士 0、护士 1 和护士 2 的图像与该文件相关联。该函数返回未裁剪的图像文件的文件名列表。注意 MTCNN 并不完美,可能会出错,因此请目视检查裁剪后的图像。另请注意,如果图像中有多个面,则该函数不会返回图像中的所有面。它返回图像中最大人脸的裁剪图像。下图为使用示例

source_dir=r'c:\temp\people\dummy' # directory with files to crop
dest_dir=r'c:\temp\people\results' # directory where cropped images get stored
uncropped_files_list=crop_image(source_dir, dest_dir,1) # mode=1 means 1 face per image
for f in uncropped_files_list:
    print(f)

【讨论】:

谢谢分享。但我想裁剪所有图像,不仅从正面轮廓可见,而且从侧面轮廓可见。 我不认为 MTCNN 可以裁剪侧面轮廓。我不知道任何可用的模块,但我会四处搜索【参考方案2】:

下面的函数将读取位于 image_path 的图像并尝试裁剪图像。 如果图像中有超过 1 张人脸,该函数将返回图像中最大尺寸人脸的裁剪图像。如果在图像中未检测到人脸,该函数将返回状态为 false,图像返回为 None。您必须在您的环境中安装 tensorflow。

from mtcnn import MTCNN
import cv2
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
def crop_image(image_path):
    detector = MTCNN() 
    img=cv2.imread(image_path)
    data=detector.detect_faces(img)
    biggest=0
    if data !=[]:
        for faces in data:
            box=faces['box']            
            # calculate the area in the image
            area = box[3]  * box[2]
            if area>biggest:
                biggest=area
                bbox=box 
        bbox[0]= 0 if bbox[0]<0 else bbox[0]
        bbox[1]= 0 if bbox[1]<0 else bbox[1]
        img=img[bbox[1]: bbox[1]+bbox[3],bbox[0]: bbox[0]+ bbox[2]] 
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # convert from bgr to rgb
        return (True, img) 
    else:
        return (False, None)

以下是使用该功能并显示裁剪图像的示例

img_path=  # set this as the full path to the image you wish to crop
status,img=crop_image(img_path)
if status:
    plt.imshow(img)
else:
    print('No facial image was detected')

如果您想检测图像中的所有人脸,您可以轻松修改该功能

【讨论】:

以上是关于python - 如何在python中使用MTCNN从文件夹中的图像中提取人脸?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Boost.Python 在 Python 中调用内置函数

如何在vscode中使用python编写和运行代码

如何在 Python 3.x 和 Python 2.x 中使用 pip

如何使用 tkinter 在 python 中嵌入 python 解释器框架?

如何在 Spark 中使用 Python 查找 DataFrame 中的分区数以及如何在 Spark 中使用 Python 在 DataFrame 中创建分区

如何在 python 脚本中使用 awscli?