上次講了數位影像處理的一題,今天再貼一題
Geometric transform (test image: fig3.tif)
Develope geometric transform program that will rotate, translate, and scale an imageby specified amounts, using the nearest neighbor and bilinear interpolationmethods, respectively.
背景
在對映像進行空間變換的過程中,典型的情況是在對映像進行放大,旋轉處理的時候,映像會出現失真的現象。這是由於在變換之後的映像中,存在著一些變換之前的映像中沒有的像素位置。處理這一問題的方法被稱為映像灰階級插值。常用的插值方式有三種:最近鄰域插值、雙線性插值、雙立方插值。理論上來講,最近鄰域插值的效果最差,雙立方插值的效果最好,雙線性插值的效果介於兩者之間。不過對於要求不是非常嚴格的映像插值而言,使用雙線性插值通常就足夠了。
最近領域演算法Matlab代碼
sourcePic=imread('fig3.tif');%以下為了彩色映像%[m,n,o]=size(sourcePic);%grayPic=rgb2gray(sourcePic);grayPic=sourcePic;[m,n]=size(grayPic);%比例係數為0.2-5.0K = str2double(inputdlg('請輸入比例係數(0.2 - 5.0)', '輸入比例係數', 1, {'0.5'}));%驗證範圍if (K < 0.2) && (K > 5.0) errordlg('比例係數不在0.2 - 5.0範圍內', '錯誤'); error('請輸入比例係數(0.2 - 5.0)');endfigure;imshow(grayPic);width = K * m; height = K * n;resultPic = uint8(zeros(width,height));widthScale = m/width;heightScale = n/height;for x = 5:width - 5 for y = 5:height - 5 xx = x * widthScale; yy = y * heightScale; if (xx/double(uint16(xx)) == 1.0) && (yy/double(uint16(yy)) == 1.0) % if xx and yy is integer,then J(x,y) <- I(x,y) resultPic(x,y) = grayPic(int16(xx),int16(yy)); else % xx or yy is not integer a = double(round(xx)); % (a,b) is the base-dot b = double(round(yy)); resultPic(x,y) = grayPic(a,b); % calculate J(x,y) end endendfigure;rotate(resultPic,-20);imshow(resultPic);
雙線性插值Matlab演算法
sourcePic=imread('fig3.tif');%以下為了彩色映像%[m,n,o]=size(sourcePic);%grayPic=rgb2gray(sourcePic);grayPic=sourcePic;[m,n]=size(grayPic);%比例係數為0.2-5.0K = str2double(inputdlg('請輸入比例係數(0.2 - 5.0)', '輸入比例係數', 1, {'0.5'}));%驗證範圍if (K < 0.2) or (K > 5.0) errordlg('比例係數不在0.2 - 5.0範圍內', '錯誤'); error('請輸入比例係數(0.2 - 5.0)');endfigure;imshow(grayPic);%輸出圖片長寬width = K * m; height = K * n;resultPic = uint8(zeros(width,height));widthScale = n/width;heightScale = m/height;for x = 5:width-5 for y = 5:height-5 xx = x * widthScale; yy = y * heightScale; if (xx/double(uint16(xx)) == 1.0) && (yy/double(uint16(yy)) == 1.0) % if xx and yy is integer,then J(x,y) <- I(x,y) resultPic(x,y) = grayPic(int16(xx),int16(yy)); else % xx or yy is not integer a = double(uint16(xx)); % (a,b) is the base-dot b = double(uint16(yy)); x11 = double(grayPic(a,b)); % x11 <- I(a,b) x12 = double(grayPic(a,b+1)); % x12 <- I(a,b+1) x21 = double(grayPic(a+1,b)); % x21 <- I(a+1,b) x22 = double(grayPic(a+1,b+1)); % x22 <- I(a+1,b+1) resultPic(x,y) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12) ); end endendfigure;resultPic = imrotate(resultPic,-20);imshow(resultPic);
效果如下
最近領域演算法放大2倍並順時針旋轉20度
雙線性插值演算法放大2倍並順時針旋轉20度
體會
該實驗表明雙線性插值得到的映像效果是比較好的。能夠避免採用最近領域插值方式時可能存在的映像模糊、塊狀失真等問題。但雙線性插值也存在問題,在放大倍數比較高的時候,映像失真將會比較嚴重,此時應該考慮使用更高階的插值演算法。