赞
踩
具体的实现步骤大致如下:
本文主要用两种方式实现对目标人脸进行打码,方法一是使用开源的第三方库face_recognition对人脸进行识别然后打码,法二是自己使用PaddleX下的模型库训练一个特定人脸的检测模型,然后打码
face_recognition是开源的第三方库,是世界上最简单的人脸识别库(这是它自己说的)下面是他的使用说明文档,啪,很快啊,很详细啊
首先当然是环境的配置,使用这个库需要首先确保已经安装了dlib,当然不管你有没有安装dlib,只需要下面这个命令,他就会帮它安装好相关的依赖
pip install face_recognition
这里主要是用到face_recognition库下face_recognition.load_image_file,face_recognition.face_encodings,face_recognition.face_locations,face_recognition.compare_faces这几个API函数
使用方法如下:
face_recognition.load_image_file(file,mode =‘RGB’ ),将图像文件(.jpg,.png等)加载到numpy数组中,返回值:图像内容为numpy数组
参数 | 解释 |
---|---|
file | 图像文件名或要加载的文件对象 |
mode | 将图像转换成的格式。仅支持“ RGB”(8位RGB,3通道)和“ L”(黑白) |
face_recognition.face_encodings(face_image,known_face_locations = None,num_jitters = 1,model =‘small’ )给定图像,返回图像中每个面部的128维面部编码,返回值:128维面部编码列表(图像中的每个面部一个)
参数 | 解释 |
---|---|
face_image | 包含一个或多个面部的图像 |
known_face_locations | 可选-每个面的边界框(如果已经知道的话) |
num_jitters | 计算编码时对面部重新采样的次数。越高越准确,但越慢(即100慢100倍) |
model | 可选-使用哪种模型。“大”或“小”(默认)仅返回5点,但速度更快 |
face_recognition.face_locations(img,number_of_times_to_upsample = 1,model =‘hog’ )返回图像中人脸边界框的数组,返回值: 以css(上,右,下,左)顺序找到的脸部位置的元组列表
参数 | 解释 |
---|---|
img | 图像(作为numpy数组) |
number_of_times_to_upsample | 对图像进行人脸向上采样的次数。数字越大,面孔越小 |
model | 要使用的人脸检测模型。“ hog”精度较低,但在CPU上更快。“ cnn”是经过GPU / CUDA加速(如果可用)的更准确的深度学习模型。默认值为“ hog”。 |
face_recognition.compare_faces(known_face_encodings,face_encoding_to_check,tolerance = 0.6 )将面部编码列表与候选编码进行比较,以查看它们是否匹配,返回值:真/假值列表,指示哪些known_face_encodings与面部编码匹配以进行检查
参数 | 解释 |
---|---|
known_face_encodings | 已知面部编码列表 |
face_encoding_to_check | 与列表进行比较的单一面部编码 |
tolerance | 认为相匹配的面孔之间的距离有多大。越低越严格。0.6是典型的最佳性能 |
下面实现的功能是,找到图像中的CXK的脸然后用篮球替换,实现打码
话不多说,上代码:
import cv2 import face_recognition # 打码图片 mask = cv2.imread('mask.jpg') # 读取视频 cap = cv2.VideoCapture('1.mp4') # 读取视频参数,fps、width、heigth fps = cap.get(5) width = cap.get(3) height = cap.get(4) # 设置写视频参数,格式为 mp4 size = (int(width), int(height)) # 定义编解码器并创建VideoWriter对象 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, fps, size) # 已知人脸 target = face_recognition.load_image_file("target.jpg") target_encoding = face_recognition.face_encodings(target)[0] while(cap.isOpened()): ret, frame = cap.read() if ret: # 检测人脸 face_locations = face_recognition.face_locations(frame) # 检测每一个人脸 for (top_right_y, top_right_x, bottom_left_y, bottom_left_x) in face_locations: temp_image = frame[top_right_y:bottom_left_y, bottom_left_x:top_right_x] temp = face_recognition.face_encodings(temp_image) if len(temp): temp_encoding=temp[0] # 对比结果 results = face_recognition.compare_faces([target_encoding], temp_encoding,tolerance = 0.5) # 是CXK,就将打码贴图。 if results[0] == True: mask = cv2.resize(mask, (top_right_x - bottom_left_x, bottom_left_y - top_right_y)) frame[top_right_y:bottom_left_y, bottom_left_x:top_right_x] = mask # 写入视频 out.write(frame) else: break # 完成工作后释放所有内容 cap.release() out.release()
下面是保存后的视频,感兴趣的小伙伴们,可以看看
视频传送门
这里是,实现对视频中的指定人脸进行打码,如果只要求对人脸进行打码,通过face_recognition也是可以实现的,也更简单,这里就不赘述了
这里还是使用PaddleX下的目标检测模型PPYOLO,这里使用该模型训练CXK的人脸图片,进行目标检测,实现目标人脸打码,不知道PaddleX怎么用的小伙伴,下面会附上PaddleX的说明文档,这里就不复述PaddleX怎么使用了(PS:百度飞桨的paddlepaddle深度学习框架真的很好用,小伙伴真的可以尝试一下)
这是我在AIStudio上该项目的链接,感兴趣的小伙伴可以看看
传送门
下面是训练代码:
# 环境变量配置,用于控制是否使用GPU # 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu import os os.environ['CUDA_VISIBLE_DEVICES'] = '0' from paddlex.det import transforms import paddlex as pdx # 定义训练和验证时的transforms # API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html train_transforms = transforms.Compose([ transforms.MixupImage(mixup_epoch=250), transforms.RandomDistort(), transforms.RandomExpand(), transforms.RandomCrop(), transforms.Resize( target_size=608, interp='RANDOM'), transforms.RandomHorizontalFlip(), transforms.Normalize() ]) eval_transforms = transforms.Compose([ transforms.Resize( target_size=608, interp='CUBIC'), transforms.Normalize() ]) # 定义训练和验证所用的数据集 # API说明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection train_dataset = pdx.datasets.VOCDetection( data_dir='work/CXK', file_list='work/CXK/train_list.txt', label_list='work/CXK/labels.txt', transforms=train_transforms, shuffle=True) eval_dataset = pdx.datasets.VOCDetection( data_dir='work/CXK', file_list='work/CXK/val_list.txt', label_list='work/CXK/labels.txt', transforms=eval_transforms) # 初始化模型,并进行训练 # 可使用VisualDL查看训练指标,参考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html num_classes = len(train_dataset.labels) # API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-yolov3 model = pdx.det.PPYOLO(num_classes=num_classes) # API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#train # 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html model.train( num_epochs=300, train_dataset=train_dataset, train_batch_size=4, eval_dataset=eval_dataset, learning_rate=0.000125, lr_decay_epochs=[210, 240], save_dir='output/ppyolo', use_vdl=True)
因为我只用了50几张图片进行的训练,并且这50几张图片都是从一个视频里提取的,所以效果并不是很好,但勉强可用
使用api进行预测,啪,很快啊
import paddlex as pdx
test_jpg = '17.jpg'
model = pdx.load_model('output/ppyolo/best_model')
# predict接口并未过滤低置信度识别结果,用户根据需求按score值进行过滤
result = model.predict(test_jpg)
# 可视化结果存储在./visualized_test.jpg, 见下图
pdx.det.visualize(test_jpg, result, threshold=0.5, save_dir='./')
实现大致效果如下:
下面就是使用通过模型预测获得的返回值,对视频进行打码,打码方法与法一相同
代码如下:
import cv2 import paddlex as pdx model = pdx.load_model('output/ppyolo/best_model') # predict接口并未过滤低置信度识别结果,用户根据需求按score值进行过滤 def bounding_box(outs): boxes = [] for out in outs: class_id = out['category_id'] if class_id == 0: # 0 is ID of CXK,当然其实这里没有不要进行category_id的筛选,应为这里就一种 confidence = out['score'] if confidence > 0.55: w = int(out['bbox'][2]) h = int(out['bbox'][3]) x = int(out['bbox'][0]) y = int(out['bbox'][1]) boxes.append([x, y, w, h]) return boxes # 打码图片 mask = cv2.imread('mask.jpg') # 读取视频 cap = cv2.VideoCapture('1.mp4') # 读取视频参数,fps、width、heigth fps = cap.get(5) width = cap.get(3) height = cap.get(4) # 设置写视频参数,格式为 mp4 size = (int(width), int(height)) # 定义编解码器并创建VideoWriter对象 fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter('output.avi', fourcc, fps, size) while(cap.isOpened()): ret, frame = cap.read() if ret: result = model.predict(frame) boxes = bounding_box(result) # 检测每一个人脸 if len(boxes): for (x,y,w,h) in boxes: mask = cv2.resize(mask, (w,h)) frame[y:y+h, x:x+w] = mask # 写入视频 out.write(frame) else: break # 完成工作后释放所有内容 cap.release() out.release()
下面是视频链接:
视频传送门
因为数据量太小,所以效果不是太好,但大体还行
木有了
如果有什么错误的地方,还请大家批评指正。最后,希望小伙伴们都能有所收获。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。