当前位置: 首页 > news >正文

【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实现哈哈镜
http://www.lryc.cn/news/462591.html

相关文章:

  • QT IEEE754 16进制浮点数据转成10进制
  • 无人机+视频推流直播EasyCVR视频汇聚/EasyDSS平台在森林防护巡检中的解决方案
  • Rancher—多集群Kubernetes管理平台
  • 使用多IP香港站群服务器对网站管理seo优化提升排名有益处
  • 网管平台(基础篇):网管系统的重要性
  • Ubuntu20.04下安装多CUDA版本,以及后续切换卸载
  • 图像处理高频面试题及答案
  • 尤雨溪都打赏的虚拟列表组件,到底有多强
  • FrameWork使用EfCore数据库映射举例
  • 汽车与航空领域的功能安全对比:ISO 26262-6 与 DO-178C 的差异浅析
  • linux命令之lspci用法
  • 虚幻闪烁灯光材质
  • UNION ALL函数用法
  • JavaWeb合集14-WebSocket
  • Vue快速嵌入百度地图,避坑提效指南
  • 深入理解售后派单管理系统,功能优势一览
  • 一文读懂K8S的PV和PVC以及实践攻略
  • 在react-native中如何获取View的漏出比例和漏出时间
  • 谷歌新安装包文件形式 .aab 在UE4中的打包原理
  • 昂首平台:多货币专家顾问助力投资者优化外汇投资
  • Go标准库runtime.MemStats
  • MAC 电脑Office power point编辑的时候,显示“某些字体无法随演示文稿一起保存,仍然要保存演示文稿吗?”
  • R语言机器学习算法实战系列(四)随机森林算法+SHAP值 (Random Forest)
  • 用柔性神经k-Opt学习搜索路径问题的可行和不可行区域(未完,先看前驱文章L2S)
  • 【升华】人工智能python重要库scikit-learn学习
  • Stable Diffusion Web UI 大白话术语解释 (二)
  • vue-vben-admin 首页加载慢优化 升级vite2到vite3
  • 集合框架07:LinkedList使用
  • 一区鱼鹰优化算法+深度学习+注意力机制!OOA-TCN-LSTM-Attention多变量时间序列预测
  • Cesium 黑夜效果