matlab練習程式(矩形變換為單連通形狀)

Dsp Tian發表於2014-10-02

變換使用的模板必須是單連通的,而且模板中心必須在模板內,如果在模板中打個結或是月牙形,這裡的程式就處理不了了。

雖然非單連通模板也有辦法處理,不過不是這裡要討論的。

這裡用到的方法和矩形變換為圓那片文章中用的方法幾乎一樣,變換前後畫素按比例縮減,不過在判斷弧度和影象邊界到模板中心距離時略有不同。

變換為圓時弧度可以直接計算出來,而變換為任意形狀只能算出一個最小相似值。

至於影象邊界到模板中心距離只能分八種情況判斷了,處理圓時可以根據對稱性簡化程式,這裡似乎沒有什麼好辦法簡化。

變換細節上,那篇文章中使用的是正向插值,這裡使用正向插值則會產生很多空洞,因此選擇了更常見的逆向插值。

處理結果如下:

原圖:

模板:

結果:

matlab程式碼如下:

clear all;close all;clc;

img=imread('lena.jpg');
mask_line=imread('mask.bmp')>50;

[h w]=size(img);
imgn=zeros(h,w);

ind=find(mask_line==1);
[lineY lineX]=ind2sub([h w],ind);   %模板形狀畫素的位置
cenY=round(mean(lineY));            %模板形狀中心
cenX=round(mean(lineX));

lineAng=atan2(lineY-cenY,lineX-cenX);        %模板線上每個點到形狀中心弧度
lineR=sqrt((lineY-cenY).^2+(lineX-cenX).^2); %模板線上每個點到形狀中心距離

ang_ul=atan2(1-cenY,1-cenX);        %影象四個點與模板形狀中心弧度
ang_ur=atan2(1-cenY,w-cenX);
ang_dl=atan2(h-cenY,1-cenX);
ang_dr=atan2(h-cenY,w-cenX);

for y=1:h
    for x=1:w
        r=sqrt((x-cenX)^2+(y-cenY)^2);
        ang=atan2(y-cenY,x-cenX);

        if ang>=-pi && ang<ang_ul           %分別求八個象限影象邊界到模板中心距離
            R=abs(cenX/cos(ang));           %應該可以簡化,這樣判斷似乎繁瑣了
        elseif ang>=ang_ul && ang<-pi/2
            R=abs(cenY/cos(pi/2-ang));        
        elseif ang>=-pi/2 && ang<ang_ur
            R=abs(cenY/cos(pi/2+ang)); 
        elseif ang>=ang_ur && ang<0
            R=abs((w-cenX)/cos(pi-ang)); 
        elseif ang>=0 && ang<ang_dr
            R=abs((w-cenX)/cos(ang));           
        elseif ang>=ang_dr && ang< pi/2
            R=abs((h-cenY)/cos(pi/2-ang));    
        elseif ang>=pi/2 && ang<ang_dl
            R=abs((h-cenY)/cos(pi/2+ang));             
        elseif ang>=ang_dl && ang<=pi
            R=abs(cenX/cos(pi-ang));              
        end
            
        [junk index]=min(abs(ang-lineAng));     %距離最近的弧度
        newR=lineR(index);
        
        ss=R*r/newR;        %縮減擴充套件比例係數
        xx=round((ss*cos(ang)+cenX));
        yy=round((ss*sin(ang)+cenY));
       
        if xx>=1 && xx<=w && yy>=1 && yy<=h
            imgn(y,x)=img(yy,xx);
        end
                      
    end
end

imshow(img);
figure;imshow(mask_line);
figure;imshow(imgn,[])

題外話:

今天等了一天在京東訂的kindle,到下午5點都還沒送來,最後發現竟然是手機沒訊號,沒有收到送貨通知。

中國移動一定是看我用的2G卡,又沒開上網功能,欺負人,不給優先順序。

如果收到貨,也許現在正在玩kindle,就不會有這篇文章了。

相關文章