前言

在抖音中,我们经常看到各种抖音玩家都喜欢使用哈哈镜效果。那么什么是哈哈镜呢?

在现实生活中,哈哈镜是指一种表面凹凸不平的镜子,可以反应出人像及物体的扭曲面貌。简单点来说就是拉伸人脸(物件),或者压缩人脸(物体)的效果。

哈哈镜实现原理

假设输入图像的宽高为wh,图像中心点的坐标为(cx,cy)。那么图像中任意一点(x,y)到中心点的距离为(x-cx)(y-cy)

那么拉升放大,图像变换的半径为r(r是哈哈镜的范围大小),得到公式如下:

x=(tx/2)(sqrt(txtx+tyty)/r)+cx
y=(ty/2)(sqrt(txtx+tyty)/r)+cy

同理,压缩缩小的公式如下(compress为压缩强度):

x=cos(atan2(ty,tx))compresssqrt(sqrt(txtx+tyty))+cx
x=cos(atan2(ty,tx))compresssqrt(sqrt(txtx+tyty))+cy

原始图像:

基于OpenCV的哈哈镜放大实现

既然我们了解了其数学公式以及其实现的原理,下面我们来直接实现哈哈镜的放大效果。具体代码如下所示:

import cv2
import math
#哈哈镜放大效果实现
def enlarge_effect(img):
h, w, n = img.shape
cx = w / 2
cy = h / 2
radius = 100#该值可以自行定义,它决定了哈哈镜的大小,当图像很大时,应该相应的调大
r = int(radius / 2.0)
new_img = img.copy()
for i in range(w):
for j in range(h):
tx = i - cx
ty = j - cy
distance = tx * tx + ty * ty
if distance < radius * radius:
x = int(int(tx / 2.0) * (math.sqrt(distance) / r) + cx)
y = int(int(ty / 2.0) * (math.sqrt(distance) / r) + cy)
if x < w and y < h:
new_img[j, i, 0] = img[y, x, 0]
new_img[j, i, 1] = img[y, x, 1]
new_img[j, i, 2] = img[y, x, 2]
return new_img if __name__ == "__main__":
img = cv2.imread("4.jpg")
enlarge_img = enlarge_effect(img)
cv2.imshow("4", enlarge_img)
cv2.waitKey()
cv2.destroyAllWindows()

运行后的效果:

需要注意的是,上面的计算过程可能导致有浮点数的出现,而像素值必须为整数。所以,为了保证像素值的有效性,必须在计算过程完整之后,进行强制类型转换int()。另外,计算x,y值时,可能会导致超过图像坐标的范围,所以必须用x<w和y<h来判断防止越界。

基于OpenCV的哈哈镜缩小实现

具体代码如下所示:

import cv2
import math #哈哈镜缩小效果实现
def reduce_effect(img):
h, w, n = img.shape
cx = w / 2
cy = h / 2
radius = 100
r = int(radius / 2.0)
compress = 8
new_img = img.copy()
for i in range(w):
for j in range(h):
tx = i - cx
ty = j - cy
x = int(cx + (math.sqrt(math.sqrt(tx * tx + ty * ty)) * compress * math.cos(math.atan2(ty, tx))))
y = int(cy + (math.sqrt(math.sqrt(tx * tx + ty * ty)) * compress * math.sin(math.atan2(ty, tx))))
if x < 0 and x > w:
x = 0
if y < 0 and y > h:
y = 0
if x < w and y < h:
new_img[j, i, 0] = img[y, x, 0]
new_img[j, i, 1] = img[y, x, 1]
new_img[j, i, 2] = img[y, x, 2]
return new_img if __name__ == "__main__":
img = cv2.imread("lena.jpg")
frame = reduce_effect(img)
cv2.imshow("lena1", img)
cv2.imshow("lena2", frame)
cv2.waitKey()
cv2.destroyAllWindows()

运行后的效果如下:

视频实现哈哈镜效果

抖音上面的哈哈镜都是动态的,并不是单一的图片这么变来变去。其实,只要我们集合摄像头视频录制功能,就可以完成视频哈哈镜的动态效果。具体代码如下:

import cv2
import math #哈哈镜放大效果实现
def enlarge_effect(img):
h, w, n = img.shape
cx = w / 2
cy = h / 2
radius = 100#该值可以自行定义,它决定了哈哈镜的大小,当图像很大时,应该相应的调大
r = int(radius / 2.0)
new_img = img.copy()
for i in range(w):
for j in range(h):
tx = i - cx
ty = j - cy
distance = tx * tx + ty * ty
if distance < radius * radius:
x = int(int(tx / 2.0) * (math.sqrt(distance) / r) + cx)
y = int(int(ty / 2.0) * (math.sqrt(distance) / r) + cy)
if x < w and y < h:
new_img[j, i, 0] = img[y, x, 0]
new_img[j, i, 1] = img[y, x, 1]
new_img[j, i, 2] = img[y, x, 2]
return new_img #哈哈镜缩小效果实现
def reduce_effect(img):
h, w, n = img.shape
cx = w / 2
cy = h / 2
radius = 100
r = int(radius / 2.0)
compress = 8
new_img = img.copy()
for i in range(w):
for j in range(h):
tx = i - cx
ty = j - cy
x = int(cx + (math.sqrt(math.sqrt(tx * tx + ty * ty)) * compress * math.cos(math.atan2(ty, tx))))
y = int(cy + (math.sqrt(math.sqrt(tx * tx + ty * ty)) * compress * math.sin(math.atan2(ty, tx))))
if x < 0 and x > w:
x = 0
if y < 0 and y > h:
y = 0
if x < w and y < h:
new_img[j, i, 0] = img[y, x, 0]
new_img[j, i, 1] = img[y, x, 1]
new_img[j, i, 2] = img[y, x, 2]
return new_img if __name__ == "__main__":
cap = cv2.VideoCapture("video.mp4")
while (cap.isOpened()):
ret, frame = cap.read()
enlarge_img = enlarge_effect(frame)
frame = reduce_effect(frame)
cv2.imshow('video1', enlarge_img)
cv2.imshow('video2', frame)
c = cv2.waitKey(1)
if c == 27:
break
cap.release()
cv2.destroyAllWindows()

OpenCV开发实战1——抖音哈哈镜效果的更多相关文章

  1. Python音视频开发:消除抖音短视频Logo和去电视台标

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...

  2. Python音视频开发:消除抖音短视频Logo的图形化工具实现

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 在<Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解>节介绍了怎么通过Python+Moviepy+OpenCV实现 ...

  3. python 手机App数据抓取实战二抖音用户的抓取

    前言 什么?你问我国庆七天假期干了什么?说出来你可能不信,我爬取了cxk坤坤的抖音粉丝数据,我也不知道我为什么这么无聊. 本文主要记录如何使用appium自动化工具实现抖音App模拟滑动,然后分析数据 ...

  4. Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...

  5. uni-app仿抖音APP短视频+直播+聊天实例|uniapp全屏滑动小视频+直播

    基于uniapp+uView-ui跨端H5+小程序+APP短视频|直播项目uni-ttLive. uni-ttLive一款全新基于uni-app技术开发的仿制抖音/快手短视频直播项目.支持全屏丝滑般上 ...

  6. 抖音抖一抖-SVG和CSS视觉故障艺术小赏

    故障艺术,英文名称叫glitch,在很多赛博朋克作品中经常看到,其实就是故意表现一种显示设备的小故障效果,抖音的图标其实就是这种的效果,我们看下这个图标 这个图标中的红色和蓝色的偏移其实就是一种故障艺 ...

  7. 抖音短视频爆火的背后到底是什么——如何快速的开发一个完整的直播app

    前言 今年移动直播行业的兴起,诞生了一大批网红,甚至明星也开始直播了,因此不得不跟上时代的步伐,由于第一次接触的原因,因此花了很多时间了解直播,今天我来教你从零开始搭建一个完整的直播app,希望能帮助 ...

  8. 我的大学Android开发学习之路——从开始到微信/支付宝/抖音Offer

    前言 笔者2016年高考考入华中科技大学计算机科学与技术专业. 2017年底(大二寒假)拿到今日头条(字节跳动)深圳研发中心Android开发实习生Offer,在深圳研发中心实习至2018年3月. 2 ...

  9. 一个类似抖音 APP 拍摄按钮效果的控件

    TouchButton 一个类似抖音 APP 拍摄按钮效果的控件 效果图预览 用法 <net.angrycode.library.TouchButton android:id="@+i ...

随机推荐

  1. Hack The Box - Archetype

    攻略的话在靶场内都有,也有官方的攻略,我作为一个技术小白,只是想把自己的通关过程记录下来,没有网站内大佬们写得好 我们获得了一个IP: 尝试访问了一下,应该不存在web页面: 对常规端口进行一个扫描: ...

  2. linux当前运行进程

    一:linux查询服务器服务进程 inux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照, 就是执行ps命令的那个时刻的 ...

  3. HTML <video>

    HTML <video> 元素 用于在HTML或者XHTML文档中嵌入媒体播放器,用于支持文档内的视频播放.你也可以将 <video> 标签用于音频内容,但是 <audi ...

  4. vue 访问页面时报错 Failed to compile

    这个是因为node-sass没安装好,所以要重新安装 windows下运行命令:npm install node-sass --registry=https://registry.npm.taobao ...

  5. JVM垃圾回收器总结

    常见七种垃圾回收器以及使用的垃圾回收算法总结:

  6. Map&Set的理解

    Set子接口 特点:无序.无下标.元素不可重复. 方法:全部继承自Collection中的方法. Set实现类 HashSet: 基于HashCode实现了不重复. 当存入元素的哈希码相同时,会调用e ...

  7. 从零搭建springboot服务01-初始搭建、内嵌swagger

    愿历尽千帆,归来仍是少年 1.基础springBoot框架 编辑工具:IDEA.jdk1.8.tomcat8.maven3.3.9 编码格式:UTF-8 参考文献:https://www.cnblog ...

  8. 一文学完makefile语法

    一.开始 1.Hello World 新建一个makefile文件,写入如下内容, hello: echo "Hello World" clean: echo "clea ...

  9. CentOS7中下载RPM及其所有的依赖包

    CentOS7中下载RPM及其所有的依赖包 转载beeworkshop 最后发布于2019-09-28 07:43:40 阅读数 1096  收藏 展开 利用 Downloadonly 插件下载 RP ...

  10. docker容器中日志文件过大处理方法

    背景 :在日常工作中一个基于centos镜像构建起来的python爬虫程序,日志文件在两个月内到了500G,日志存放在根目录下面,在不扩容的情况下把这个问题给解决掉.通过定时任务和脚本的方法,定期的清 ...