使用 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 视觉交互应用,这种“稳定拼接 + 局部变换”的方法可以广泛应用于艺术特效、增强现实等场景。
欢迎讨论与交流 👇!如果你感兴趣我还可以继续写更多镜面视觉扩展方案!