影象的灰度變換——影象旋轉、影象的反色處理、對比度拉伸
這次我們要處理的是對影象進行旋轉操作,具體要求,如下:
自定義一個影象的仿射變換函式,用於旋轉給定的輸入影象,該函式的輸入引數包括處理前的影象和旋轉角度。輸入的角度為正數,表明處理結果為順時針旋轉,負數則為逆時針旋轉,輸出引數為處理後的影象。
曾參考《數字影象處理(第三版)》一書中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'),執行結果如下: