碎纸条拼接复原

有一份文字文件被纵向切割成为19条碎纸条,文字为中文,现通过计算机编程计算将其还原。图片切割如图所示:

1440598279_20150826204054

这个问题可以理解为碎纸条排列成一个序列,要使得碎纸条与碎纸条之间的差异最小。在这个问题中,可以将每张碎纸条理解为一个点,将两张纸条拼接起来时边缘的吻合程度为对应两个点的距离。由于文字文件两边都会有留白,所以最后一张碎纸条的右边与第一张碎纸条的左边都是留白,因此它们能很好吻合,这就使得碎纸条能够连接成为一个回路。这样子就可以将问题转化为求拜访每个地点后回到起点的最短路径的“旅行商问题”。“旅行商问题”常被称为“旅行推销员问题”,是指一名推销员要拜访多个地点时,如何找到在拜访每个地点一次后再回到起点的最短路径。

1 碎纸条吻合程度的量化

1.1 边缘吻合程度

图片在计算机中是以矩阵的形式表示的。例子中给出的是灰度图像,即图像没有色彩。灰度图像的像素数据就是一个矩阵,矩阵的行对应图像的高(单位为像素),矩阵的列对应图像的宽(单位为像素),矩阵的元素对应图像的像素,矩阵元素的值就是像素的灰度值。两张图片边缘的越能吻合,它们边缘对应像素的灰度值就越接近,所以在这里我们使用两张碎纸条边缘像素的灰度值的差的绝对值的和来描述两张碎纸条边缘的吻合程度。吻合度越小表示越吻合。即:

式中d表示吻合程度,akq表示碎纸条i第k行第q列的像素的灰度值,ak1表示碎纸条j第k行第一列的像素的灰度值。

1.2 邻接矩阵

我们用邻近矩阵的形式来表示任意两张碎纸条的吻合程度。我们规定,邻接矩阵中第i行第j列的元素dij表示将序号为j的碎纸条连接到序号为i的碎纸条的右边的吻合程度。因此,通过1.1中对碎纸条边缘吻合程度的量化,我们可以得到一个19*19的矩阵。

1.3 邻接矩阵的计算

邻接矩阵能够通过MATLAB编程计算出来,程序如下:

 
  
clear;clc; %运行本程序时需要将 m 文件放到存储碎纸条的文件夹中 %并且将MATLAB的根目录 CD 到储存碎纸条的文件夹中 ljjz = ones(19,19);  %邻接矩阵 for i = 0:18     %根据序号得到文件名     if(i<10)         imiph = ['00',num2str(i),'.bmp'];     else         imiph = ['0',num2str(i),'.bmp'];     end     for j = 0:18         if(j<10)             imjph = ['00',num2str(j),'.bmp'];         else             imjph = ['0',num2str(j),'.bmp'];         end         %读取图片,并且将图片矩阵转为double         imi = im2double(imread(imiph));         imj = im2double(imread(imjph));         [imh,iml] = size(imi);         %相减,求吻合度         mysum = sum(abs(imi(:,iml) - imj(:,1)));         ljjz(i+1,j+1) = mysum;     end end
 

 

 

运行这个程序就能得到邻接矩阵。

2 碎纸条拼接序列

2.1 旅行商模型

“旅行商问题”可以利用0-1规划求解。设xij = 1为将序号为j的碎纸条连接到序号为i的碎纸条的右边;dij为相应的吻合程度。对于任意一张碎纸条,只能有一张碎纸条连接在它的左边,也只能有一张碎纸条连接在它的右边,所以有以下两个约束条件。

由此可以得到以下0-1规划模型:

1440598293_20150826214258

 

2.2 LINGO求解

LINGO是一款用于求解线性或非线性规划模型的优秀的软件,我们将应用这款软件求解2.1总的模型。程序代码如下:

sets:          s/1..19/;          link(s,s):d,x;
endsets
Data:
d =  数据省略
enddata
min = @sum(s(i):@sum(s(j):x(i,j)*d(i,j)));
@for(s(i):@sum(s(j):x(i,j)) = 1);
@for(s(j):@sum(s(i):x(i,j)) = 1);
@for(s(i):@for(s(j):@bin(x(i,j))));

 

 

代码中的d为邻接矩阵,是1中MATLAB的计算结果。

3 拼接碎纸条

3.1 分析结果

通过2.2的计算,我们能够得到一个回路,但是这并不能很好的拼接碎纸条,因为我们并不知道从何开始拼接。由于文字文件的左右两端都会有留白,所以第一张碎纸条的左边应是有留白的,通过这个特点,我们能利用肉眼观察找到最左边的碎纸条。经过观察确定,编号为008的碎纸条为第一张碎纸条。这样子我们就能得到碎纸条的拼接顺序,如下:

8141215310216145913181171706

3.2 拼接碎纸条

利用3.1的分析结果,通过MATLAB编程,即可将碎纸条拼接成一张完整的文字文件。程序代码如下:

 
  
sets:
         s/1..19/;          link(s,s):d,x; endsets Data:=  数据省略 enddata min = @sum(s(i):@sum(s(j):x(i,j)*d(i,j))); @for(s(i):@sum(s(j):x(i,j)) = 1); @for(s(j):@sum(s(i):x(i,j)) = 1); @for(s(i):@for(s(j):@bin(x(i,j))));
 

 

 

拼接结果如下:

1440598300_20150826220425

从结果上看,拼接效果很好。

本问题是2013年全国大学生数学建模大赛B题的第一问,这篇文章是作者参考竞赛论文《基于旅行商模型的文字碎纸片拼接复原》写成,作为练习之用。本文程序由作者自己编写,方法参考竞赛获奖论文。

转载于:https://www.cnblogs.com/chenjiafeng/p/5330074.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2013年全国信息学奥林匹克竞赛(以下简称国赛)纸片B题是一道考察递推算法的题目。题目主要考查学生对递推算法的掌握及思维能力。 题目大意是:给出一张 $n\times m$ 的纸片,每个位置上初始写有1或0,依次进行 $t$ 次操作,每次操作选择一个初始为1的位置,将这个位置的1撕掉并在其上、下、左、右四个方向相邻位置加上1,如果该位置上原本是0,则不执行操作。最后统计剩余纸片上初始为1的位置数目。 对于这道题目,首先需要建立模型,将题目的要求转化为数学模型,进而进行求解。建立模型时,需要仔细思考,设计合理的递推式,同时需要保证递推式的正确性。在本题中,需要注意到纸片上的点在进行一次撕纸操作时,只会影响到相邻的四个位置。因此我们可以设置一个 $n\times m$ 的数组存储每个位置的值,然后按照题目要求进行 $t$ 次操作。每次选取初始位置后,通过递推式进行处理,同时需要注意判断位置是否越界,以及位置的初始值是否为1。最后统计数组中初始值为1的位置数目即为答案。 在解题过程中,需要分析算法的时间复杂度和空间复杂度。在此题中,时间复杂度为 $O(nmt)$,空间复杂度为 $O(nm)$。因此,需要在保证正确性的前提下,尽可能优化算法,减小时间和空间的占用。 对于本题,需要注意一些细节问题,如初始纸片上元素为0时的统计,纸片尺寸变化对边界的影响等。经过认真分析和细心实现,就能得到正确的答案。 总之,本题难度较大,需要考生具有一定的数学建模和编程能力。通过这种方式锻炼了学生的思维能力和算法水平,为科学研究和工程实践提供了有力的支撑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值