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 中调用内置函数
如何在 Python 3.x 和 Python 2.x 中使用 pip
如何使用 tkinter 在 python 中嵌入 python 解释器框架?
如何在 Spark 中使用 Python 查找 DataFrame 中的分区数以及如何在 Spark 中使用 Python 在 DataFrame 中创建分区