序1:
首先呢, 得感谢百度提供了AI的教师培训课程,这才使得我有机会接触并认真去搞整搞整百度提供的飞桨平台。其次呢,还是得感谢百度,再次提供了AI的教师培训课程。哈哈哈哈。有点绕吧,其实事情是这样的,以前也搞整过深度学习的研究,不过是用的tensorflow系列。我觉得,如今的国际形势。。。(扯远了,以下省略字数N万)。 总之就是得搞整一点国货,不然技术一封,我们这些技术人员不是得吃白饭了。于是在今年(2020年)5月的时候,就参加过一次百度提供的这个培训课程了,在各位老师的耐心指导下学到了不少的东西,5月的培训中,在讲到paddlehub 时,就开设了一个paddlehub的创意项目。当时,就有做这个火柴人的想法, 并且和当时的助教-熊熊讨论过,他也有过类似的相法,我们俩都觉得这个想法不错。但是5月份我学校的课程还没有结束,再加上技术上还有不少不太清楚的地方, 所以最后这个想法----搁浅了。 但是,(又是但是, 怎么那么多但是, 没法啊。语文没学好,今天晚上督促娃多读两篇语文书,不能吃我吃过的亏 。(娃:我好无辜 ),今年(2020年)7月,百度又再次提供了这样的机会,我居然有幸再次参加了这次的课程,两次课程的内容大致差不多, 不过,温故而知新嘛,又GET到了不少技能。在这次的创意项目中,我又再次想起了上次的点子,于是....开干吧。
序2:
火柴人GIF,火柴人视频,火柴人游戏,不知道多少人还记得这东东。画风给人独树一帜的感觉,很新奇,去掉了各种华丽的装饰,直入主题,动作感很突出。
其中以小小出品的火柴人游戏,更是当年的掌中明珠。
忘记的同学可以看看以下图片和链接:
火柴人游戏:
https://baike.baidu.com/item/火柴人小游戏/10896187?fr=aladdin
https://baijiahao.baidu.com/s?id=1578483231378609401&wfr=spider&for=pc
当年, 这个系列就给我留下了相当深刻的映像,于是,才有了今天的这个创意作品。
花絮
首先,感谢又来了。没法子,从小妈妈就教育我们要有一颗感恩的心。 这里要特别感谢 培训班的班班-倩倩,助教-余老师以及湖南大学的周老师,他们给了我不少的帮助和支持。
有了想法, 又有了技术和平台的支持(paddlehub),于是,继续开干吧。
首先参考了aistudio上别人的项目:
《图像分割任务--人像扣图实战》 链接: https://aistudio.baidu.com/aistudio/projectdetail/702576
该项目实现了从图片中扣人像的功能。 不过在复现这个项目的时候出现了点小问题,在用paddlehub 进行扣图时,一直无法存储扣图后的结果。 在助教余老师和湖南大学的周老师的帮助下,将这个BUG 修复了。其主要原因是,参数少了一坨。
原始代码:
results = module.segmentation(data=input_dict,output_dir=output_path)
这个用法可能是早期版本的,在目前python = 3.7, paddlepaddle = 1.8.0, paddlehub =1.6的环境下,一直无法把处理后的图像存放到指定目录。
经多次实验和查找相关资料,终于查到目前的正确用法,如下:
results = module.segmentation(data=input_dict,visualization=True,output_dir=output_path)
为了火柴人,最核心的地方就是动作,既然要有动作,那最方便的便是从视频中截取吧。于是又参考了另一个paddlehub的项目:
《PaddleHub抠图比赛》, 链接: https://aistudio.baidu.com/aistudio/projectdetail/377462
这个项目里,实现了视频转图片, 图片扣人像,加背景,生成视频4个部分。 (PS:这个项目里的扣图,也出现了上面提到的无法存图的问题。)
程序流程及算法
整个程序的流程以及核心技术方案最初设计如下:
视频抽帧(opencv) -> 扣人像(paddlehub) -> 人像二值化(opencv) -> 提取骨架(scikit-image) -> 生成视频(opencv)
在多次实验后发现,按照上面的流程做,提取骨架后,骨架很多地方就那么1-2个像素,看起来不是火柴人,而是丝线人,动作感的表达也不尽人意,然后呢,用OPENCV做二值 化,有点大材小用了,干脆采用了最简单粗暴的方法,直接把矩阵值大于 0 的置1,于是修改程序流程以及核心技术方案如下:
视频抽帧(opencv) -> 扣人像(paddlehub) -> 人像二值化(矩阵数值转换) -> 提取骨架(scikit-image) -> 骨架膨胀(opencv) -> 生成视频(opencv)
在实现过程中,也出现了一些小麻烦,PIL和CV两个库都有读图像、处理图像的函数,经常用混淆了,从而出现多个意外。在合成视频时,由于保存视频分辨率设置与扣图后的分辨率不同,使得保存的视频出错。 又或保存视频的FPS设置不当,使得视频看起来要么是快放,要么是慢动作。等等等等, 不过在不懈的努力下,终于搞好了。
老师当久了,就那毛病,P话F话特别多。哈哈哈。 说了那么多,我们来上干货吧。 先看看原始视频和处理后结果 。
原始视频 (这个论坛无法看视频,只能上几张截图来看看效果了。要看请移步本项目的分享链接,见本文最后) ( 这里吐槽下AISTUDIO 的论坛,不支持视频,不支持GIF动画,感觉有些太简陋了点。希望度娘的奶妈们能把这个论坛也奶大吧)
火柴人视频 (这个论坛无法看视频,只能上几张截图来看看效果了。要看请移步本项目的分享链接,见本文最后)
主要技术其实在上面的流程中已经写了。
在视频抽帧中,主要采用了
cap = cv2.VideoCapture(video_path) # 读取视频文件
cap.read() # 按帧读取视频
在扣人像步骤中, 主要采用了:
paddlehub 的 module.segmentation(data=input_dict,visualization=True, output_dir=out_path) # 扣取人像
在人像二值化中,先将像素值归一化后,直接使大于0的置1:
scope_map = np.array(in_image)[:,:,-1] / 255
img1 = np.int64(scope_map>0)
在骨架提取中,使用了Scikit-Image库:
# 首先安装 Scikit-Image库 :
!pip install Scikit-Image
# 然后用:
skeleton =morphology.skeletonize(img1) #对图像img1 进行骨架提取
在将骨架膨胀中用了opencv库的dilate函数:
kernel = np.ones((7,7),np.uint8) # 定义一个膨胀卷积核,里面的两个数字决定了膨胀的程度
dst = cv2.dilate(src,kernel) # 用kernel 对src 进行膨胀
最后采用opencv 中的VideoWriter_fourcc 和 VideoWriter函数把处理后的图片合成一个视频。
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(out_path,fourcc, FPS, size)
好了。 搞整了半个晚上来写代码,调程序 ,又搞整了半天来写篇BLOG分享一下自己的思路,技术,以及喜悦。从此以后, 终于可以方便的做自己的火柴人视频了。不过骨架提取的效果还是有待提升。
恩。差点忘了上整 个项目的链接:
https://aistudio.baidu.com/aistudio/projectdetail/702857
最后,还是给个QQ空间的本文的链接吧,上面能够看到GIF,和相关视频。 强调:不是打广告,所以我把这个写到最后, 字体也用得最小。希望大家能够理解。
https://user.qzone.qq.com/2198737/blog/1597041281
主人设置了权限,您可通过以下方式访问
厉害的样子
点个赞~
赞一个
哇哦,好炫酷,学习一个
有意思
+1
好玩~
哇塞!好厉害!
这也太强了吧
又刷到了