1. 程式人生 > >matlab練習程式(尋找凸包,Graham掃描法)

matlab練習程式(尋找凸包,Graham掃描法)

  我不太清楚這個凸包在影象處理中到底會怎樣的運用,因為這個好像更多的是計算幾何或是圖形學裡面的東西。不過作為一個演算法,我感覺還是有必要研究一下的。我主要的參考資料是《演算法導論》的33.3和這個部落格

  程式碼在這裡,我只寫了主要過程,過分細節的判斷就省略了。這裡是逆時針尋找:

main.m

複製程式碼
clear all;
close all;
clc;

img=ones(256,256);
imshow(img);
[x y]=ginput();
x=round(x);
y=round(y);
n=length(x);
p=[];
for i=1:n
   img(y(i)-1:y(i)+1
,x(i)-1:x(i)+1)=0; p=[p;x(i) y(i)]; %待判斷凸包的點集 end imshow(img); %%下面計算凸包 [t index]=max(p(:,2)); %找到y最大的點的索引,這裡沒考慮當有多個這樣的點的情況 tmp_p=p(index,:); %找到y最大的點 tmp_heng=[tmp_p(1)+30,tmp_p(2)]; %設一個和y最大的點平行的點 for i=1:n %這裡沒判斷夾角相同的情況,當夾角相同,可以判斷當前點和p0點的距離。 jiao(i)=multi_jiao(tmp_heng,p(i,:),tmp_p); %求每個點和y最大的點的夾角,自己和自己夾角NAN
end jiao=jiao'; p=[p jiao]; p=sortrows(p,3); %按第三列排序,第三列是夾角度數 re{1}=p(n,1:2); %re相當於棧 re{2}=p(1,1:2); re{3}=p(2,1:2); top=3; %指向棧頂的指標 for i=3:n-1 while multi(p(i,1:2),re{top-1},re{top})>=0 %如果為正 top=top-1; end top=top+1; re{top}=p(i,1:2); end %下面是把找到的凸包上的點連線
for i=2:top img=drawline(img,re{i-1}(1),re{i-1}(2),re{i}(1),re{i}(2)); end img=drawline(img,re{1}(1),re{1}(2),re{top}(1),re{top}(2)); figure; imshow(img)
複製程式碼

multi_jiao.m  向量的夾角,0-180度

複製程式碼
function re=multi_jiao(p1,p2,p0)    %判斷<p10,p20>夾角,為排序做準備
    x=1;
    y=2;

    vec1=p1-p0;
    vec2=p2-p0;

    re=acos(dot(vec1,vec2)/(norm(vec1)*norm(vec2)))*180/pi;
end
複製程式碼

multi.m  叉積,判斷返回值的符號

複製程式碼
function re=multi(p1,p2,p0)     %p10,p20叉積,獲取正負,為正則棧頂的值不為凸包上的點,為負則為凸包上的點
    x=1;
    y=2;
   
   re=(p1(x)-p0(x))*(p2(y)-p0(y))-(p1(y)-p0(y))*(p2(x)-p0(x));

end
複製程式碼

drawline.m  畫線函式,matlab好像沒有,自己動手,豐衣足食

複製程式碼
function img=drawline(img,x1,y1,x2,y2)   %因為影象座標和數學函式座標y軸朝向相反,所以這裡所有y變數取相反數
    y1=-y1;
    y2=-y2;
    k=(y2-y1)/(x2-x1);
    b=y1-k*x1;
    
    mi=min(x1,x2);
    ma=max(x1,x2);
    for i=mi:ma
       img(-round(i*k+b),i)=0; 
    end
    
    mi=min(y1,y2);
    ma=max(y1,y2);
    for i=mi:ma
       img(-i,round((i-b)/k))=0; 
    end

end
複製程式碼

下面是一個結果,matlab最大的好處就是直觀的看到演算法結果: