前言

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

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

哈哈镜实现原理

假设输入图像的宽高为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. Windows 驱动加载程序代码

    #include <windows.h> #include <winsvc.h> #include <conio.h> #include <stdio.h&g ...

  2. Portswigger web security academy:Cross-site request forgery (CSRF)

    Portswigger web security academy:Cross-site request forgery (CSRF) 目录 Portswigger web security acade ...

  3. 【JavaScript】Leetcode每日一题-移除元素

    [JavaScript]Leetcode每日一题-移除元素 [题目描述] 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度. 不要使用 ...

  4. Maven执行Install命令时跳过测试

    1. 在pom.xml中添加插件 <!-- 跳过单元测试,不然打包的时候会因为加载不了application.yaml报错 --> <plugin> <groupId&g ...

  5. Windows子系统Ubuntu安装宝塔面板

    首先你需要安装Ubuntu子系统,安装方法点击这里,安装完成后再进行下面的步骤. 安装宝塔面板 输入命令 wget -O install.sh http://download.bt.cn/instal ...

  6. unapp一键登录

    一.整理思路 un-app官网提供多种实现[一键登录](https://uniapp.dcloud.net.cn/uniCloud/univerify "")的方法,这里的选择是 ...

  7. .Net Core with 微服务 - 架构图

    上一次我们简单介绍了什么是微服务(.NET Core with 微服务 - 什么是微服务 ).介绍了微服务的来龙去脉,一些基础性的概念.有大佬在评论区指出说这根本不是微服务.由于本人的能力有限,大概也 ...

  8. 了解常用数据库MySQL、Oracle、MongoDB

    本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net 注:转载文章 什么是数据库 简单的说,数据库(英文 Dtabase)就是一个存放数据的仓库,这个仓库是按照一定的数据结果( ...

  9. ElasticSearch实战系列十一: ElasticSearch错误问题解决方案

    前言 本文主要介绍ElasticSearch在使用过程中出现的各种问题解决思路和办法. ElasticSearch环境安装问题 1,max virtual memory areas vm.max_ma ...

  10. 前端Node的实用方法

    Node 一.什么是Node Node是以基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动.非阻塞式I/O模型(I/O是 input/output的缩写,即输入输出端口,在 ...