用ModelScope带你制作小动画

本文涉及的产品
模型训练 PAI-DLC,100CU*H 3个月
交互式建模 PAI-DSW,每月250计算时 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
简介: 本文带你利用ModelScope把实际拍摄的视频转换为动画,基本原理是把视频解码成图像,使用人像卡通化模型对视频逐帧进行卡通化,再把多帧图像合并成视频,从而完成动画生成

平台概览

近日阿里发布的ModelScope(https://modelscope.cn/#/models) 平台,意在打造开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单。  这个平台上模型丰富度还可以,目前一共138个模型,其中55个可以通过在线demo体验效果,4个可以支持finetune(finetune还有待加强)。


卡通化模型介绍

打开模型库,映入眼帘的就是人像卡通化模型,不得不说这页面做的还挺好看的,不知道模型实际效果怎么样,是不是只是表面功夫做的好,那就拿第一个模型来小试牛刀把。

image.png

看模型页面上动图的转换效果还是挺好的,不禁想着,利用你给视频做个卡通化,那我是不是就可以生成动画了?  如果视频中没有人像,背景的卡通化效果是不是很好? 视频中有各种质量参差不齐的帧,正好也可以用来测试下模型的各种corner case。 话不多说,那就让我们开始把。


ModelScope的基本使用和环境搭建我就不重复了,大家自行参考文档:

https://modelscope.cn/#/docs/%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B



视频卡通化

先展示一个大概效果



首先,我们要理解下视频和图片的区别,视频一般是有视频和音轨两部分,视频部分可以理解为是若干张连续图片,如果我们可以吧这些图片提取出来,逐帧利用模型做卡通化生成新的图像,再把生成的图像合成视频,就可以得到一个小动画了。

因此,我们可以把视频卡通化拆解为如下步骤:

  1. 视频解码
  2. 批量图片卡通化
  3. 视频合成
  4. 音轨恢复


下面我们将分步骤介绍实现,并在本文最后给出了完成的可执行python代码


视频解码

首先,我们利用opencv进行视频解码,把解码后的图片存放在frames中

video=cv2.VideoCapture(video_file)
if (video.isOpened() ==False): 
print("Error reading video file")
# Read frameframes= []
i=0while(video.isOpened()):
i+=1# Capture frame-by-frameif(i%10):
print(f'loading {i} frames')
ret, frame=video.read()
ifret==True:
frames.append(frame)
else:
break# When everything done, release the video capture objectvideo.release()
print('loading video done.')


批量图片卡通化

首先,初始化卡通化pipeline

img_cartoon=pipeline('image-portrait-stylization', model='damo/cv_unet_person-image-cartoon_compound-models')

看文档示例,pipeline支持图片文件名输入, 不知道是不是支持图片数据的直接输入, 自己尝试了下OK,  然后又根据 官方pipeline的使用文档(https://modelscope.cn/#/docs/%E6%A8%A1%E5%9E%8B%E7%9A%84%E6%8E%A8%E7%90%86Pipeline) 介绍, 觉得应该是支持多张图片的输入,小心翼翼的尝试后果然也是可以的,为我的小机智感到自豪,也不得不说官方的文档细节做的还是不到位。


最终,采取如下代码完成批量图片卡通化,并把卡通化后的图片存在 result_frames

results=img_cartoon(frames)
result_frames= [r['output_img'] forrinresults]


另外不得不吐槽一下, 多张图片本地gpu推理跑的是真慢啊, 后来发现全是用的cpu。


视频合成

最后,通过opencv把多张图片再合成为视频,这里需要强调一下:

输出图片的尺寸和输入图片不同, 因此再设置输出视频大小的时候不能采用原始输入视频的大小,这个地方把我坑了半个小时debug。

frame_height, frame_width, _=result_frames[0].shapesize= (frame_width, frame_height)
# FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.# To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.#  r, _, _, _ = lstsq(X, U)foridxinrange(len(result_frames)):
result_frames[idx] =result_frames[idx].astype(np.uint8)
print(f'saving video to file {out_file}')
out=cv2.VideoWriter(out_file,cv2.VideoWriter_fourcc(*'mp4v'), fps, size)
forfinresult_frames:
out.write(f)
out.release()
print(f'saving video done')

此外,在保存视频的时候还发现另一个问题,有些视频帧转换会打印如下日志,导致输出的图片不再是unint8,而是float32类型,因此加上强制把每帧图片转换为uint8的逻辑

FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
r, _, _, _ = lstsq(X, U)

音轨还原

opencv没有提取音轨,音轨和视频合成的功能,我们利用MoviePy(https://zulko.github.io/moviepy/)来完成。


首先安装MoviePy

pip install ffmpeg moviepy


利用moviepy提取原始音轨

importmoviepy.editorasmpaudio_file='out.mp3'my_clip=mp.VideoFileClip(video_file)
my_clip.audio.write_audiofile(audio_file)


读取合成视频和原始音轨,生成带有声音的动画

frommoviepy.editorimportVideoFileClip, AudioFileClip# loading video dsa gfg intro videoclip=VideoFileClip(out_tmp_file)
# loading audio fileaudioclip=AudioFileClip(audio_file)
# adding audio to the video clipvideoclip=clip.set_audio(audioclip)
videoclip.write_videofile(out_file)
# save to gif# videoclip.write_gif(out_gif_file)


效果展示

鼓浪屿的树-详细对比

树的这个视频我认为是尝试的几个视频中效果最好的,虽然没有任务,但是效果看起来挺好的,看起来卡通化的背景部分对于纹理比较密集、颜色多样的画面效果会比较好。



大海

大海的效果还行,海鸥也都可以看到,注意这个是没有人像的背景卡通化,看起来和可以接受


沙滩


这个视频转换效果不太好, 原始视频上孩子的脸部没有强光,不知道为什么卡通化后脸上出现了异样。



问题整理

  1. 上传图片后模型一直处于模型加载过程,用户群反馈后已修复

image.png


  1. 看起来一直没有用gpu,虽然显存占用了,但是在用cpu计算,cpu利用率很高

image.png

image.png


  1. 第三个沙滩视频孩子脸部的badcase有待定位解决。



完整代码

使用方法:

修改video_file变量指向你的输入视频路径

修改out_file变量指定输出视频路径

python运行如下代码即可

importcv2importnumpyasnpfrommodelscope.hub.snapshot_downloadimportsnapshot_downloadfrommodelscope.pipelinesimportpipelinefrommoviepy.editorimportVideoFileClip, AudioFileClipimportlogginglogging.basicConfig(level=logging.INFO)
img_cartoon=pipeline('image-portrait-stylization', model='damo/cv_unet_person-image-cartoon_compound-models')
video_file='apps/gulangyu-tree.mp4'out_file='apps/gulangyu-tree_out.mp4'out_tmp_file='video_tmp.mp4'audio_file='audio_tmp.mp3'my_clip=VideoFileClip(video_file)
my_clip.audio.write_audiofile(audio_file)
logging.info('save audio file done')
logging.info(f'load video {video_file}')
video=cv2.VideoCapture(video_file)
fps=video.get(cv2.CAP_PROP_FPS)
if (video.isOpened() ==False): 
logging.info("Error reading video file")
# Read frameframes= []
i=0while(video.isOpened()):
i+=1# Capture frame-by-frameif(i%10):
logging.info(f'loading {i} frames')
ret, frame=video.read()
ifret==True:
# Display the resulting frameframes.append(frame)
else:
break# When everything done, release the video capture objectvideo.release()
logging.info('loading video done.')
results=img_cartoon(frames)
result_frames= [r['output_img'] forrinresults]
# We need to set resolutions for writing video and  convert them from float to integer.frame_height, frame_width, _=result_frames[0].shapesize= (frame_width, frame_height)
# FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.# To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.#  r, _, _, _ = lstsq(X, U)foridxinrange(len(result_frames)):
result_frames[idx] =result_frames[idx].astype(np.uint8)
logging.info(f'saving video to file {out_tmp_file}')
out=cv2.VideoWriter(out_tmp_file,cv2.VideoWriter_fourcc(*'mp4v'), fps, size)
forfinresult_frames:
out.write(f)
out.release()
logging.info(f'saving video done')
logging.info(f'merging audio and video')
# loading video dsa gfg intro videoclip=VideoFileClip(out_tmp_file)
# loading audio fileaudioclip=AudioFileClip(audio_file)
# adding audio to the video clipvideoclip=clip.set_audio(audioclip)
videoclip.write_videofile(out_file)
# save to gif# videoclip.write_gif(out_gif_file)logging.info('finished!')


目录
相关文章
|
计算机视觉
教你如何玩转Modelscope (一、图片编辑与描述生成)
本文通过一个有趣的图片处理例子,教你如何利用modelscope强大且多样的模型能力去解锁你专属的图片编辑能力。
3073 1
教你如何玩转Modelscope (一、图片编辑与描述生成)
|
机器学习/深度学习 编解码 自然语言处理
modelscope模型库列表
modelscope模型库列表
5987 0
|
1月前
|
自然语言处理 前端开发 开发者
使用 modelscope-studio 构建你的 Gradio 应用
modelscope-studio是一个基于 Gradio 的三方组件库,它可以为开发者提供更定制化的界面搭建能力和更丰富的组件使用形式。
|
5月前
|
人工智能 自然语言处理 API
ModelScope是什么
【9月更文挑战第1天】ModelScope是什么
897 2
|
2月前
|
人工智能 API 开发工具
ModelScope魔搭12月版本发布月报
为了给开发者提供更便捷的开源模型API访问方式,我们正式启动了 ModelScope API-Inference 的公测。在开源工具链方面,我们进行了ModelScope 1.21.0的新版本发布,提供了llamafile的集成以及模型加载/下载链路的优化,SWIFT 3.0大版本也已经合并主干,在这个基础上新模型的支持会更加顺畅与便利。
ModelScope魔搭12月版本发布月报
|
7月前
|
人工智能 开发者
基于ModelScope 实现图片 千变万换 ReplaceAnything
【7月更文挑战第17天】基于ModelScope 实现图片 千变万换 ReplaceAnything
|
9月前
|
机器学习/深度学习 人工智能 监控
ModelScope
ModelScope
287 9
|
存储 人工智能 Serverless
【收藏】制作艺术二维码,用 Stable Diffusion 就行!
艺术永远都不至于一种方式,基于函数计算部署 Stable Diffusion 制作艺术二维码,把你的艺术作品藏在二维码里面!
|
机器学习/深度学习 算法 uml
用 Modelscope 评测 Modelscope 是什么效果?
突发奇想是不是可以用机器的思想评测Modelscope 会出现什么结果?让我们一起看看吧。
1410 194
用 Modelscope 评测 Modelscope 是什么效果?
|
存储 机器学习/深度学习 缓存
ModelScope 模型库产品快速使用
ModelScope 的模型库(Model Hub)是共享机器学习模型、demo 演示、数据集和数据指标的地方。可以轻松地创建和管理自己的模型库,利用界面或开发环境来便捷地上传、下载相关模型文件,并从 Model Hub 中获取有用的模型和数据集元数据。
32891 1

热门文章

最新文章