【python】OpenCV—Fun Mirrors
文章目录
- 1、准备工作
- 2、原理介绍
- 3、代码实现
- 4、效果展示
- 5、参考
1、准备工作
pip install vacm
2、原理介绍
在OpenCV中,VCAM 库是一个用于简化创建三维曲面、定义虚拟摄像机、设置参数以及进行投影任务的工具。它特别适用于实现如哈哈镜等图像变形效果。
一、VCAM 库的功能
VCAM 库的主要功能包括:
-
创建三维曲面:用户可以根据需要定义一个三维曲面,这个曲面将作为虚拟镜面的基础。
-
定义虚拟摄像机:用户可以设置虚拟摄像机的各种参数,如焦距、位置等,以模拟不同的拍摄效果。
-
投影与重映射:将三维曲面上的点投影到虚拟摄像机的成像平面上,并生成相应的二维点。这些二维点可以用于图像的重映射,从而实现图像的变形效果。
二、使用VCAM库实现哈哈镜效果
-
获取图像并创建网格:首先,获取待处理的图像,并创建一个与图像大小相同的网格。这个网格将用于表示三维曲面上的点。
-
定义三维曲面:通过修改网格中每个点的Z坐标值,来定义一个凹凸不平的三维曲面。这可以通过各种数学函数来实现,如正弦函数、余弦函数等。
-
创建虚拟摄像机并投影:使用VCAM库创建一个虚拟摄像机,并将定义好的三维曲面投影到虚拟摄像机的成像平面上。这一步将生成对应的二维点集。
-
图像重映射:根据投影得到的二维点集,使用OpenCV的remap函数对原始图像进行重映射。重映射的过程将根据二维点集的位置关系,将原始图像中的每个像素点映射到新的位置,从而实现图像的变形效果。
三、代码示例
以下是一个使用Python和VCAM库实现哈哈镜效果的示例代码:
import cv2
import numpy as np
from vcam import vcam, meshGen # 读取图像
img = cv2.imread('your_image.jpg')
H, W = img.shape[:2] # 创建虚拟摄像机
c1 = vcam(H=H, W=W) # 创建网格
plane = meshGen(H, W) # 定义三维曲面(例如,使用正弦函数来创建波浪形的曲面)
plane.Z = 10 * np.sin((plane.X / plane.W) * 2 * np.pi * 10) # 获取三维曲面上的点
pts3d = plane.getPlane() # 将三维点投影到二维图像坐标
pts2d = c1.project(pts3d) # 构建映射函数
map_x, map_y = c1.getMaps(pts2d) # 应用映射函数进行图像重映射
output = cv2.remap(img, map_x, map_y, interpolation=cv2.INTER_LINEAR) # 显示结果
cv2.imshow('Funny Mirror', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
四、注意事项
-
安装VCAM库:在使用VCAM库之前,需要确保已经正确安装了该库。如果使用的是Python,可以通过pip等包管理工具进行安装。
-
调整参数:在使用VCAM库时,可以通过调整虚拟摄像机的参数、三维曲面的定义等来实现不同的变形效果。用户可以根据需要进行多次尝试和调整。
-
性能考虑:对于较大的图像或复杂的变形效果,图像重映射的过程可能会比较耗时。因此,在实际应用中需要考虑性能问题,并采取相应的优化措施。
综上所述,OpenCV的VCAM库是一个功能强大的工具,可以用于实现各种有趣的图像变形效果。通过合理使用该库,用户可以轻松地创建出具有创意和趣味性的图像作品。
3、代码实现
# FunnyMirrorsImages.py
import cv2
import numpy as np
import math
from vcam import vcam, meshGenpaths = ["./chess.jpeg", "./1.jpg", "./2.jpg"]for mode in range(8):for i, path in enumerate(paths):# 读取输入图像img = cv2.imread(path)img = cv2.resize(img, (300, 300))H, W = img.shape[:2]# 创建虚拟相机对象c1 = vcam(H=H, W=W)# 创建表面对象plane = meshGen(H, W)# 我们生成一面镜子,其中对于每个 3D 点,其 Z 坐标定义为 Z = F(X,Y)if mode == 0:plane.Z += 20 * np.exp(-0.5 * ((plane.X * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))elif mode == 1:plane.Z += 20 * np.exp(-0.5 * ((plane.Y * 1.0 / plane.H) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))elif mode == 2:plane.Z -= 10 * np.exp(-0.5 * ((plane.X * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))elif mode == 3:plane.Z -= 10 * np.exp(-0.5 * ((plane.Y * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))elif mode == 4:plane.Z += 20 * np.sin(2 * np.pi * ((plane.X - plane.W / 4.0) / plane.W)) + 20 * np.sin(2 * np.pi * ((plane.Y - plane.H / 4.0) / plane.H))elif mode == 5:plane.Z -= 20 * np.sin(2 * np.pi * ((plane.X - plane.W / 4.0) / plane.W)) - 20 * np.sin(2 * np.pi * ((plane.Y - plane.H / 4.0) / plane.H))elif mode == 6:plane.Z += 100 * np.sqrt((plane.X * 1.0 / plane.W) ** 2 + (plane.Y * 1.0 / plane.H) ** 2)elif mode == 7:plane.Z -= 100 * np.sqrt((plane.X * 1.0 / plane.W) ** 2 + (plane.Y * 1.0 / plane.H) ** 2)else:print("Wrong mode selected")exit(-1)# 提取生成的 3D 平面pts3d = plane.getPlane()# 在虚拟相机中投影(捕捉)平面pts2d = c1.project(pts3d)# 为基于网格的扭曲生成映射函数。map_x, map_y = c1.getMaps(pts2d)# 生成输出output = cv2.remap(img, map_x, map_y, interpolation=cv2.INTER_LINEAR)output = cv2.flip(output, 1)cv2.imshow("Funny Mirror", output)cv2.imshow("Input and output", np.hstack((img, np.zeros((H, 2, 3), dtype=np.uint8), output)))# 取消注释以下行以保存输出# cv2.imwrite("Mirror-effect-%d-image-%d.jpg"%(mode+1,i+1),np.hstack((img,np.zeros((H,2,3),dtype=np.uint8),output)))cv2.waitKey(0)
4、效果展示
输入图片
plane.Z += 20 * np.exp(-0.5 * ((plane.X * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))
plane.Z += 20 * np.exp(-0.5 * ((plane.Y * 1.0 / plane.H) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))
plane.Z -= 10 * np.exp(-0.5 * ((plane.X * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))
plane.Z -= 10 * np.exp(-0.5 * ((plane.Y * 1.0 / plane.W) / 0.1) ** 2) / (0.1 * np.sqrt(2 * np.pi))
plane.Z += 20 * np.sin(2 * np.pi * ((plane.X - plane.W / 4.0) / plane.W)) + 20 * np.sin(2 * np.pi * ((plane.Y - plane.H / 4.0) / plane.H))
plane.Z -= 20 * np.sin(2 * np.pi * ((plane.X - plane.W / 4.0) / plane.W)) - 20 * np.sin(2 * np.pi * ((plane.Y - plane.H / 4.0) / plane.H))
plane.Z += 100 * np.sqrt((plane.X * 1.0 / plane.W) ** 2 + (plane.Y * 1.0 / plane.H) ** 2)
plane.Z -= 100 * np.sqrt((plane.X * 1.0 / plane.W) ** 2 + (plane.Y * 1.0 / plane.H) ** 2)
5、参考
- https://github.com/kaustubh-sadekar/FunMirrors
- https://github.com/kaustubh-sadekar/VirtualCam
- OpenCV进阶(11)使用 OpenCV实现哈哈镜
相关文章:

【python】OpenCV—Fun Mirrors
文章目录 1、准备工作2、原理介绍3、代码实现4、效果展示5、参考 1、准备工作 pip install vacm2、原理介绍 在OpenCV中,VCAM 库是一个用于简化创建三维曲面、定义虚拟摄像机、设置参数以及进行投影任务的工具。它特别适用于实现如哈哈镜等图像变形效果。 一、VC…...
QT IEEE754 16进制浮点数据转成10进制
IEEE754标准转换QT代码 qtcreator使用的ieee754标准的4字节数组与浮点数之间的转换方法,ieee754的4位数组如果转换成二进制后,大体结构是: 位序号12-910-32意义 符号位, 正数为0,负数为1. 指数位, 指数是…...

无人机+视频推流直播EasyCVR视频汇聚/EasyDSS平台在森林防护巡检中的解决方案
随着科技的飞速发展,无人机技术在各个领域的应用日益广泛,特别是在森林防护与巡检方面,无人机以其独特的优势,为传统林业管理带来了革命性的变化。本文将探讨无人机在森林防护巡检中的解决方案,分析其工作原理、优势及…...

Rancher—多集群Kubernetes管理平台
目录 一、Rancher 简介1.1 Rancher 和 k8s 的区别 二、Rancher 安装及配置2.1 安装 rancher2.2 登录 Rancher 平台2.3 Rancher 管理已存在的 k8s 集群2.4 创建名称空间 namespace2.5 创建 Deployment 资源2.6 创建 service2.7 Rancher 部署监控系统 一、Rancher 简介 Rancher …...
使用多IP香港站群服务器对网站管理seo优化提升排名有益处
在网站管理和优化中,选择合适的服务器是至关重要的。针对某些特定需求,使用多IP香港站群服务器可以带来明显的益处。本文将探讨使用多IP香港站群服务器 对网站管理的明显益处,并介绍其中的关键要点和优势。 I. 理解多IP香港站群服务器 1. 多I…...

网管平台(基础篇):网管系统的重要性
网管系统的核心地位:数字世界的稳定舵手 在信息技术日新月异的今天,网络如同一条无形的纽带,将世界紧密相连。然而,这条纽带背后隐藏着无数复杂的节点与链路,如何确保它们高效、稳定地运行,成为了一个亟待解…...

Ubuntu20.04下安装多CUDA版本,以及后续切换卸载
本方案的前提是假设机子上已经有一个版本的cuda,现在需要支持新的torch2.1.2和torchvision0.16.2,于是来安装新的cuda 一、选择版本 如果我想安装支持torch2.1.2的cuda版本,到官网(https://pytorch.org/get-started/previous-ve…...
图像处理高频面试题及答案
目录 高频面试题及答案1. 什么是图像处理?2. 什么是图像的分辨率?3. 图像的颜色空间是什么?4. 什么是边缘检测,为什么重要?5. 解释一下图像增强的常见方法。6. 什么是图像的直方图?7. 什么是图像的去噪声?8. 什么是图像分割,常用的方法有哪些?9. 图像滤波的目的是什么…...

尤雨溪都打赏的虚拟列表组件,到底有多强
尤雨溪都打赏的虚拟列表组件,到底有多强? 在前端开发中,性能优化永远是绕不开的主题。今天就带你看看 vue-virtual-scroller,一款让你滚动页面时流畅得像火箭一样的 Vue 组件。本文将简单介绍这个组件的主要功能、技术特点&#x…...
FrameWork使用EfCore数据库映射举例
Microsoft.EntityFrameworkCore新的版本不支持FrameWork框架。 这里举例使用旧版本实现数据存取 首先下载 Microsoft.EntityFrameworkCore 版本控制在2.1.14以下 同样下载Microsoft.EntityFrameworkCore.sqlite 举例时间记录 public class RunTimeInfo{[Key]public int Id { g…...

汽车与航空领域的功能安全对比:ISO 26262-6 与 DO-178C 的差异浅析
ISO 26262-6 和 DO-178C (航空系统与设备认证中的软件考量)。是汽车和航空领域分别广泛应用的软件安全标准。它们的共同目标是确保系统软件可靠性,减少系统软件故障对生命安全的威胁,但在具体的软件安全方案和规范实施上存在明显的…...
linux命令之lspci用法
lspci 显示当前主机的所有PCI总线信息 补充说明 lspci命令 用于显示当前主机的所有PCI总线信息,以及所有已连接的PCI设备信息。 语法 lspci(选项)选项 -n:以数字方式显示PCI厂商和设备代码; -t:以树状结构显示PCI设备的层次…...

虚幻闪烁灯光材质
创建一个材质 材质域改成光照函数 , Time让材质动起来 参数B用来控制速度 , Sine 让灯光闪烁 , Frac 增加了闪烁细节 把材质放到灯光材质上 效果还是挺不错的! 可以用于一些恐怖游戏~...
UNION ALL函数用法
文章目录 1. 什么是 UNION ALL?2. UNION ALL 的特点2.1 不去重2.2 性能更优2.3 列数和数据类型 3. 示例应用3.1 基本示例3.2 结合其他 SQL 功能3.3 使用子查询3.4 转换操作(leetcode真题) 4. 注意事项5. 结论 在数据库查询中, 合并多个结果集是一个常见…...

JavaWeb合集14-WebSocket
十四、WebSocket WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信,浏览器和服务器只需要完成一次握手, 两者之间就可以创建持久性的连接,并进行双向数据传输。 HTTP协议和WebSocket协议对比: HTTP是短连…...
Vue快速嵌入百度地图,避坑提效指南
Vue快速嵌入百度地图,避坑提效指南 在Vue项目中引用百度地图并没有高德地图那么方便,但是项目要用,这里分享下找到的方法,方便使用到的时候能快速接入,避雷避坑! 新建bmap.js文件 export default {init: f…...

深入理解售后派单管理系统,功能优势一览
售后派单管理系统优化售后服务流程,提升响应速度、运营效率和服务质量。ZohoDesk等系统通过自动化派单、实时调度监控等功能,助力企业赢得竞争优势。适用于电子产品、汽车、IT及房地产等行业。 一、什么是售后派单管理系统 售后派单管理系统是一种专门用…...
一文读懂K8S的PV和PVC以及实践攻略
一文读懂K8S的PV和PVC以及实践攻略 Kubernetes(K8S)作为当前云原生和微服务架构的首选平台,凭借其强大的容器编排和管理能力,迅速成为一线大厂分布式平台的标配技术。在Kubernetes中,持久化存储是一个核心问题&#x…...
在react-native中如何获取View的漏出比例和漏出时间
写在前面 最近在项目中遇到了一个这样的需求:给一个模块做埋点,要求埋点的触发时机是当模块露出50%且停留300毫秒才进行上报 开搞 首先要有一个View <View></View>然后在View里定义一个ref <View ref { viewRef }></View>然…...

谷歌新安装包文件形式 .aab 在UE4中的打包原理
摘要 本文学习了aab的基本概念以及UE4中产生aab的构建原理。 从官网了解基本概念 官网:Android Developers 1、什么是aab? .aab包形如: 2021年7月,在Google Play应用程序中,已经有数千个应用程序率先跟进了AAB格式。…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...