影像的灰度變換——影像旋轉、影像的反色處理、對比度拉伸

葡萄乾是個程式設計師發表於2015-10-22

這次我們要處理的是對影像進行旋轉操作,具體要求,如下:

       自定義一個影像的仿射變換函式,用於旋轉給定的輸入影像,該函式的輸入引數包括處理前的影像和旋轉角度。輸入的角度為正數,表明處理結果為順時針旋轉,負數則為逆時針旋轉,輸出引數為處理後的影像。

       曾參考《數字影像處理(第三版)》一書中P51的公式編寫過自己的影像“旋轉”函式,但是在某些角度下,輸出結果卻發生了錯誤,至於原因,也由於時間關係,仍未思考出來。使用Matlab程式設計,原始碼如下:

%自己寫的函式
function []=myRotation(pho,angle)
im1=imread(pho);
subplot(121);
imshow(im1);
title('輸入影像');
im1=double(im1);
[r,c,h]=size(im1);
 
R=angle*pi/180;
h2 = ceil(r*cos(R)+c*sin(R));
w2 = ceil(r*sin(R)+c*cos(R));
im2=zeros(h2,w2,h);
 
T=[sin(R) cos(R); cos(R) -sin(R)];
%invT=inv(T);
for i=1:h
    for x=1:h2
        for y=1:w2
            temp=([x y]-[0 r*sin(R)])/T;
            temp(1)=ceil(temp(1));
            temp(2)=ceil(temp(2));
            if temp(2)>0 && temp(2)<=r && temp(1)>0 && temp(1)<=c
                im2(x,y,i)=im1(temp(2),temp(1),i);
            end
        end
    end
end
subplot(122);
imshow(uint8(im2));
title('輸出影像');

       另外,採用了一種方法(參考 點選開啟連結),同樣使用推匯出來的公式,採用反向對映的方法,結合雙線性內插,得出旋轉後的影像。但是得出來的結果,如輸入 180°,沒有出現輸出結果。參考後修改的程式如下:

function []=myRotation3(pho,angle)
im1=imread(pho);
im1=double(im1);
[m,n,h]=size(im1);
 
R = angle*pi/180;   %旋轉角度
%新影像大小
m2 = ceil(m*cos(R)+n*sin(R));
n2 = ceil(m*sin(R)+n*cos(R));
 
u0= m*sin(R);%平移量
 
%變換矩陣   
T=[cos(R),sin(R);-sin(R),cos(R)];
L = zeros(m2,n2);
for i=1:h
    for u=1:n2
      for v=1:m2
        %新影像座標變換到原影像座標x和y中
        temp = T*([u;v]-[u0;0]);
        x= temp(1);
        y= temp(2);
        if x>=1 & x<=m & y>=1 & y<=n    %若變換出的x和y在原影像範圍內
            x_low=floor(x);
            x_up=ceil(x);
            y_low=floor(y);
            y_up=ceil(y);
 			%雙線性內插值
            p1=im1(x_low,y_low,i);
            p2=im1(x_up,y_low,i);
            p3=im1(x_low,y_low,i);
            p4=im1(x_up,y_up,i);
            s=x-x_low;
            t=y-y_low;
            L(u,v,i)=(1-s)*(1-t)*p1+(1-s)*t*p3+(1-t)*s*p2+s*t*p4;
        end
      end
    end
end
 
imshow(uint8(L));
title('輸出影像');

而正確程式程式碼,則是通過研究參考 影像旋轉演算法原理點選開啟連結),在只有原理的情況下,研究透,將其轉化為 程式。MATLAB程式碼如下:

%這個旋轉才沒有bug
function []=myRotation(pho,angle)
im1=imread(pho);
subplot(121);
imshow(im1);
title('輸入影像');
im1=double(im1);
[r,c,h]=size(im1);
 
%將角度單位化為弧度單位
R=-angle*pi/180;
%這樣的寬高會出現BUG,原因不明
%h2 = ceil(r*cos(R)+c*sin(R));
%w2 = ceil(r*sin(R)+c*cos(R));
 
%將對角線作為旋轉後影像的寬高
h2=ceil(sqrt(r*r+c*c));
w2=h2;
 
im2=zeros(h2,w2,h);
 
%旋轉時x y的偏移量
dx=-0.5*w2*cos(R)-0.5*h2*sin(R)+0.5*c;
dy=0.5*w2*sin(R)-0.5*h2*cos(R)+0.5*r;
 
%採用反向對映
for i=1:h
    for x=1:h2
        for y=1:w2
            %由結果影像的座標 得出 原來影像的座標
            x0=ceil(x*cos(R)+y*sin(R)+dx); 
            y0=ceil(-x*sin(R)+y*cos(R)+dy);
            
            if x0>0 && x0<=r && y0>0 && y0<=c
                im2(x,y,i)=im1(x0,y0,i);
            end
        end
    end
end
%顯示影像
subplot(122);
imshow(uint8(im2));
title('輸出影像');


旋轉45°——> myRotation('實驗2_lena.bmp',45),結果如下:


旋轉-45°——> myRotation('實驗2_lena.bmp',-45),結果如下:


影像反色處理

       自定義一個函式,將輸入影像進行反色處理,該函式輸入引數為處理前的影像,輸出引數為處理後的影像。

Matlab程式設計,程式碼如下:

function []=myFanse(pho)
im1 = imread(pho);
subplot(121);
imshow(im1);
title('輸入影像');
im1 = double(im1);
[r c m] = size(im1);
im2 = zeros(r,c,m);
for i=1:m
for j=1:r
for k=1:c
im2(j,k,i)=255-im1(j,k,i); %由最高灰度級減去原座標位置的灰度級進行反色
end
end
end
im2 = uint8(im2);
subplot(122);
imshow(im2);
title('輸出影像');
       當然,其實也可以利用Matlab中的矩陣運算編寫程式,這樣程式可以更加精簡,這裡就不給出了。   

       myFase('實驗2_lena.bmp'),執行結果如下:


影像對比度拉伸變換

  自定義一個影像的對比度拉伸函式,將輸入影像的對比度拉伸到指定的灰度級區間,該函式的輸入引數包括處理前的影像、期望灰度級區間的最小值和最大值(如指定區間為[50 200]),輸出引數為處理後的影像。

Matlab程式碼如下:

function []=myContrConver(pho, mi, ma)
im1 = imread(pho);
subplot(121);
imshow(im1);
title('輸入影像');
im1 = double(im1);
[r c m] = size(im1);
im2 = zeros(r,c,m);
%for i=1:m
%    for j=1:r
%        for k=1:c
%            im2(j,k,i)=min+(im1(j,k,i)-minR)/(maxR-minR)*(max-min);
%        end
%    end
%end
 
%先對原影像的 灰度級 進行歸一化,再由歸一化的區間縮放至所需區間
tempIma1=im1(:,:,1);
tempIma2=im1(:,:,2);
tempIma3=im1(:,:,3);
im2(:,:,1)=mi+(im1(:,:,1)-min(tempIma1(:)))/(max(tempIma1(:))-min(tempIma1(:)))*(ma-mi);
im2(:,:,2)=mi+(im1(:,:,2)-min(tempIma2(:)))/(max(tempIma2(:))-min(tempIma2(:)))*(ma-mi);
im2(:,:,3)=mi+(im1(:,:,3)-min(tempIma3(:)))/(max(tempIma3(:))-min(tempIma3(:)))*(ma-mi);
 
im2=uint8(im2);
subplot(122);
imshow(im2);
title('輸出影像');


       myContrConver('實驗2_lena.bmp'),執行結果如下:



相關文章