m*n拼图自动还原算法

引言       
          拼图游戏很适合休闲放松的时候玩,所有在上大学的一段时间里,我比较喜欢玩用以打发无聊的时光。
         恰巧2016年李世石与阿尔法狗对弈,虽然不懂围棋,但是围棋对弈作为还未被计算机算法攻陷的堡垒,我很好奇最后结果是什么样,于是就看了每一场比赛。比赛最后的结果与李世石和围棋大师们的预期相反,李世石1:4阿尔法狗宣告计算机获得了胜利。当时我想既然下围棋都能够用算法完成,那么可不可以写一个自动还原拼图的算法呢?我并不懂人工智能,但是还原拼图也是一件很简单的事情,应该能够写成算法。然后我就着手进行了研究,经过一个多月心里也有了一个完整的可行想法。研究做完后由于快要期末了,有很多期末实验要做,也就没有真正的去实现它。现在到了2017年,找了点时间对这个问题进行了更深入的研究,也觉得既然心里有一个不错的想法分享出来会更好。
     
                    
                       打乱前                                         打乱后
人复原拼图的思路
       以4*4拼图为例,说明复原拼图的一般方法,分别对拼图中的图片及位置进行编号。这样我们就能用二元向量来表示某一块图片当前所对应的坐标了,如下图用向量的形式可以表示为:(1,1)、(2,2)......(16,16)。
      约定:向量的第一个数字代表位置,第二个数字代表图片编号 直接用某一块拼图图片的编号作为它的名字,例如称编号为1的一块拼图图片为1.

                                                                                            
    在打乱拼图后,按以下步骤进行复原:
                   图1                      图2                    图3                                 图4      
                                             图5                                                                                       图6                                                                                                                                                                               
          
                   图7                         图8                            图9                                  图10
                

       1.打乱拼图后(图1),首先把1复原到位置1(图2),接着把2复原到位置2(图3)。接着要复原3、4,这时不能直接把3复原到位置3,而是需要先把3移动到位置4,把4移动到位置8(图4),同时复原3、4(图5)。对于m*n拼图,在m>=3,n>=3时,我们需要按行复原,每一行的最后两个需要向上面说的同时进行复原。
       2.按复原第一行的方法复原第二行(图6),对于后两行我们需要按列从左到右进行复原,首先把13移动到位置9,9移动到位置10(图7),同时复原13和9(图8).依照同样的方法复原10、14(图9),最后三块随便按照某一方向旋转,如果拼图是可复原的,剩下的三块会自然地回到自己的位置上(图10)。在复原任意拼图的时候最后两行遵循同样的方法。
       既然是复原m*n,自然会有一些特殊情况:m=1,n>1; m>1,n=1; m=2,n=2; m=2,n=3; m=3,n=2 五种特殊情况,如果一个人知道如何复原4*4的拼图,其实他就能复原任何m*n的拼图。如果机器知道如何复原4*4的拼图,那它就不一定知道如何复原其它的拼图,写这篇博客的动因就是寻找一种复原拼图的普适算法(用面向对象的方法实现它),我们在寻找方法之前可以问自己,为什么人可以迅速掌握一个普遍适用的方法?是否可以用数学里的理论去分析它们呢?


寻求数学上的解法

         不可还原拼图: 不可还原拼图

        了解不可还原拼图对我们的探索会有很大帮助。

         可以用向量的形式表示图片与位置的对应,例如(3,4),我们可以这样定义:处于位置3的是图片4。对于拼图以2*3为例:(1,3)、(2,5)、(3,2)、(4,6)、(5,1)、(6,4)这样可以表示出一个打乱时的状态。

        这为我们提供了一些思路,但是有更好的方法来表示拼图的状态。用置换群表示会是这种形式:(1,3,2,5)(4,6),位置1对应3,位置3对应2,位置2对应5,位置5对应1,位置4对应 6,位置6对应4。 每个数字都有两重意义:位置和拼图编号,读者可以上网搜一些置换群的资料,只需很少的知识就能理解上面的表示方法。
       e表示拼图还原时的状态。
       每次移动拼图都能表示为一次置换运算,例如:由(1,3,2,5)(4,6)移动拼图为(1,6,4,3,2,5)可以用群运算表示为(1,4)(1,3,2,5)(4,6)。可以这样理解对换(1,4),位置1和位置4上的图片交换位置,拼图状态的每一次变化都是一次位置的对换。
      2*3的拼图一共存在7种对换, m*n(m>1,n>1)的拼图一共存在 2*m*n-m-n种对换。
      看看复原拼图的过程如何用置换运算表示,以(1,3,2,5)(4,6)为例,按步计算:
              1,(4,5)(1,3,2,5)(4,6)=(1,3,2,4,6,5)    //交换位置4和5图片
              2,(5,6)(1,3,2,4,6,5)=(1,3,2,4,5)             //交换位置5和6的图片,6回到了自己的位置(这里需要说明6是空缺的那一块)
              3,(3,6)(1,3,2,4,5)=(1,6,3,2,4,5)
              4,     (2,3)(1,6,3,2,4,5)=(1,6,2,4,5)
              5,     (2,5)(1,6,2,4,5)=(1,6,5)(2,4)
              6,     (5,6)(1,6,5)(2,4)=(1,5)(2,4)
              7,     (3,6)(1,5)(2,4)=(1,5)(2,4)(6,3)
              8,(2,3)(1,5)(2,4)(6,3)=(1,5)(2,4,3,6)
              9,     (1,2)(1,5)(2,4,3,6)=(1,5,2,4,3,6)
              10,   (1,4)(1,5,2,4,3,6)=(1,5,2)(3,6,4)
              11,   (4,5)(1,5,2)(3,6,4)=(1,4,3,6,5,2)
               12,  (5,6)(1,4,3,6,5,2)=(1,4,3,5,2)
               13,  (3,6)(1,4,3,5,2)=(1,4,6,3,5,2)
               14,  (2,3)(1,4,6,3,5,2)=(1,4,6,2)(3,5)
               15,  (2,5)(1,4,6,2)(3,5)=(1,4,6,5,3,2)
               16,(5,6)(1,4,6,5,3,2)=(1,4,5,3,2)
              17 ,(3,6)(1,4,5,3,2)=(1,4,5,6,3,2)
              18,(2,3)(1,4,5,6,3,2)=(1,4,5,6,2)
             19 ,(1,2)(1,4,5,6,2)=(1,4,5,6)
             20,(1,4)(1,4,5,6)=(4,5,6)
             21, (4,5)(4,5,6)=(5,6)
             22,(5,6)(5,6)=e
        经过22步把拼图复原,这些计算过程模仿了人复原拼图用的方法。

总结

      现在我们已经找到了人复原拼图遵循的普遍方法,又在数学上找到了移动的对应的表示方式,所以到此可以说已经找到了自动复原拼图的算法。拼图的数学上的解法,有一个有意思之处:每个数字都有双重的含义(即表示图片又表示位置)。由于有其他事情我并未真正实现这个算法,在以后的我会先制作一个拼图游戏,然后再去实现它。如果读到这篇博客的人,对这个问题也有兴趣,也可以按照这个思路自己去实现它。

    


               
          
    
     

       


对显微镜图片进行m*n拼图可以借助不同的工具和方法,以下为你介绍常见的几种方式: ### 使用Python和OpenCV库 OpenCV是用于计算机视觉任务的强大库,可编写Python脚本来完成拼图。 ```python import cv2 import numpy as np # 读取图片列表,这里假设图片按顺序命名为 image_0.jpg, image_1.jpg 等 image_paths = [f'image_{i}.jpg' for i in range(m * n)] images = [cv2.imread(path) for path in image_paths] # 初始化空白画布 height, width = images[0].shape[:2] result = np.zeros((height * m, width * n, 3), dtype=np.uint8) # 拼接图片 for i in range(m): for j in range(n): index = i * n + j result[i * height:(i + 1) * height, j * width:(j + 1) * width] = images[index] # 保存结果 cv2.imwrite('mosaic.jpg', result) ``` 使用时,需将`m`和`n`替换为实际的拼图行列数,同时确保图片路径和命名正确。 ### 使用Adobe Photoshop 1. 打开Photoshop软件,依次点击“文件”-“脚本”-“将文件载入堆栈”。 2. 在弹出的对话框中,点击“浏览”,选择要拼接的显微镜图片,点击“确定”。 3. 图片载入后,选择“编辑”-“自动对齐图层”,在对话框中选择合适的对齐方式,如“自动”,点击“确定”,软件会自动对齐图片。 4. 对齐完成后,选择“编辑”-“自动拼接图层”,Photoshop会尝试将图片拼接成完整图像。 5. 手动调整拼接效果,如裁剪多余部分、调整颜色等。 6. 完成调整后,点击“文件”-“存储为”,选择合适的格式保存图片。 ### 使用ImageJ软件 1. 打开ImageJ软件,依次点击“File”-“Import”-“Image Sequence”,选择要拼接的图片序列。 2. 图片导入后,点击“Plugins”-“Stitching”-“Pairwise stitching”。 3. 在弹出的对话框中,设置图片的排列方式(m*n)和其他参数,点击“OK”。 4. 软件会自动计算图片之间的重叠区域并进行拼接。 5. 拼接完成后,可对结果进行裁剪、调整等操作。 6. 点击“File”-“Save As”保存拼接后的图片。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值