如何用 ModelScope 实现 “AI 换脸” 视频

网络 分享 时间: 收藏本文

如何用 ModelScope 实现 “AI 换脸” 视频

前言

当下,视频内容火爆,带有争议性或反差大的换脸视频总能吸引人视线。虽然 AI 换脸在市面上已经流行了许久,相关制作工具或移动应用也是数不胜数。但是多数制作工具多数情况下不是会员就是收费,而且替换模板有限。以下在实战的角度,用阿里 的图像人脸融合实现一下 AI 视频换脸。

流程

提供一段视频和一张替换的人脸图片,用 - 将视频根据帧率拆成图片,用 提取视频里的音频为单独文件 (mp3)。遍历目录下的每一帧的图片,通过 的人脸融合模型,传入新的人脸和帧率图片,得到替换过人脸的帧图片。最后再通过 - 将替换的人脸图片组合成新视频, 添加提取出的音频文件。

环境

1. 3.7.16

2. 1.4.2

3. - 4.7.0

4. 12.2.0

环境安装

1. 虚拟环境添加

conda create -n modelscope python=3.7 && conda activate modelscope

2. 安装 ,使用了国内镜像源

pip install modelscope --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple

3. 安装

pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

4. 安装

因为单是图片用不上,所以安装方法放在下面视频换脸里

图片换脸

1. 素材准备

我这里分别准备了一个画面里出现正脸,侧脸和两张脸的图片,然后分别用一张图片替换,最后运行代码查看效果。(可能是模型原因,感觉光看图片的换脸好像相差不大,倒有点像只是开了个美颜,也有可能是俩演员有点像,认真看还有有点不同)。

2. 代码部分

import cv2
from modelscope.outputs import OutputKeys
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
image_face_fusion = pipeline(Tasks.image_face_fusion, 
                       model='damo/cv_unet-image-face-fusion_damo')
template_path = '181.jpg'
user_path = 'face.jpg'
result = image_face_fusion(dict(template=template_path, user=user_path))
cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG])
print('finished!')

视频换脸

1. 安装

如果是 可以按我下面的选择, 是动态版本,不带的是静态版本,所有的功能都集合在一起。

2. 环境配置

下载后解压会生成一下目录,将 bin 文件放入电脑环境变量中,然后通过 - 查看是否安装成功。

3. 用法

3.1. 从视频中抽取音频 (输入视频和输出音频的地址可以是相对路径)

ffmpeg -i videos\11.mp4 -q:a 0 -map a audio\audio.mp3 

3.2. 将独立音频文件添加到视频里 (接收输入视频,输入音频,输出新视频)

ffmpeg -i videos/ldh.mp4 -i audio/audio.mp3 -c:v copy -c:a aac -strict experimental videos/new_ldh.mp4

4. 开始编码

from pathlib import Path
import cv2
import os
def video2mp3_img(video_path, save_path):
    def video_split(video_path, save_path):
        if not os.path.exists(save_path):
            os.makedirs(save_path)
        cap = cv2.VideoCapture(video_path)
        i = 0
        while True:
            ret, frame = cap.read()
            if ret:
                cv2.imwrite(save_path + '/' + str(i) + '.jpg', frame)
                i += 1
            else:
                break
        cap.release()
    if not os.path.exists(save_path):
        os.makedirs(save_path)
        
    # 视频分割
    video_split(video_path, save_path)
    
    # 视频转音频
    os.system("ffmpeg -i {} -q:a 0 -map a {}/audio.mp3".format(video_path, save_path))
def face_replace(user_path=""):
    from pathlib import Path
    import cv2
    from modelscope.outputs import OutputKeys
    from modelscope.pipelines import pipeline
    from modelscope.utils.constant import Tasks
    import os
    os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
    def my_function(img_path):
    
        image_face_fusion = pipeline(Tasks.image_face_fusion, model='damo/cv_unet-image-face-fusion_damo')
        template_path = img_path
        filename = os.path.splitext(os.path.basename(img_path))[0]
        
        # 替换面部依赖
        result = image_face_fusion(dict(template=template_path, user=user_path))
        cv2.imwrite(f'video_imgout/{filename}.jpg', result[OutputKeys.OUTPUT_IMG])
            
    threads = []
    BASE_PATH = os.path.dirname(__file__)
    
    for dirpath, dirnames, filenames in os.walk(r"D:\3code\3Python\modelscope\mv_face_change-main"):
        for filename in filenames:
            print(filename)
            if filename.endswith('.jpg'):
                file_path = Path(os.path.join(dirpath, filename))
                print(file_path)
                my_function(str(file_path))
def img2mp4(video_path, save_name):
    BASE_PATH = "D:\3code\3Python\modelscope\mv_face_change-main"
    img = cv2.imread("video_img/0.jpg")
    imgInfo = img.shape
    size = (imgInfo[1], imgInfo[0])
    
    files = []
    for dirpath, dirnames, filenames in os.walk(r"D:\3code\3Python\modelscope\mv_face_change-main\video_imgout"):
        for filename in filenames:
            fileName = Path(os.path.join(dirpath, filename))
            files.append(os.path.join(dirpath, filename))
    
    files = [file.replace('\\', '/') for file in files]
    files.sort(key=lambda x: int(x.split('/')[-1].split('.')[0]))
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    videoWrite = cv2.VideoWriter(r"D:\3code\3Python\modelscope\mv_face_change-main\videos\ldh.mp4", fourcc, 25, size)  # 写入对象 1 file name  3: 视频帧率
    for i in files:
        print(i)
        img = cv2.imread(str(i))
        videoWrite.write(img)
    
    # 将video_img中的音频文件添加到视频中
    os.system("ffmpeg -i {} -i {} -c:v copy -c:a aac -strict experimental {}".format("videos/ldh.mp4", "audio/audio.mp3", "videos/newlest_ldh.mp4"))
if __name__ == '__main__':
    BASE = os.path.dirname(__file__)
    video_path = os.path.join(BASE, "videos/demo.mp4")  
    save_path = os.path.join(BASE, "video_img")         
    # 视频  ==> imgs
    video2mp3_img(video_path, save_path)
    
    # 人脸替换
    face_replace(user_path='zsy.jpg')
    
    # imgs ==> 视频
    img2mp4(video_path, save_name='zsy')

5. 报错汇总

当运行上面代码,如果出现 file does not any ,那就是分离音频或追加音频到视频的这两个地方报的错误,大部分情况下输出路径不正确或命令参数不对。还有一个错误我没有记录,就是让视频压根没有声音,再执行分离操作时也会报错。这个是我上班时随便拿的视频测试 (因为不能戴耳机,刚好视频就是没声音的),所以使劲测使劲报错,换了视频就好了,关键是错误提示也没说是视频没声音。

6. 效果演示

由于时间原因,没有用杨过的视频,就用没有声音的视频做了换脸演示。以后还要对换脸图片替换做多线程处理。

信息流广告 网络推广 周易 易经 代理招生 二手车 网络营销 招生代理 旅游攻略 非物质文化遗产 查字典 精雕图 戏曲下载 抖音代运营 易学网 互联网资讯 成语 成语故事 诗词 工商注册 注册公司 抖音带货 云南旅游网 网络游戏 代理记账 短视频运营 在线题库 国学网 知识产权 抖音运营 雕龙客 雕塑 奇石 散文 自学教程 常用文书 河北生活网 好书推荐 游戏攻略 心理测试 好做题 石家庄人才网 考研真题 汉语知识 心理咨询 手游安卓版下载 兴趣爱好 网络知识 十大品牌排行榜 商标交易 单机游戏下载 短视频代运营 宝宝起名 范文网 电商设计 职业培训 免费发布信息 服装服饰 律师咨询 搜救犬 Chat GPT中文版 经典范文 优质范文 工作总结 二手车估价 实用范文 爱采购代运营 古诗词 衡水人才网 石家庄点痣 养花 名酒回收 石家庄代理记账 女士发型 搜搜作文 石家庄人才网 铜雕 词典 围棋 chatGPT 读后感 玄机派 企业服务 法律咨询 chatGPT国内版 chatGPT官网 励志名言 河北代理记账公司 文玩 朋友圈文案 语料库 游戏推荐 男士发型 高考作文 PS修图 儿童文学 买车咨询 工作计划 礼品厂 舟舟培训 IT教程 手机游戏推荐排行榜 暖通,电采暖, 女性健康 苗木供应 主题模板 短视频培训 优秀个人博客 包装网 创业赚钱 养生 民间借贷律师 绿色软件 安卓手机游戏 手机软件下载 手机游戏下载 单机游戏大全 免费软件下载 石家庄网络推广 石家庄招聘 石家庄网络营销 培训网 网赚 手游下载 游戏盒子 职业培训 资格考试 成语大全 英语培训 艺术培训 少儿培训 苗木网 雕塑网 好玩的手机游戏推荐 汉语词典 中国机械网 美文欣赏 红楼梦 道德经 网站转让 鲜花