摘要: matlab,數學建模,碎片拼接html
額,最近摳c++摳累了,忽然心血來潮翻看近年來的大學生數學建模題。相比當年參加比賽的題目,整體感受如今的題目愈來愈接近生活了。多是多了一些經歷,對一些題特別有感受,加之聯想起之前作完一道難題獲得的興奮感,一個想法涌上心頭,爲何不利用如今的知識來好好「收拾收拾」它們呢。所以便有了這篇的文章,一方面是分享下本身的想法,另外也是鍛鍊下本身的文筆,身爲程序猿,是時候改變一下一些習慣了。選出特別感興趣的題目《2013年數學建模B賽題-圖像碎片拼接》,開弄!c++
題目連接:http://www.mcm.edu.cn/html_cn/block/8579f5fce999cdc896f78bca5d4f8237.html算法
題目按切割方式不一樣歸類爲三個子問題:單面縱切,單面縱橫切,雙面縱橫切,其中前兩個又分爲中英文紙張的狀況,三個問題依次愈來愈複雜,愈來愈接近實際狀況。不過相較於生活中的問題,《女子將5萬鈔票撕成碎片續:丈夫辭職在家拼錢》,http://news.qq.com/a/20120506/000091.htm,建模題仍是比較小兒科的。 網絡
單面縱切:能夠理解爲對n個碎片塊進行「行內」排列組合,最終要求是使碎片邊界無縫接合起來。排列組合的話能夠用神經網絡,遺傳算法等智能算法實現,「無縫」須要一個量來表徵。前面智能算法對碎片不一樣組合時的無縫量進行評估,以後獲得的最優解。這是學院派的解法,以此思路進行下去,一篇華麗的文章就能夠出爐了。另外兩個子問題也能夠做相似的分解。spa
下面是我實現的解法,之前面方法相比,這種方法有些「簡單粗暴」,先上matlab代碼先(複製後放在相應的文件夾裏運行便可):htm
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)
大概的思路是先計算塊的特徵,而後計算塊間的類似性,最後進行拼接。其實看代碼更容易理解,其中的無縫量選擇,能夠應用在前面方法的實現裏。對象
拼接後的效果圖:blog
中文: 英文:get
~~Yemuzi分享文章,歡迎拍磚~~數學