一、缘起

春节期间,为了打发时间,我迷上了一款拼图小游戏。游戏规则很简单——给你一张漂亮的图片,打乱成若干块,然后在时间限制内把它拼好。听起来很休闲对不对?too young too simple

问题在于:每次超时都要看30秒视频广告。人菜瘾又大的我,经常需要看广告才能过关。

终于在某次看了第17遍"是兄弟就来砍我"之后,我一拍桌子——不行,我要搞点事情

📢 友情提示:本文不涉及游戏外挂或修改游戏本身,只是研究如何用程序自动操作已知的拼图图片。

二、动手干

2.1 拼图还原问题

拼图还原问题(Jigsaw Puzzle Reassembly Problem) 是计算机视觉和图像处理领域的一个重要研究课题。简单来说,就是给定一幅被打碎的图像,如何让计算机自动识别各个碎片之间的关系,并将它们重新拼合成完整的原始图像。

问题分类

根据不同的碎片特征,拼图还原问题可以分为以下几类:

类型碎片特征难度典型场景
Type 1矩形碎片,排列规则,无旋转⭐⭐网格切割的图片
Type 2矩形碎片,排列规则,有旋转⭐⭐⭐可旋转的拼图游戏
Type 3传统锯齿边缘,无旋转⭐⭐⭐⭐传统拼图
Type 4传统锯齿边缘,有旋转⭐⭐⭐⭐⭐复杂拼图、考古文物修复

本文面对的问题

回顾本文面对的拼图问题:

  • 矩形分块:每块都是规整的矩形,没有传统拼图的锯齿边缘
  • 网格排列:6×6、7×7、8×8 三种规格,整齐排列
  • 无旋转:所有碎片都是正向朝上,不涉及旋转匹配
  • 无参考图:原图被打碎后完全不可见,需要通过碎片自身特征推断位置

这属于上表中的 Type 1 类型——矩形碎片、无旋转的规则拼图。虽然是相对简单的一类,但结合"无参考图"这一约束条件,仍然需要借助图像边缘匹配等计算机视觉技术来解决。

2.2 实施方案

2.2.1 提取拼图区域

输入:含 UI 的原始截图 输出:纯拼图区域图像 + bbox

方法:基于背景颜色分割

从图像四周边缘采样获取背景色,对每个像素计算 RGB 欧氏距离。距离 > 35 的像素标记为非背景,经形态学开闭运算去噪填洞后,查找最大连通域作为拼图区域。


2.2.2 检测拼图块边界

输入:纯拼图区域图像 输出:M×N 个等大小 patch

方法:基于轴向纹理信号检测分割线

灰度化后沿行/列方向计算标准差。拼图块内部纹理有变化→信号高,块间缝隙处纹理一致→信号低。通过搜索信号局部最小值定位每条分割线,最后归一化所有 patch 为统一尺寸。


2.2.3 遗传算法拼图

输入:打乱的 M×N 个 patch 输出:还原后的 grid + 重建图像

方法:进化算法最小化相邻块边缘差异

种群 200 个随机排列个体,以相邻块边缘像素差(MSE/Median/Percentile/Huber)的总和作为适应度。轮盘赌选择父代、交叉产生子代、精英保留 Top2,连续 10 代无提升则早停。

拼图还原示例

三、最终效果展示

四、总结

这个项目大概花了我四周的周末时间,从最初的"看广告好烦"到最后的"这玩意儿居然还真能跑",过程颇为曲折。虽然全程vibe coding,但是大方向还是需要自己去研究清楚后,再给AI讲清楚后,才能有个好的结果。

目前这个效果离我最初设想的效果,一键启动通关,还差很远,还存在不少问题,不过也算基本达到当时的目的,用了这个后,玩这个拼图游戏再也没有看过广告了。也许后面有时间,再看看没有其它能够实现一键通关的方法,比如RL之类的,现在就暂时到这里吧,毕竟只是一个副本任务。

项目地址:JigsawPuzzleReconstruction


最后,如果你也被游戏广告折磨得不行,不妨试试这个思路——有时候最好的外挂,是用自己的技术绕过广告(而不是去黑游戏服务器)。

祝大家拼图愉快,永不看广告