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

使用 OpenCV 构建稳定的多面镜片墙效果(镜面反射 + Delaunay 分块)

✨ 效果概览

我们将实现一种视觉效果,模拟由许多小镜面拼接而成的“镜子墙”。每个镜面是一个三角形区域,其内容做镜像反射(如水平翻转),在视频中形成奇特的万花筒、哈哈镜、空间折叠感。

使用 OpenCV 实现“随机镜面墙”——多镜片密铺的哈哈镜效果-CSDN博客https://blog.csdn.net/weixin_43607107/article/details/148126936?spm=1001.2014.3001.5501

为了让视频连贯播放而无明显闪烁,还需解决随机性带来的帧间结构跳变问题。

1. 背景知识:图像分块与仿射变换

我们利用以下两种技术实现该效果:

🟩 1.1 Delaunay 三角剖分

  • 对图像中随机生成的点进行 Delaunay 三角剖分(scipy.spatial.Delaunay

  • 可将整个图像划分为若干不重叠的三角区域,适合对局部进行变换

🟦 1.2 OpenCV 仿射变换

  • 对每个三角形区域进行水平镜像变换,使用 cv2.warpAffine() 函数

  • 控制点的选择与重心、外接圆等几何信息结合使用,可衍生更多镜面效果


2. 初始实现的问题:每帧结构不同导致闪烁

以下是初始实现的逻辑:

# 在 do() 方法中每帧都重新生成点 -> Delaunay -> 镜面反射

这样每帧都会产生不同的三角剖分结构,导致在连续视频中“镜子拼贴”的结构跳动不定,出现明显闪烁(flickering)现象,观感较差。


3. 改进思路:结构一次生成,复用即可

我们将随机点生成和三角剖分的过程移到 __init__initialize() 方法中,只在第一次调用时执行一次,之后的每一帧复用同样的三角结构。

✅ 优势

  • 消除闪烁

  • 性能更高,避免频繁三角剖分

  • 保持视觉一致性,为后续加入动态渐变打基础


4. 完整实现代码(固定结构版)

import cv2
import numpy as np
from scipy.spatial import Delaunayclass FrameObject:def __init__(self):self.initialized = Falseself.triangles = Nonedef initialize(self, w, h):# 初始化结构一次num_points = np.random.randint(50, 101)points = np.random.randint(0, [w, h], size=(num_points, 2))corners = np.array([[0,0], [w-1,0], [w-1,h-1], [0,h-1]])points = np.vstack((points, corners))tri = Delaunay(points)self.triangles = points[tri.simplices]self.initialized = Truedef do(self, frame, device):h, w = frame.shape[:2]if not self.initialized:self.initialize(w, h)result = np.zeros_like(frame)for tri_pts in self.triangles:mask = np.zeros((h, w), dtype=np.uint8)cv2.fillConvexPoly(mask, tri_pts, 255)centroid = np.mean(tri_pts, axis=0)x, y, bw, bh = cv2.boundingRect(tri_pts)roi = frame[y:y+bh, x:x+bw]mask_roi = mask[y:y+bh, x:x+bw]cx, cy = centroid - np.array([x, y])M = np.array([[-1, 0, 2*cx],[0, 1, 0]], dtype=np.float32)warped = cv2.warpAffine(roi, M, (bw, bh), flags=cv2.INTER_LINEAR)mask_bin = (mask_roi > 0)for c in range(frame.shape[2]):result[y:y+bh, x:x+bw, c][mask_bin] = warped[:, :, c][mask_bin]return result
5. 效果展示(截图/动画)


6. 扩展思路

你可以将该基础框架扩展为更多样的视觉效果:

  • 👓 镜面方式可选:水平、垂直、中心扭曲

  • 🎛 添加控制面板,改变分块数量或动态渐变

  • 🌀 加入水波或镜面变形(结合重心旋转/扰动)

  • 🎮 使用鼠标或动作检测交互式驱动镜面变换


7. 小结

在处理视频特效时,结构的一致性往往比效果的复杂性更重要。通过将镜面剖分结构从逐帧生成改为初始化一次,既提升了性能,又增强了稳定性,是视频处理中的一个经典优化思路。


如果你也在做计算机视觉、视频滤镜或 AI 视觉交互应用,这种“稳定拼接 + 局部变换”的方法可以广泛应用于艺术特效、增强现实等场景。

欢迎讨论与交流 👇!如果你感兴趣我还可以继续写更多镜面视觉扩展方案!

http://www.xdnf.cn/news/589285.html

相关文章:

  • MinerU教程第二弹丨MinerU 本地部署保姆级“喂饭”教程
  • Oracle 物理存储与逻辑管理
  • 偏微分方程数值方法指南及AI推理
  • 深入理解Diffusers: 从基础到Stable Diffusion
  • (07)数字化转型之产品材料管理:从基础数据到BOM的全生命周期管理
  • Basic concepts for seismic source - Finite fault model
  • 【 开源:跨平台网络数据传输的万能工具libcurl】
  • DOM API-JS通过文档对象树操作Doc和CSS
  • 【Linux 学习计划】-- makefile
  • shell脚本总结5
  • 当AI遇上科研:北大“科学导航”重塑学术探索全流程
  • LeetCode Hot100 (哈希)
  • x-cmd install | cargo-selector:优雅管理 Rust 项目二进制与示例,开发体验升级
  • OpenCV计算机视觉实战(7)——色彩空间详解
  • 网络图片的缓存和压缩
  • 海康相机---采集图像
  • 如何解决鸿蒙应用闪退问题
  • Flutter 3.32 新特性
  • 鸿蒙Flutter实战:21-混合开发详解-1-概述
  • flutter getx路由管理、状态管理、路由守卫中间件、永久储存get_storage
  • 汇川EasyPLC MODBUS-RTU通信配置和编程实现
  • S7-1500PLC通过工艺对象实现V90总线伺服定位控制(105报文)
  • 英伟达有意入股 PsiQuantum,释放战略转向量子计算的重要信号
  • JVM常量池(class文件常量池,运行时常量池,字符串常量池)
  • Mysql数据库之索引与事务
  • 【内部教程】ISOLAR-AB配置以太网栈|超详细实战版
  • Kotlin与Flutter:跨平台开发的互补之道与实战指南
  • Armadillo C++ 线性代数库介绍与使用
  • Kotlin 极简小抄 P10(类与对象、主构造函数、带有默认参数值的主构造函数、次要构造函数)
  • 【机器学习】集成学习算法及实现过程