楔子

西施沉鱼自苎萝 当为复越首功臣

昭君落雁出边塞 一平烽火即五旬

貂蝉月下邀对酌 离间巧计除奸恶

玉环香消马嵬坡 舍身为国安大唐----《王者四大美女–红昭愿》

目的

将b站很火的4小戏骨的红昭愿视频中相信很多人都看过,
里面的角色背景是我国古代四大美女。本人又是一个王者荣耀er,
所有就想到了将王者荣耀中四大美女的形象人脸替换到B站视频上面的创意。

项目地址

aistudio地址

github地址

bilibli视频地址

使用到的模型:

模型1pyramidbox_lite_mobile

模型2resnet_v2_18_imagenet

实现思路

     1.先将视频按帧提取保存为图片的集合2.然后使用paddlehub提供的pyramidbox_lite_mobile模型进行人脸位置检测,使用自己finetune的resnet_v2_18_imagenet模型对每一帧图片进行人脸识别。可能出现图片中没有人、图片中只有一个人、图片中有超过一个人三种情况。对于图中没有人,则不做任何操作;如果图中只有一个人,那么可以使用模型2精确分类该人物是谁,然后换上对应的贴图;如果图中使用模型1识别处理超过1人,则采用随机算法,随机给人脸换上贴图。3.将经过人脸分类+识别+贴图的图片集合使用cv2生成视频4.步骤3中生成的视频是没有bgm的,采用VideoFileClip给视频加上bgm

项目前期准备

首先需要有王者荣耀中四大美女的头像。博主于是打开了王者荣耀,截取了四个英雄的海报照片,然后使用ps将四个英雄的头像扣取了出来。本来是准备使用paddlehub提供的抠图模型的,但是貌似这个模型对于游戏人物的识别能力不是很强,所有还是回归了最初的ps。最终四大美女法师的头像如下。

下面是项目的一个文件目录结构:
face中放的就是上面的四张头像,底部是透明的
video中放的就是源视频

下面进入代码部分

工具函数部分:

def checkdir(dir_path):'''检查是否存在该文件,如果存在就删除了新建,不存在就新建:param dir_path:需要检测的路径:return:'''if os.path.exists(dir_path):shutil.rmtree(dir_path)os.makedirs(dir_path)if not os.path.exists(dir_path):os.makedirs(dir_path)def getvideoinfo(video_path):'''获取视频的帧率和撒小:param src_video:视频的地址:return: 帧率,视频大小fps: 25.0size: (720.0, 576.0)'''video_capture = cv2.VideoCapture(video_path)fps = video_capture.get(cv2.CAP_PROP_FPS)size = (int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT)))print("视频的fps: {}\n视频的size: {}".format(fps, size))return fps,size

finetune resnet_v2_18_imagenet模型对四个人进行识别:

class DemoDataset(BaseCVDataset):def __init__(self):# 数据集存放位置self.dataset_dir = "./train-data"super(DemoDataset, self).__init__(base_path=self.dataset_dir,train_list_file="train_list.txt",validate_list_file="validate_list.txt",test_list_file="test_list.txt",label_list_file="label_list.txt",)
def data_config_and_run():module = hub.Module(name="resnet_v2_18_imagenet")dataset = DemoDataset()print(dataset)data_reader = hub.reader.ImageClassificationReader(image_width=module.get_expected_image_width(),image_height=module.get_expected_image_height(),images_mean=module.get_pretrained_images_mean(),images_std=module.get_pretrained_images_std(),dataset=dataset)config = hub.RunConfig(use_cuda=False,  # 是否使用GPU训练,默认为False;num_epoch=4,  # Fine-tune的轮数;checkpoint_dir="cv_finetune",  # 模型checkpoint保存路径, 若用户没有指定,程序会自动生成;batch_size=10,  # 训练的批大小,如果使用GPU,请根据实际情况调整batch_size;eval_interval=10,  # 模型评估的间隔,默认每100个step评估一次验证集;strategy=hub.finetune.strategy.DefaultFinetuneStrategy())  # Fine-tune优化策略;# 组建FinetuneTaskinput_dict, output_dict, program = module.context(trainable=True)img = input_dict["image"]feature_map = output_dict["feature_map"]feed_list = [img.name]task = hub.ImageClassifierTask(data_reader=data_reader,feed_list=feed_list,feature=feature_map,num_classes=dataset.num_labels,config=config)# run the finetune task启动finetune任务run_states = task.finetune_and_eval()#如果第一次使用,请打开下面的注释,将人脸的分类模型训练一些
data_config_and_run()

使用前面一步训练好的模型对传入的图片进行人脸识别分类

def human_classfication(data):'''使用前面训练好的图片进行人脸识别分类:param data: 要检测的图片的地址:return: 人脸的标签(是谁)'''module = hub.Module(name="resnet_v2_18_imagenet")dataset = DemoDataset()# 模型构建data_reader = hub.reader.ImageClassificationReader(image_width=module.get_expected_image_width(),image_height=module.get_expected_image_height(),images_mean=module.get_pretrained_images_mean(),images_std=module.get_pretrained_images_std(),dataset=dataset)config = hub.RunConfig(use_cuda=False,  # 是否使用GPU训练,默认为False;num_epoch=4,  # Fine-tune的轮数;checkpoint_dir="cv_finetune",  # 模型checkpoint保存路径, 若用户没有指定,程序会自动生成;batch_size=10,  # 训练的批大小,如果使用GPU,请根据实际情况调整batch_size;eval_interval=10,  # 模型评估的间隔,默认每100个step评估一次验证集;strategy=hub.finetune.strategy.DefaultFinetuneStrategy())  # Fine-tune优化策略;# 组建FinetuneTaskinput_dict, output_dict, program = module.context(trainable=True)img = input_dict["image"]feature_map = output_dict["feature_map"]feed_list = [img.name]task = hub.ImageClassifierTask(data_reader=data_reader,feed_list=feed_list,feature=feature_map,num_classes=dataset.num_labels,config=config)task.load_checkpoint()# ##--------------开始预测label_map = dataset.label_dict()index = 0run_states = task.predict(data=data)results = [run_state.run_results for run_state in run_states]for batch_result in results:batch_result = np.argmax(batch_result, axis=2)[0]for result in batch_result:return result
前面的一些工具函数都已经准备好了,下面主要就是前面思路中的四个步骤,每一个一个函数实现

分成4步(4个函数)完成本任务

  1. 从视频中提取图片 function1
  2. 对图片进行王者荣耀贴图 function2
  3. 将进过face贴图处理的图片从新合成为视频 function3
  4. 视频添加声音

function1

# step1 从视频中提取图片
def extract_images(src_video, dst_dir):'''src_video:为目标的视频文件地址dst_dir:为视频图片的保存路径'''video = cv2.VideoCapture(src_video)count = 0while True:flag, frame = video.read()if not flag:breakcv2.imwrite(os.path.join(dst_dir, str(count) + '.png'), frame)count = count + 1print('extracted {} frames in total.'.format(count))

function2


# step2 对图片进行王者荣耀贴图
def face_chartlet(img_path,save_path):module = hub.Module(name="pyramidbox_lite_mobile")offset_length = 30 #人脸识别的框可能会比较小,给贴图加一个偏移值img = cv2.imread(img_path)# prep maskmasks = [cv2.imread('./work-hong/face/dc.png', -1),cv2.imread('./work-hong/face/wzj.png', -1),cv2.imread('./work-hong/face/xs.png', -1),cv2.imread('./work-hong/face/yyh.png', -1)]# set input dict 因为这个模型value为待检测的图片,numpy.array类型,shape为[H, W, C],BGR格式。所有使用cv2读取input_dict = {"data": [img]}results = module.face_detection(data=input_dict)img2 = img.copy()# 因为计划一次只传入一张图片,所有只需要取results的第一个元素就行了result_list = results[0]['data']if len(result_list) < 1:print('图中没有人脸,不做处理')elif len(result_list) == 1:print('图中只有一张人脸,先进行人脸识别,识别出对应的人脸后再进行贴图')index_ = human_classfication([img_path])for pos_result in result_list:# 获取人脸的位置left_pos, right_pos, top_pos, bottom_pos, _ = pos_result.values()# print(left_pos, right_pos, top_pos, bottom_pos)left_pos = int(left_pos)#将坐标值转换为int类型,防止后面计算出错right_pos = int(right_pos)top_pos = int(top_pos)bottom_pos = int(bottom_pos)# print(left_pos,right_pos,top_pos,bottom_pos)mask = cv2.resize(masks[index_],(int(right_pos - left_pos + offset_length), int(bottom_pos - top_pos + offset_length)))# 取出mask非0的值index = mask[:, :, 3] != 0index = np.repeat(index[:, :, np.newaxis], axis=2, repeats=3)try:img2[int(top_pos - offset_length / 2):int(bottom_pos + offset_length / 2), int(left_pos - offset_length / 2):int(right_pos + offset_length / 2), :][index] = mask[:, :, :3][index]except Exception as e:print(e)elif len(result_list) > 1:print('检测出了多张人脸,采用随机贴图的方式进行贴图')count = 0#对人脸识别中识别到的所有人脸进行随机贴图for pos_result in result_list:# 获取人脸的位置left_pos, right_pos, top_pos, bottom_pos, _ = pos_result.values()# print(left_pos, right_pos, top_pos, bottom_pos)left_pos = int(left_pos)right_pos = int(right_pos)top_pos = int(top_pos)bottom_pos = int(bottom_pos)mask = cv2.resize(masks[count],(int(right_pos - left_pos + offset_length), int(bottom_pos - top_pos + offset_length)))# mask = cv2.resize(masks[random.randint(0,3)], (int(right_pos - left_pos), int(bottom_pos - top_pos)))# 取出mask非0的值index = mask[:, :, 3] != 0index = np.repeat(index[:, :, np.newaxis], axis=2, repeats=3)try:img2[int(top_pos - offset_length / 2):int(bottom_pos + offset_length / 2), int(left_pos - offset_length / 2):int(right_pos + offset_length / 2), :][index] = mask[:, :, :3][index]except Exception as e:print(e)count += 1# 保存图片cv2.imwrite(os.path.join(save_path, os.path.basename(img_path)), img2)

function3


# step3image2video
#将进过face贴图处理的图片从新合成为视频
def img2video(dst_video_path,pic_path,size,frame):'''dst_video_path:合成视频的保存路径(包含文件名)pic_path:合成的所有图片的路径size:图片的大小,即是视频的大小frame:帧率VideoWriter_fourcc为视频编解码器fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符组成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符顺序不能弄混cv2.VideoWriter_fourcc('I', '4', '2', '0'),该参数是YUV编码类型,文件名后缀为.avicv2.VideoWriter_fourcc('P', 'I', 'M', 'I'),该参数是MPEG-1编码类型,文件名后缀为.avicv2.VideoWriter_fourcc('X', 'V', 'I', 'D'),该参数是MPEG-4编码类型,文件名后缀为.avicv2.VideoWriter_fourcc('T', 'H', 'E', 'O'),该参数是Ogg Vorbis,文件名后缀为.ogvcv2.VideoWriter_fourcc('F', 'L', 'V', '1'),该参数是Flash视频,文件名后缀为.flvcv2.VideoWriter_fourcc('m', 'p', '4', 'v')    文件名后缀为.mp4'''dst_video = cv2.VideoWriter(dst_video_path, cv2.VideoWriter_fourcc(*'mp4v'), frame, size, True)for index in range(len(os.listdir(pic_path))):frame = cv2.imread(os.path.join(pic_path,'{}.png'.format(index)))dst_video.write(frame)dst_video.release()

function4


# step4 给视频添加声音
def add_audio(s_video_path,d_video_path):'''给视频加声音:param s_video_path: 原视频地址-含有声音的:param d_video_path: 目的视频地址-需要加声音的:return:'''video_s = VideoFileClip(s_video_path)video_d = VideoFileClip(d_video_path)audio_o = video_s.audiovideo_dd = video_d.set_audio(audio_o)video_dd.write_videofile(d_video_path[0:d_video_path.rfind('/')+1]+'hong_audio.mp4')

主函数 依次执行上面四步即可:

if __name__ == '__main__':src_video = './work-hong/video/hong4-sing.mov'dst_img_dir = './work-hong/video-imgs'  #每一帧图片的保存路径# # step1 extract images of the videos# checkdir(dst_img_dir)# extract_images(src_video,dst_img_dir)# print('step1提取图片完成')# step2 give the face chartlet of each picsave_video_imgs = './work-hong/video-imgs-face' #贴图图片的保存路径checkdir(save_video_imgs)# 对当前路径下的所有图片进行贴图处理 后期可以改进为将所有图片都放入到data_list中,只需要进行一次模型的加载即可完成任务for i in tqdm(os.listdir(dst_img_dir)):face_chartlet(os.path.join(dst_img_dir,i),save_video_imgs)print('step2所有图片贴图完成')# step3 image2videodst_video_path = './work-hong/video-result'  #最终合成视频的保存路径checkdir(dst_video_path)video_name = 'hong-sing.mp4'dst_video_name = os.path.join(dst_video_path,video_name)fps,size = getvideoinfo(src_video)size = (int(size[0]),int(size[1]))img2video(dst_video_name, save_video_imgs, size, int(fps))print('step3将所有图片合成为视频完成')# step4 add the audioadd_audio(src_video, dst_video_name)print('step4给视频加声音完成')

最终效果

参见bilibili视频王者荣耀版红昭愿

总结

  1. 贴图已经增加了30个pixel的偏移了,还是不能遮住脸。应该是模型中的人脸定位的框太小了,后期可以稍微在调大一点。
  2. 对于一种图中有多人的情况采用的是随机贴图的方式,本来应该将图中的人脸部分切图图来然后进行分类再贴图的,但是一个原因是这样切图出来的进行人脸分类的效果不好,另一个原因是因为在一幅图中有很多人的情况下,这次使用的人脸定位模型并不能将一些小的脸给精准定位。
  3. 后期还可以做一个将人的身子扣出来然后用王者荣耀中的人物模型替换的创意

paddlehub创意赛《王者四大美女--红昭愿》相关推荐

  1. 百度AIStudio之PaddleHub创意赛:你的名字,你的Face

    百度AIStudio之PaddleHub创意赛:你的名字,你的Face 使用<你的名字>动漫中的图片拼出你的人脸.本项目为 PaddleHub:人脸检测主题创意赛.实现自动检测人脸,然后实 ...

  2. Paddlehub创意赛---给人像增加背景

    Paddlehub创意赛---给人像增加背景 Paddlehub创意赛 首先配置环境 导入相关的库 展示原图 使用Paddlehub进行抠图操作 关键点检测 合并背景 Paddlehub创意赛总结 P ...

  3. (记录)PaddleHub创意赛:AI人像抠图及图像合成

    文章目录 PaddleHub创意赛:AI人像抠图及图像合成 一.安装环境(这里面有几个坑) 二.接下来就``开始P图 1. 引入包 2. 加载预训练模型(挺厉害的不得不说) 3. 图像合成 Paddl ...

  4. 计算机音乐谱红昭愿,天谕手游红昭愿乐谱代码是什么-天谕手游红昭愿乐谱代码分享_快吧手游...

    天谕手游红昭愿乐谱代码是什么?天谕中我们可以使用外部代码复制到游戏中,然后制作出自己的音乐乐谱.很多小伙伴都想把这一首歌写进自己的天谕乐谱.下面就一起来看看吧! 天谕手游红昭愿乐谱代码分享 t115v ...

  5. 计算机音乐谱红昭愿,天谕手游红昭愿乐谱代码分享

    天谕手游红昭愿乐谱代码是什么?<红昭愿>是来自音阙诗听音乐社的一首歌曲,由荒唐客填词,殇小谨谱曲,朱鸽编曲,由音阙诗听歌手王梓钰演唱,2020年9月24日,发行了由李玉刚演唱的<红昭 ...

  6. 红昭愿用计算机按的歌谱,红昭愿简谱-音阙诗听演唱-孙世彦曲谱

    红昭愿简谱 作曲 : 殇小谨 作词 : 荒唐客(偏生梓归) 手中雕刻生花 刀锋千转蜿蜒成画 盛名功德塔 是桥畔某处人家 春风绕过发梢红纱 刺绣赠他 眉目刚烈拟作妆嫁 轰烈流沙枕上白发 杯中酒比划 年少 ...

  7. 【PaddleHub创意赛】APP评论情感分析

    项目链接 无意中测试了一下paddlehub的情感分析的(唯一的三分类模型)预训练模型emotion_detection_textcnn,发现英文的准确度好像没有中文高? 同一句话的中英文测试: im ...

  8. 创意赛第二季又来了,PaddleHub人脸关键点检测实现猫脸人嘴特效

    前段时间,下班后闲来无事,参加了百度PaddleHub的AI人像抠图创意赛,凭借着大家的阅读量,获得了一个第三名,得了一个小度音响,真香啊! 对,说的是我 小奖品 PaddleHub创意赛第二期又出来 ...

  9. 【飞桨PaddlePaddle学习心得】paddle学习创意赛-人脸抠图

    目标 paddlehub项目链接:https://aistudio.baidu.com/aistudio/projectdetail/437104 PaddleHub DeepLabv3+模型(dee ...

最新文章

  1. matlab subs
  2. 多线程-Thread-Runnable
  3. Android 第十六课 使用LitePal查询数据
  4. C# datagridview、datagrid、GridControl增加行号
  5. vue 指令 v-for 遍历数组
  6. linux下查看内存频率,内核函数,cpu频率
  7. Java逐帧动画播放器V0.1.0
  8. 魔抓编程_编程中的魔数是什么?
  9. 使用频谱仪测试信号抗干扰实验
  10. android应用流程图,Android APP 启动流程简析
  11. html如何解决412问题,网站412怎么解决?
  12. 环境微生物学练习题及答案
  13. 【CPU设计实战】简单流水线CPU设计
  14. 编码规则的发展历程(通俗版)
  15. python图像几何变换_python 图像工具opencv3实例(对象识别和增强现实)1-图像几何转换...
  16. solr mysql dih_Solr结构化数据导入DIH
  17. 常用计算机的外设有哪些,电脑外设设备有哪些 电脑外设产品什么品牌好
  18. 山东职业学院的计算机网络技术,2017年山东信息职业技术学院计算机网络技术教学质量...
  19. 电商微信小程序的开发,项目及功能描述
  20. java计算机毕业设计汽车售后服务信息管理系统的设计与实现源程序+mysql+系统+lw文档+远程调试

热门文章

  1. quartus 中直接引用的延时模块(Modelsim已验证)
  2. 电脑黑客或电脑天才方面的电影
  3. iis安装ssl证书
  4. EXCEL——VLOOKUP双条件匹配
  5. 店宝宝谈男士护肤美妆:千亿风口,巨头争锋
  6. 学计算机买笔记本是i5 i7,对我们普通人买电脑来说,i7和i5、i3有多大区别,玩游戏选哪款好?!...
  7. android开发-常用色彩
  8. BUUCTF-网鼎杯2020-青龙组-joker
  9. java 8——Stream
  10. 当对手有 45 亿资金、1 亿用户,你怎么办?