利用opencv实现抖音最强变脸术

本文介绍了如何利用opencv实现类似抖音的变脸效果。通过人脸关键点识别,结合平移、缩放、旋转和透视变换,实现了图像的组合变换。文章详细讲解了仿射变换的实现过程,包括平移、缩放和旋转的数学原理和opencv代码,并对比了两种不同的变换方法,最终展示了更接近抖音效果的透视变换实现。
摘要由CSDN通过智能技术生成

最近一个“最强变脸术”又火爆抖音啦,还不知道的朋友建议先打开抖音,搜索“最强变脸术”看个十来个视频再回来看这篇文章。视频看起来炫酷,其实本质就是图像的各种变换组合到一块的结果。那我们能不能也搞出一个来玩玩?我利用周末刷了两天抖音,不停的暂停、继续… 最终在尝试了仿射变换透视变换两种方案后,搞出了一个“低配版最强变脸术”。首先先来看看最终实现的效果(忽略gif颜色问题),也可以到http://www.iqiyi.com/w_19saz1z92h.html查看完整视频,然后从数学原理、opencv代码实现入手一步步的搞一个“最强变脸术”。

人脸关键点识别

看过“最强变脸术”的都知道,这个效果最基础的技术就是人脸识别。都2020年了,人脸识别当然不是多难的事了,可以选择的技术也很多,比如可以利用深度学习自己训练一个,也可以和我一样使用dlib这个三方库。

dlib用起来很简单,下面直接上代码了。

img = cv2.imread("./imgs/2.jpg")
dets = detector(img, 1)

shape = predictor(img, dets[0])
landmarks = []
for p in shape.parts():
    landmarks.append(np.array([p.x, p.y]))

for idx, point in enumerate(landmarks):
    cv2.putText(img, str(idx), (point[0], point[1]), fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
                fontScale=0.3, color=(0, 255, 0))
cv2.imshow("--", img)
cv2.waitKey()

运行上面的代码可以看到这样的结果:

请注意上面图中364529三个数字的位置,因为在下面仿射变换的版本中我们要用到。

版本一:仿射变换实现

人脸关键点搞定后的第一次尝试,我是用的图像仿射变换来实现的。通过不断观察,我拆解出了一下三种变换方式:

  1. 平移
  2. 缩放
  3. 旋转

平移

需要平移,是因为我们需要把两张图片上的人脸叠放到一块。平移的变换操作矩阵是:

[ 1 0 t x 0 1 t y ] \left[ \begin{matrix} 1 & 0 & tx \\ 0 & 1 & ty \end{matrix} \right] [1001txty]

例如我们要向右平移100个像素,向下平移50个像素,那么变换矩阵就应该是:

[ 1 0 100 0 1 50 ] \left[ \begin{matrix} 1 & 0 & 100 \\ 0 & 1 & 50 \end{matrix} \right] [100110050]

对应的运算是:

[ x ′ y ′ ] = [ 1 0 100 0 1 50 ] ∗ [ x y 1 ] \left[ \begin{matrix} x' \\ y' \\ \end{matrix} \right]=\left[ \begin{matrix} 1 & 0 & 100 \\ 0 & 1 & 50 \end{matrix} \right]*\left[ \begin{matrix} x \\ y \\ 1 \end{matrix} \right] [xy]=[100110050]xy1


{ x ′ = 1 ∗ x + 0 ∗ y + 100 ∗ 1 y ′ = 0 ∗ x + 1 ∗ y + 50 ∗ 1 \begin{cases} x'=1*x+0*y+100*1 \\ y'=0*x+1*y+50*1 \end{cases} { x=1x+0y+1001y=0x+1y+501

所以平移操作的本质就是对每个像素加上一个偏移量。下面是使用opencv对图像进行平移操作的代码:

img = cv2.imread("./imgs/2.jpg")
M = np.float32(
    [
        [1, 0, 100],
        [0, 1, 50]
    ]
)

dst = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
cv2.imshow("", dst)
cv2.waitKey()

运行上面的代码可以看到这样的结果:

缩放

需要缩放,是因为我们在人脸对齐的时候需要尽可能的保证两张人脸大小一致。缩放的变换操作矩阵是:

[ f x 0 0 0

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亓斌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值