音视频开发之旅(74)- AI数字人-实现图像无缝融合

在做数字人时,会遇到一个问题,如何把头部说话的视频和原始图片/视频合在一起,这里就涉及到很有意思的图像无缝融合的技术, 我们一起来学习下吧

目录

  1. 融合的效果

  2. 拉普拉斯金字塔

  3. 泊松融合

  4. 参考资料

一、融合的效果

拉普拉斯金字塔进行图像融合 基本看不出来是有两类水果图片融合的

使用泊松融合,对生成的头部视频和原视频进行融合

对原图第一帧进行人脸检测和裁剪(具体实现可参考上一篇文章),然后以这个点对人脸进行裁剪,然后根据音频驱动嘴型说话,以及原来的视频眨眼和头部动作作为参考,生成新的头部视频, 最终把生成的头部视频逐帧和源视频进行融合,生成最终带身体和手部动作的视频.

二、拉普拉斯金字塔(Laplacian Pyramid)

2.1 介绍

对图片先逐级进行下采样,然后再逐级进行上采样,通过从高斯金字塔的连续两层之间计算差值来构建的,用于捕获图像在不同尺度下的细节信息

图片来自: 拉普拉斯金字zhuanlan.zhihu.com/p/454085730

拉普拉斯的用处可以分为两大类, 对图像进行压缩 和对图像进行融合

通过先下采样再上采样,然后对上采样的,得到拉普拉斯金字塔,然后再和逐级上采样的图片进行相加即可恢复为原图, 即是无损的. 如果我们对图片中变化比较小的低频分量进行剔除,只保留更多细节的高频分量(即边缘轮廓),损失一部分不明显的信息,再进行恢复 可以实现图片压缩的效果.

下面我们看下如何通过拉普拉斯金字塔实现图像融合

2.2 图像融合原理以及代码实现

对两张图片进行融合需要一个Mask图,指定从图片中哪些区域需要进行融合,比如文章开头的两种水果的融合,取左边一半进行融合(用全1 白色表示),右边一半进行保留(用全0 黑色表示)

完整代码实现如下

ini 复制代码
import numpy as np
import cv2
# 修复尺寸不匹配的问题
def fix_size(img, target):    
    if img.shape[0] != target.shape[0] or img.shape[1] != target.shape[1]:
        img = cv2.resize(img, (target.shape[1], target.shape[0]), interpolation=cv2.INTER_LINEAR) 
    return img

# 拉普拉斯金字塔图像融合实现
def Laplacian_Pyramid_Blending_with_mask(A, B, m, num_levels=6):
    gpA = [A.copy()]
    gpB = [B.copy()]
    gpM = [m.copy()]    
#先机型下采样,获取高斯金字塔
    for i in range(num_levels):
        gpA.append(cv2.pyrDown(gpA[i]))
        gpB.append(cv2.pyrDown(gpB[i]))
        gpM.append(cv2.pyrDown(gpM[i]))
    #再逐层根据上一层的高斯图以及当前层上采样结果想减获取拉普拉斯金字塔
    lpA = [gpA[num_levels]]
    lpB = [gpB[num_levels]]
    for i in range(num_levels, 0, -1):
        LA = cv2.subtract(gpA[i-1], fix_size(cv2.pyrUp(gpA[i]), gpA[i-1]))
        LB = cv2.subtract(gpB[i-1], fix_size(cv2.pyrUp(gpB[i]), gpB[i-1]))
        lpA.append(LA)
        lpB.append(LB)
    #根据mask进行融合
    LS = []
    for la, lb, gm in zip(lpA, lpB, gpM):
        gm = fix_size(gm, la)
        #通过np.newaxis添加一个维度, 把二维的mask图转为和AB图一样三通道的图片
        print(f"gm.ndim:{gm.ndim},gm:{gm.shape},la:{la.shape},lb:{lb.shape}")
        gm = gm[..., np.newaxis] if gm.ndim == 2 else gm
        la = fix_size(la, gm)
        lb = fix_size(lb, gm)
        ls = la * gm + lb * (1.0 - gm)
        LS.append(ls)
    #根据拉普拉斯金字塔重建图片
    ls_ = LS[0]
    for i in range(1, num_levels + 1):
        ls_ = fix_size(cv2.pyrUp(ls_), LS[i])
        ls_ = cv2.add(ls_, LS[i])
    ls_ = fix_size(ls_, A)
    ls_ = np.clip(ls_, 0, 255).astype('uint8')
    return ls_

需要注意的是:基于 laplace 金字塔的图像拼接限制挺大的,对两张图片匹配性有很高的要求(尺寸大小以及融合位置)

三、泊松融合(Poisson Blending)

3.1 介绍

泊松融合可以将一个图像区域无缝地融合到另一个图像中,在保持图像渐变的前提下调整图像的像素值,不仅能够保留源图像的细节和结构,又能自然地适应目标图像的颜色和亮度,使得融合区域与周围环境看起来更自热协调。比如下面的融合效果

图片来自:github.com/Erkaman/poi...

3.2 原理和代码实现

泊松融合处理图像的梯度域而非直接在像素值上操作,具体来说,它通过解泊松方程来编辑图像的一个区域,让选择的图像区域无缝地融入到目标图像中,使得融合区域内的梯度与源图像相匹配,同时边界与目标图像平滑对接

泊松融合通常涉及以下步骤:

  1. 选择源图像(要复制的图像)和目标图像(要粘贴到的图像)。

  2. 在源图像上定义一个蒙版,标记出需要融合的区域。

  3. 计算源图像在蒙版区域内的梯度(颜色变化)。

  4. 解决泊松方程,使得融合区域内的梯度与源图像相匹配,同时边界与目标图像平滑对接。

    opencv中封装了seamlessClone接口来实现泊松融合 cv.seamlessClone(src, dst, mask, p, flags[, blend]) ->blend src:输入8位3通道图像(截取目标的大图) dst:输入8位3通道图像(待粘贴融合的目标背景图) mask:输入8位1或3通道图像(目标掩码区域图像) p:对象被放置在目标图像dst中的位置 blend:输出图像,与dst具有相同大小和类型。 flags:克隆方法可以是NORMAL_CLONE,MIXED_CLONE或MONOCHROME_TRANSFER

    NORMAL_CLONE: 不保留dst 图像的texture细节。目标区域的梯度只由源图像决定。 MIXED_CLONE: 保留dest图像的texture 细节。目标区域的梯度是由原图像和目的图像的组合计算出来(计算dominat gradient)。 MONOCHROME_TRANSFER: 不保留src图像的颜色细节,只有src图像的质地,颜色和目标图像一样,可以用来进行皮肤质地填充

使用如下

ini 复制代码
#resize人脸裁剪并且根据音频驱动生成的视频帧 
oy1, oy2, ox1, ox2  = crop_info[1]
p = cv2.resize(crop_frame.astype(np.uint8), (ox2-ox1, oy2 - oy1)) 
#生成裁剪人脸大小的mask,赋值为白色(即融合区域全部使用crop_frame)
mask = 255*np.ones(p.shape, p.dtype)
#融合的中心点
location = ((ox1+ox2) // 2, (oy1+oy2) // 2)
#使用seamlessClone(通过柏松融合实现)的NORMAL_CLONE的类型进行crop_frame和原始图片进行融合
gen_img = cv2.seamlessClone(p, full_img, mask, location, cv2.NORMAL_CLONE)

四. 参考资料

  1. 拉普拉斯金字塔 zhuanlan.zhihu.com/p/454085730

  2. OpenCV图像无缝融合-seamlessClone介绍与使用 blog.csdn.net/stq054188/a...

3.计算机视觉:泊松融合 drustz.com/posts/2015/...

4.poisson_blend:github.com/Erkaman/poi...

感谢你的阅读

接下来我们继续学习输出AIGC相关内容,关注公众号"音视频开发之旅",一起学习成长。

欢迎交流

相关推荐
爱吃的小肥羊4 小时前
我整理了 14 种 GPT-Image-2 的神仙玩法,大家看看效果怎么样!
aigc·openai
刘 大 望6 小时前
RAG相关技术介绍及Spring AI中使用--第三期
java·人工智能·后端·spring·机器学习·ai·aigc
阿杰学AI6 小时前
AI核心知识132—大语言模型之 AI for Science(简洁且通俗易懂版)
人工智能·ai·语言模型·自然语言处理·aigc·ai for science·ai4s
用户5191495848458 小时前
Windows Hypervisor 分区漏洞利用与 IOCTL 通信测试工具
人工智能·aigc
用户6757049885029 小时前
【AI开发实战】从想法到上线,我用AI全栈开发了一款记账微信小程序
后端·aigc·ai编程
用户6757049885029 小时前
全网都在推 Claude Code,但只有这篇文章教你如何“真正”能用
后端·aigc·claude
用户51914958484510 小时前
Automad 2.0.0-alpha.4 存储型跨站脚本(XSS)漏洞利用
人工智能·aigc
民乐团扒谱机11 小时前
基于ArkTS与端云协同的鸿蒙智慧校园助手——项目报告(AIGC预警⚠️)
华为·aigc·harmonyos
日光明媚11 小时前
DMD 一步扩散核心原理:从符号定义到梯度推导
人工智能·机器学习·计算机视觉·ai作画·stable diffusion·aigc
captain_AIouo12 小时前
OZON运营全场景导入,Captain AI系统功能适配效果
大数据·人工智能·经验分享·aigc