使用 OpenCV 实现“随机镜面墙”——多镜片密铺的哈哈镜效果

news2025/6/2 9:52:08

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 Delaunay

class FrameObject:
    def __init__(self):
        pass

    def 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 三角剖分,将图像划分为多个小镜片,并对每个镜片独立应用镜像变换,模拟“镜子墙”哈哈镜效果。

此方法不仅简单高效,还极具扩展性。你可以基于此框架增加更多变换模式、动态动画或实时视频处理,创造更多炫酷的视觉效果。


如果你喜欢这篇教程,欢迎点赞、收藏和留言交流!
更多图像处理技术,欢迎关注我的博客。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2386652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙仓颉开发语言实战教程:页面跳转和传参

前两天分别实现了商城应用的首页和商品详情页面,今天要分享新的内容,就是这两个页面之间的相互跳转和传递参数。 首先我们需要两个页面。如果你的项目中还没有第二个页面,可以右键cangjie文件夹新建仓颉文件: 新建的文件里面没什…

最新Spring Security实战教程(十六)微服务间安全通信 - JWT令牌传递与校验机制

🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Micro麦可乐的博客 🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战 🌺《RabbitMQ》…

【五】Spring Cloud微服务开发:解决版本冲突全攻略

Spring Cloud微服务开发:解决版本冲突全攻略 目录 Spring Cloud微服务开发:解决版本冲突全攻略 概述 一、Spring Boot 二、Spring Cloud 三、Spring Cloud Alibaba 总结 概述 spring cloud微服务项目开发过程中经常遇到程序包版本冲突的问题&…

Spring Boot微服务架构(二):开发调试常见中文问题

Spring Boot开发调试常见中文问题及解决方案 一、环境配置类问题 端口冲突 表现:启动时报错"Address already in use"解决:修改application.properties中的server.port或终止占用端口的进程 数据库连接失败 表现:启动时报错"…

Linux基础IO----动态库与静态库

什么是库? 库是由一些.o文件打包在一起而形成的可执行程序的半成品。 如何理解这句话呢? 首先,一个程序在运行前需要进行预处理、编译、汇编、链接这几步。 预处理: 完成头文件展开、去注释、宏替换、条件编译等,最终…

LeetCode百题刷004(哈希表优化两数和问题)

遇到的问题都有解决的方案,希望我的博客可以为你提供一些帮助 一、哈希策略优化两数和问题 题目地址:1. 两数之和 - 力扣(LeetCode)https://leetcode.cn/problems/two-sum/description/ 思路分析: 题目要求在一个整型…

FPGA通信之VGA与HDMI

文章目录 VGA基本概念:水平扫描:垂直扫描: 时序如下:端口设计疑问为什么需要输出那么多端口不输出时钟怎么保证电子枪移动速度符合时序VGA转HDMI 仿真电路图代码总结:VGA看野火电子教程 HDMITMDS传输原理为什么使用TMD…

Leetcode百题斩-二叉树

二叉树作为经典面试系列,那么当然要来看看。总计14道题,包含大量的简单题,说明这确实是个比较基础的专题。快速过快速过。 先构造一个二叉树数据结构。 public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode…

ACM Latex模板:合并添加作者和单位

目录: 1.ACM会议论文Latex模板,逐个添加作者和单位: 1)Latex: 2)效果: 2. ACM会议论文Latex模板,合并添加作者和单位: 1)Latex: 2&#x…

将MCP(ModelContextProtocol)与Semantic Kernel集成(调用github)

文章目录 将MCP(ModelContextProtocol)与Semantic Kernel集成(调用github)一、模型上下文协议(MCP)简介1.1 简介1.2 示例 二、集成步骤2.1 安装环境依赖2.2 构建语义内核(Kernel)2.3…

游戏引擎学习第311天:支持手动排序

仓库: https://gitee.com/mrxiao_com/2d_game_7(已满) 新仓库: https://gitee.com/mrxiao_com/2d_game_8 回顾并为今天的内容定下基调 我们接下来要继续完成之前开始的工作,上周五开始的部分内容,虽然当时对最终效果还不太确定,但现在主要任…

LambdaQueryWrapper、MybatisPlus提供的基本接口方法、增删改查常用的接口方法、自定义 SQL

DAY26.2 Java核心基础 MybatisPlus提供的基本接口方法 分页查询 导入依赖springboot整合Mybatis-plus <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version&g…

深度学习---可视化

模型可视化 深度学习模型可视化是理解、调试和优化模型的关键技术&#xff0c;涉及模型结构、参数、层输出、数据流动、训练过程等多维度分析。 一、可视化的核心作用 模型理解 解析复杂模型的网络架构&#xff08;如CNN的层级连接、Transformer的注意力机制&#xff09;。揭…

Windows系统如何查看ssh公钥

很多人只是一味的为拿到ssh公钥而努力&#xff0c;往往却会忽略了ssh公钥与私钥背后的作用。 咱们在这里会花两分钟。 一分钟速通概念&#xff0c;一分钟教会你如何获取。 一分钟速通概念&#xff1a; 如何生成&#xff1a; SHH 公钥 与 私钥 是基于非对称加密算法&#xff…

【2025】嵌入式软考中级部分试题

大题: 大模型 神经网络 机器学习 深度学习的包含关系 不一定对 订阅-发布者模型 发布/订阅模式特点: ①解耦:发布者和订阅者之间没有直接联系,它们通过中间的消息代理(如消息队列或事件总线)进行通信。这种解耦使得系统更加灵活,可以独立地添加或移除发布者和订阅者…

Antd中Upload组件封装及使用:

1.Upload上传组件功能: 文件校验 : 文件格式校验/文件大小校验/上传文件总个数校验 相关功能 : 拖拽功能/上传到远程(七牛)/文件删除及下载 2.组件效果展示: 3.疑难点及解决方案: Promise.all多文件并行上传到远程(七牛云): (1)在beforeUpload钩子函数中获取token (2)循环fi…

Linux环境基础开发工具->vim

引入&#xff1a;vim是什么&#xff1f; vs叫作继承开发环境&#xff0c;我们可以在里面编辑代码&#xff0c;调式代码&#xff0c;运行代码....这种叫集成开发环境&#xff1b;而vim只用来编辑代码&#xff0c;也就是类似于在windows上打开一个记事本来写代码的操作 集成开发…

跳板问题(贪心算法+细节思考)

首先直接看题&#xff1a; 这题直接贪心其实问题不大&#xff1a; 下面先展示我的一个错误代码&#xff1a; # include<iostream> # include<vector> # include<algorithm>using namespace std;int main() {int N,M;cin>>N>>M;vector<vecto…

RuoYi前后端分离框架集成UEditorPlus富文本编辑器

一、背景 采用若依框架搭建了一个小型的电子书项目,项目前端、后端、移动端就一人,电子书的章节内容是以富文本内容进行呈现的,产品设计人员直接给了一个第三方收费的富文本编辑器截图放到开发文档中,提了一沓需求点,概况下来就是要做成下图中的样子。作为一个后端开发人…

IPD流程落地:项目任务书Charter开发

目录 简介 第一个方面&#xff0c;回答的是Why的问题。 第二点&#xff0c;要回答做什么的问题&#xff0c;也就是产品定义What的问题。 第三点就是要回答执行策略与计划的问题&#xff0c;也就是How、When、Who的问题。 第四点是对上述这些分析的总结分析&#xff0c;要为…