用Matlab解《2013年數據建模比賽》圖像碎片拼接題


摘要: matlab,數學建模,碎片拼接

  額,最近摳c++摳累了,突然心血來潮翻看近年來的大學生數學建模題。相比當年參加比賽的題目,總體感覺現在的題目越來越接近生活了。可能是多了一些經歷,對一些題特別有感覺,加之聯想起以前做完一道難題得到的興奮感,一個想法涌上心頭,為什么不利用現在的知識來好好“收拾收拾”它們呢。因此便有了這篇的文章,一方面是分享下自己的想法,另外也是鍛煉下自己的文筆,身為程序猿,是時候改變一下一些習慣了。選出特別感興趣的題目《2013年數學建模B賽題-圖像碎片拼接》,開弄!

 

  題目鏈接:http://www.mcm.edu.cn/html_cn/block/8579f5fce999cdc896f78bca5d4f8237.html

  題目按切割方式不同歸類為三個子問題:單面縱切,單面縱橫切,雙面縱橫切,其中前兩個又分為中英文紙張的情況,三個問題依次越來越復雜,越來越接近實際情況。不過相較於生活中的問題,《女子將5萬鈔票撕成碎片續:丈夫辭職在家拼錢》,http://news.qq.com/a/20120506/000091.htm,建模題還是比較小兒科的。 

  單面縱切:可以理解為對n個碎片塊進行“行內”排列組合,最終要求是使碎片邊界無縫接合起來。排列組合的話可以用神經網絡,遺傳算法等智能算法實現,“無縫”需要一個量來表征。前面智能算法對碎片不同組合時的無縫量進行評估,之后得到的最優解。這是學院派的解法,以此思路進行下去,一篇華麗的文章就可以出爐了。另外兩個子問題也可以作類似的分解。

 

  下面是我實現的解法,以前面方法相比,這種方法有些“簡單粗暴”,先上matlab代碼先(復制后放在相應的文件夾里運行即可):

clear all;clc;close all
%% 碎片拼接
file_list= dir('*.bmp'); % 獲取文件列表
if size(file_list,1)>0
    image_list = {file_list.name};
else
    error('no image')
end
file_num=size(image_list,2);
score=zeros(1,file_num);
feature=cell(1,file_num);
for ind=1:file_num % 計算碎片特征
    filename=cell2mat(image_list(ind));
    a=imread(filename);
    [row,col,len]=size(a);
    if len==3
        a=rgb2gray(a);
    end
    a_d=double(a);
    
    f=a_d(:,1)';
    tmp1=f.*f;
    tmp2=sqrt( sum(tmp1) );
    f=f/tmp2;
    one.left=f;
    one.left_std=std(f);
    
    f=a_d(:,end)';
    tmp1=f.*f;
    tmp2=sqrt( sum(tmp1) );
    f=f/tmp2;
    one.right=f;
    one.right_std=std(f);
    
    feature{ind}=one;
end
%% 計算碎塊的相似性矩陣
score_left=zeros(file_num,file_num);
score_right=zeros(file_num,file_num);
std_thr=0.001;
for y=1:file_num % compare
    for x=1:file_num
        if y==x
            continue;
        end        
        score_left(y,x)=feature{y}.left*feature{x}.right';
        score_right(y,x)=feature{y}.right*feature{x}.left';
        if feature{y}.left_std<std_thr
            score_left(y,x)=0;
        end
        if feature{y}.right_std<std_thr
            score_right(y,x)=0;
        end
    end
end
%% 計算塊間相似性
order=[1];
order_left=2:file_num; % order,第一個保證前后都有對象
while 1
    order
    if isempty(order_left)
        break;
    end
    left=order(1);right=order(end);
    score=score_left(left,:);
    [c,i]=max(score);
    if c(1)>0.95 && any(order_left==i(1))
        order=[i order];
        order_left(order_left==i(1))=[];
    end
    score=score_right(right,:);
    [c,i]=max(score);
    if c(1)>0.95 && any(order_left==i(1))
        order=[order i];
        order_left(order_left==i(1))=[];
    end
end
%% 拼接
b=[];
for ind=1:file_num % 拼接
    filename=cell2mat(image_list(order(ind)));
    a=imread(filename);
    [row,col,len]=size(a);
    if len==3
        a=rgb2gray(a);
    end
    b=[b a];
end
%% show
imshow(b)

  大概的思路是先計算塊的特征,然后計算塊間的相似性,最后進行拼接。其實看代碼更容易理解,其中的無縫量選擇,可以應用在前面方法的實現里。

拼接后的效果圖:

中文:                                                                                英文:

           

 

~~Yemuzi分享文章,歡迎拍磚~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM