1. 引言
“哈哈鏡”是一種典型的圖像變形效果,通過局部鏡面反射產生扭曲的視覺趣味。在計算機視覺和圖像處理領域,這類效果不僅有趣,還能用于藝術創作、交互裝置、視覺特效等場景。
傳統的“哈哈鏡”往往是針對整張圖像做某種鏡像或扭曲變換,而如果我們將圖像劃分為多個小鏡片,每個鏡片獨立做鏡面反射,拼成一面“鏡子墻”,效果更豐富,也更具創意。
本文將介紹如何使用 Python 和 OpenCV 實現這樣一種“隨機鏡面墻”效果:
-
在圖像上隨機生成多個點,利用三角剖分將圖像切成多個小三角形面片(鏡片)。
-
對每個鏡片分別以其重心為中心做局部鏡面反射變換。
-
最后將所有變換后的鏡片無縫拼接,形成一幅由多個鏡面組成的“哈哈鏡”墻。
2. 基礎準備:OpenCV 簡介
OpenCV 是一個開源的計算機視覺庫,提供了豐富的圖像處理功能,如圖像讀取、變換、繪制等。
本案例中,主要用到的功能包括:
-
cv2.fillConvexPoly
:繪制多邊形掩碼 -
cv2.boundingRect
:獲取多邊形的最小外接矩形 -
cv2.warpAffine
:仿射變換實現局部鏡像 -
NumPy 進行數組和坐標操作
3. 設計思路
3.1 隨機采樣點 + 邊界點
在圖像區域內隨機采樣若干點(50~100個),并額外加入圖像四個角點,確保后續切割覆蓋整幅圖。
3.2 Delaunay 三角剖分密鋪
使用 SciPy 的 Delaunay
對采樣點做三角剖分,得到一組不重疊的三角形面片,組成密鋪。
3.3 計算三角形重心
對每個三角形頂點坐標求均值,得到重心作為局部鏡面的“反射中心”。
3.4 局部鏡面反射變換
以三角形重心為中心,利用仿射變換矩陣實現水平或垂直鏡像(或旋轉+鏡像)。
-
例如水平鏡像矩陣為:
M=[?102cx010]M = \begin{bmatrix} -1 & 0 & 2c_x \\ 0 & 1 & 0 \end{bmatrix}M=[?10?01?2cx?0?]
其中 cxc_xcx? 是重心的水平坐標(相對于當前ROI局部坐標)。
3.5 裁剪與拼接
-
對每個三角形計算外接矩形,裁剪圖像和掩碼。
-
將鏡像變換后的結果放回對應位置,只覆蓋三角形區域。
4. 關鍵代碼示例
import cv2
import numpy as np
from scipy.spatial import Delaunayclass FrameObject:def __init__(self):passdef do(self, frame, device):h, w = frame.shape[:2]# 生成隨機點 + 添加四角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))# Delaunay 三角剖分tri = Delaunay(points)triangles = points[tri.simplices]result = np.zeros_like(frame)for tri_pts in triangles:# 創建掩碼,繪制三角形mask = np.zeros((h, w), dtype=np.uint8)cv2.fillConvexPoly(mask, tri_pts, 255)# 計算重心centroid = np.mean(tri_pts, axis=0)# 裁剪ROI區域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]# 轉換重心到ROI局部坐標系cx, cy = centroid - np.array([x, y])# 構造水平鏡像仿射矩陣M = np.array([[-1, 0, 2*cx],[0, 1, 0]], dtype=np.float32)# 對ROI做鏡像變換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. 運行效果與拓展
-
運行后你會看到畫面被切割成許多小三角形鏡片,每個鏡片都經過水平鏡像,組成豐富的鏡面墻效果。
-
可以將
M
變換矩陣換成垂直鏡像、旋轉鏡像,甚至結合水波扭曲,做出更多變化。 -
采樣點數越多,鏡片越細密,視覺越復雜。
-
6. 總結
本文介紹了如何結合 OpenCV 和 SciPy,基于隨機采樣點和 Delaunay 三角剖分,將圖像劃分為多個小鏡片,并對每個鏡片獨立應用鏡像變換,模擬“鏡子墻”哈哈鏡效果。
此方法不僅簡單高效,還極具擴展性。你可以基于此框架增加更多變換模式、動態動畫或實時視頻處理,創造更多炫酷的視覺效果。
如果你喜歡這篇教程,歡迎點贊、收藏和留言交流!
更多圖像處理技術,歡迎關注我的博客。