MATLAB数字图像处理 实验一:图像处理基本操作(平移、放大、缩小、旋转、插值)
目錄
- 一、實驗目的
- 二、實驗環境
- 三、實驗內容
- 題目
- 相關知識
- 部分核心代碼
- 實驗結果
- 分析:兩種插值法優缺點
- 四、實驗心得
一、實驗目的
1、熟悉并掌握MATLAB工具的使用;?
2、實現圖像的讀取、顯示、存儲、平移、鏡像、放大、縮小及旋轉操作;
3、掌握常用的插值方法,并了解其優缺點。
二、實驗環境
Matlab 2020B
三、實驗內容
題目
1、讀入一幅RGB圖像,變換為灰度圖像和二值圖像,并在同一個窗口內分別顯示RGB圖像和灰度圖像,注上文字標題,并將結果以文件形式存到磁盤上。
2、對圖像執行平移、鏡像(水平鏡像、垂直鏡像)放大、縮小及旋轉操作,其中放大、旋轉操作分別采用最近鄰插值及雙線性插值方法實現,要求根據算法自己編寫代碼實現,并分析兩種插值方法的優缺點。
相關知識
在matlab環境中,調用imread()函數可讀入圖像,默認的存儲方式為的矩陣,分RGB三個通道。值類型為uint8,即取值范圍為0~255。
rgb2gray()函數將RGB三個通道存儲的圖像消除色調和飽和度,保留亮度,將RGB圖像轉為灰度圖。
im2bw(I,level)函數基于閾值將圖像轉化為二值圖像。輸入圖像可以為RGB圖像,也可以為灰度圖像。level參數為閾值取值范圍為0到1之間的小數,將大于閾值的像素點變為白色(1),其他像素點變為黑色(0)。
圖像平移時,設某個像素點坐標為(x0,y0)(x_0,y_0)(x0?,y0?),經過平移(tx,ty)(t_x,t_y)(tx?,ty?),達到坐標為(x1,y1)(x_1,y_1)(x1?,y1?)。該關系可記為:{x1=x0+txy1=y0+ty\begin{cases}x_1=x_0+t_x\\y_1=y_0+t_y\end{cases}{x1?=x0?+tx?y1?=y0?+ty??,用矩陣形式可以記作:(x1y11)=(x0y01)(100010txty1)\begin{pmatrix}x_1&y_1&1\end{pmatrix}=\begin{pmatrix}x_0&y_0&1\end{pmatrix}\begin{pmatrix}1&0&0\\0&1&0\\t_x&t_y&1\end{pmatrix}(x1??y1??1?)=(x0??y0??1?)???10tx??01ty??001????。在實現時,記圖像的高為hhh,寬為www,需要判斷x1,y1x_1,y_1x1?,y1?與h,wh,wh,w的大小關系,不能發生下標越界。
圖像水平鏡像時,記圖像寬為www。則原像素點(x0,y0)(x_0,y_0)(x0?,y0?)變為(w?x0,y0)(w-x_0,y_0)(w?x0?,y0?),即:{x1=w?x0y1=y0\begin{cases}x_1=w-x_0\\y_1=y_0\end{cases}{x1?=w?x0?y1?=y0??。用矩陣形式記作:{x1=x0+txy1=y0+ty\begin{cases}x_1=x_0+t_x\\y_1=y_0+t_y\end{cases}{x1?=x0?+tx?y1?=y0?+ty??,用矩陣形式可以記作:(x1y11)=(x0y01)(?100010w01)\begin{pmatrix}x_1&y_1&1\end{pmatrix}=\begin{pmatrix}x_0&y_0&1\end{pmatrix}\begin{pmatrix}-1&0&0\\0&1&0\\w&0&1\end{pmatrix}(x1??y1??1?)=(x0??y0??1?)????10w?010?001????。
圖像垂直鏡像時,記圖像高為hhh。則原像素點(x0,y0)(x_0,y_0)(x0?,y0?)變為(x0,h?y0)(x_0,h-y_0)(x0?,h?y0?),即:{x1=x0y1=h?y0\begin{cases}x_1=x_0\\y_1=h-y_0\end{cases}{x1?=x0?y1?=h?y0??。用矩陣形式記作:(x1y11)=(x0y01)(1000?100h1)\begin{pmatrix}x_1&y_1&1\end{pmatrix}=\begin{pmatrix}x_0&y_0&1\end{pmatrix}\begin{pmatrix}1&0&0\\0&-1&0\\0&h&1\end{pmatrix}(x1??y1??1?)=(x0??y0??1?)???100?0?1h?001????。
圖像放大分為兩個步驟:1.創建新的像素點位。2.給新的像素點位的對應位置賦值。
在使用最近鄰插值法時,直接用原圖中最近的像素點位給新圖賦值。
在使用雙線性插值法時,記原圖大小m?nm*nm?n,新圖大小a?ba*ba?b,則新圖的坐標(x0′,y0′)(x_0',y_0')(x0′?,y0′?)對應原圖(x0,y0)=(x0′?m/a,y0′?n/b)(x_0,y_0)=(x_0'*m/a,y_0'*n/b)(x0?,y0?)=(x0′??m/a,y0′??n/b)。找到與(x0,y0)(x_0,y_0)(x0?,y0?)最近的四個整數點位記作(x1,y1),(x1,y2),(x2,y1),(x2,y2)(x_1,y_1),(x_1,y_2),(x_2,y_1),(x_2,y_2)(x1?,y1?),(x1?,y2?),(x2?,y1?),(x2?,y2?),其對應點位上的灰度值記為P11,P12,P21,P22P_{11},P_{12},P_{21},P_{22}P11?,P12?,P21?,P22?。
則(x0′,y0′)(x_0',y_0')(x0′?,y0′?)的灰度值為
y2?y0y2?y1(x2?x0x2?x1P11+x0?x1x2?x1P21)+y0?y1y2?y1(x2?x0x2?x1P12+x0?x1x2?x1P22)\frac{y_2-y_0}{y_2-y_1}(\frac{x_2-x_0}{x_2-x_1}P_{11}+\frac{x_0-x_1}{x_2-x_1}P_{21})+\frac{y_0-y_1}{y_2-y_1}(\frac{x_2-x_0}{x_2-x_1}P_{12}+\frac{x_0-x_1}{x_2-x_1}P_{22})y2??y1?y2??y0??(x2??x1?x2??x0??P11?+x2??x1?x0??x1??P21?)+y2??y1?y0??y1??(x2??x1?x2??x0??P12?+x2??x1?x0??x1??P22?)
在實現時,可能需要去掉邊框上的像素點值,以防止下標越界等情況。若(x0,y0)=(x0′?m/a,y0′?n/b)(x_0,y_0)=(x_0'*m/a,y_0'*n/b)(x0?,y0?)=(x0′??m/a,y0′??n/b)為整數,則直接取該點灰度值賦給(x0′,y0′)(x_0',y_0')(x0′?,y0′?)而無需進行雙線性插值。
圖像縮小算法與放大類似,只要新圖像大小a?ba*ba?b小于原圖像大小m?nm*nm?n即可。
在對圖像進行旋轉時,為了對圖像中心進行旋轉,需要先把坐標系平移到中心。記原中心點(x′,y′)=(0,0)(x',y')=(0,0)(x′,y′)=(0,0),則變換后的中心點(x,y)(x,y)(x,y)與原中心點關系為(xy1)=(x′y′1)(1000?10?0.5w0.5h1)\begin{pmatrix}x&y&1\end{pmatrix}=\begin{pmatrix}x'&y'&1\end{pmatrix}\begin{pmatrix}1&0&0\\0&-1&0\\-0.5w&0.5h&1\end{pmatrix}(x?y?1?)=(x′?y′?1?)???10?0.5w?0?10.5h?001????.則旋轉分為三個步驟:將x′o′yx'o'yx′o′y變成xoyxoyxoy,將該點順時針轉α\alphaα度,最后將xoyxoyxoy變回x′o′y′x'o'y'x′o′y′。則完整的變換為:
(xy1)=(x′y′1)=(1000?10?0.5wold0.5hold1)(cos?α?sin?α0sin?αcos?α0001)(1000?10?0.5wnew0.5hnew1)\begin{pmatrix}x&y&1\end{pmatrix}=\begin{pmatrix}x'&y'&1\end{pmatrix}=\begin{pmatrix}1&0&0\\0&-1&0\\-0.5w_{old}&0.5h_{old}&1\end{pmatrix}\begin{pmatrix}\cos\alpha&-\sin\alpha&0\\\sin\alpha&\cos\alpha&0\\0&0&1\end{pmatrix}\begin{pmatrix}1&0&0\\0&-1&0\\-0.5w_{new}&0.5h_{new}&1\end{pmatrix}(x?y?1?)=(x′?y′?1?)=???10?0.5wold??0?10.5hold??001???????cosαsinα0??sinαcosα0?001???????10?0.5wnew??0?10.5hnew??001????
由于前后圖像大小不一定相等。所以需要進行插值處理,可以使用上文中提到的兩種插值算法。新圖像寬為w′=∣cos?α∣?w+∣sin?α∣?hw'=|\cos\alpha|*w+|\sin\alpha|*hw′=∣cosα∣?w+∣sinα∣?h。新圖像的高為h′=∣sin?α∣?w+∣cos?α∣?hh'=|\sin\alpha|*w+|\cos\alpha|*hh′=∣sinα∣?w+∣cosα∣?h
部分核心代碼
I_0=imread("test.jpg"); I_1=rgb2gray(I_0); I_2=im2bw(I_0,0.5); %figure('P1','P2','P3','P4') title("實驗1-1") subplot(1,3,1);imshow(I_0);title('原圖') subplot(1,3,2);imshow(I_1);title('灰度圖') subplot(1,3,3);imshow(I_2);title('二值化') savefig("lab1_1.fig")完成了讀入一幅RGB圖像,變換為灰度圖像和二值圖像,并在同一個窗口內分別顯示RGB圖像和灰度圖像,注上文字標題,并將結果以文件形式存到磁盤上。
I=imread("test.jpg"); [R,C,color]=size(I); res=zeros(R,C,color); for color=1:3for i=1:Rfor j=1:Cnewx=i+60;newy=j+60;if ((newx<=R) && (newy<=C))res(newx,newy,color)=I(i,j,color);endendend end imshow(uint8(res))完成了對圖像的平移操作,對圖像向右下平移60個像素。對于每個像素點,先平移,再判斷下標是否越界,最后將像素點填入。
I=imread("test.jpg"); [R,C,ch]=size(I); res=zeros(R,C,ch); for color=1:3for i=1:Rfor j=1:C-1res(i,j,color)=I(i,C-j,color);endend end imshow(uint8(res))完成了對圖像的垂直翻轉操作。沒有使用矩陣運算。
I=imread("test.jpg"); [R,C,ch]=size(I); res=zeros(R,C,ch); for color=1:3for i=1:R-1for j=1:Cres(i,j,color)=I(R-i,j,color);endend end imshow(uint8(res))完成了對圖像的水平翻轉操作。沒有使用矩陣運算。
I=imread("test2.jpg"); [h,w,ch]=size(I); height=1500; width=1500; newimg=zeros(height,width); multh=height/h; multw=width/w; for i=1:heightfor j=1:widthfor c=1:3oldi=round(i/multh);oldj=round(j/multw);if (oldi>=1&&oldi<=h&&oldj>=1&&oldj<=w)newimg(i,j,c)=I(oldi,oldj,c);endendend end imshow(uint8(newimg))完成了對圖像的放大/縮小操作。使用最近鄰插值法。先把新圖中的像素點除以放大倍數映射得到其在原圖中的位置,將該位置值四舍五入找到最近鄰,直接將最近鄰的值填入。
I=imread('test2.jpg'); [m,n,ch]=size(I); width=100; height=100; newimg = uint8(zeros(width,height,3)); % 計算放大/縮小倍數 widthScale = m/width; heightScale = n/height; for ch=1:3for x = 1:width - 1for y = 1:height - 1 xx = x * widthScale;%新圖像位置對應原圖像位置 yy = y * heightScale;%新圖像位置對應原圖像位置 if (xx/double(uint16(xx)) == 1.0) && (yy/double(uint16(yy)) == 1.0)newimg(x,y,ch) = I(int16(xx),int16(yy),ch);%若正好對應到整數點,則直接賦值,不插值else a = double(uint16(xx));%找整數點b = double(uint16(yy));if a==0||b==0||a>=m||b>=n%下標不能越界continue;endx11 = double(I(a,b,ch)); % x11 = I(a,b)x12 = double(I(a,b+1,ch)); % x12 = I(a,b+1)x21 = double(I(a+1,b,ch)); % x21 =I(a+1,b)x22 = double(I(a+1,b+1,ch)); % x22 = I(a+1,b+1)newimg(x,y,ch) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12));endendend end imshow(newimg);完成了對圖像的放大/縮小操作。使用雙線性插值法。先把新圖中的像素點除以放大倍數映射得到其在原圖中的位置,如果是整數則直接填入,如果不是整數則找到與其相鄰的四個點,按照上文中的公式進行插值,將該值填入。
I=imread("test2.jpg"); angle=30; [h,w,d]=size(I); theta=angle/180*pi; cos_val = cos(theta); sin_val = sin(theta);w2=round(abs(cos_val)*w+h*abs(sin_val)); h2=round(abs(cos_val)*h+w*abs(sin_val)); img_rotate = uint8(zeros(h2,w2,3)); %像素是整數for x=1:w2for y=1:h2x0 = uint32(x*cos_val + y*sin_val -0.5*w2*cos_val-0.5*h2*sin_val+0.5*w);%展開矩陣乘法y0 = uint32(y*cos_val - x*sin_val +0.5*w2*sin_val-0.5*h2*cos_val+0.5*h);%展開矩陣乘法x0=round(x0); %最近鄰y0=round(y0); %最近鄰if x0>=1 && y0>=1&& x0<=w && y0<=h %檢測下標不能越界img_rotate(y,x,:) = I(y0,x0,:);endend end imshow(img_rotate)完成了對圖像的旋轉操作。對于圖像大小會發生變化的情況,使用最近鄰插值法處理縮放。同理,按四舍五入方式找到最近鄰。
angle=45; I=imread('test2.jpg'); imshow(I); [h,w,d]=size(I); theta=angle/180*pi; M=[cos(theta) -sin(theta) 0;sin(theta) cos(theta) 0;0 0 1]; leftup=[1 1 1]*M; %新圖左上角 rightup=[1 w 1]*M; %新圖右上角 leftdown=[h 1 1]*M; %新圖左下角 rightdown=[h w 1]*M; %新圖右下角 cos_val = cos(theta); sin_val = sin(theta);w2=round(abs(cos_val)*w+h*abs(sin_val));%新圖寬度 h2=round(abs(cos_val)*h+w*abs(sin_val));%新圖高度 img_rotate=uint8(zeros(h2,w2,3)); dy=abs(min([leftup(1) rightup(1) leftdown(1) rightdown(1)])); %取得y方向的負軸超出的偏移量 dx=abs(min([leftup(2) rightup(2) leftdown(2) rightdown(2)])); %取得x方向的負軸超出的偏移量for i=1-dy:h2-dyfor j=1-dx:w2-dxpix=[i j 1]/M; %用變換后圖像的點的坐標去尋找原圖像點的坐標,yy=pix(1)-floor(pix(1));xx=pix(2)-floor(pix(2));if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= wx11=floor(pix(1)); %四個相鄰的點y11=floor(pix(2));x12=floor(pix(1));y12=ceil(pix(2));x21=ceil(pix(1));y21=floor(pix(2));x22=ceil(pix(1));y22=ceil(pix(2));value_leftup=(1-xx)*(1-yy); %計算臨近四個點在雙線性插值中的權重value_rightup=xx*(1-yy);value_leftdown=(1-xx)*yy;value_rightdown=xx*yy;img_rotate(i+dy,j+dx,:)=value_leftup*I(x11,y11,:)+value_rightup*I(x12,y12,:)+ value_leftdown*I(x21,y21,:)+value_rightdown*I(x22,y22,:);endend endimshow(uint8(img_rotate))完成了對圖像的旋轉操作。對于圖像大小會發生變化的情況,使用雙線性插值法處理縮放。同理,先找到新圖中某點坐標對應原圖位置(利用矩陣除法),找到其相鄰的四個點位,按照上文中的公式進行插值。
實驗結果
對于題目1,完成了對圖片的讀取、灰度化、二值化操作。還生成了可以被matlab打開的.fig文件。
對于平移,正確地實現了圖像的平移,并且對其余部分補上黑色邊框。
對于左右鏡像翻轉,正確地實現了圖像的左右鏡像翻轉。
對于上下鏡像翻轉,正確地實現了圖像的上下鏡像翻轉。
成功將圖像放大,利用最近鄰插值。可以看到,放大的結果存在一定的鋸齒與馬賽克的現象。
成功將圖像縮小,利用最近鄰插值。
成功將圖像放大,利用雙線性插值。可以看到,放大的結果比起最近鄰插值更為平滑,沒有存在嚴重的鋸齒現象。
成功將圖像縮小,利用雙線性插值。可以看到,利用雙線性插值進行縮小時也沒有出現失真現象。
利用最近鄰插值法與雙線性插值法分別對圖像進行旋轉45°操作,并對其余區域填充為黑色。
分析:兩種插值法優缺點
最近鄰插值法優點:實現簡單,運行速度快。缺點:在放大圖像時可能出現鋸齒現象,圖像中一些曲線的邊緣不平滑。在放大后縮小回去還會出現一定的失真現象,使圖像看起來變得模糊了,像馬賽克。
雙線性插值法優點:一定程度上緩解了最近鄰插值法缺點出現的情況。放大圖像后圖像中的一些曲線看起來更平滑,對一張圖像反復放大縮小后失真現象不嚴重,處理效果較好。缺點:處理速度慢,在matlab2020B實驗環境中往往需要對一張圖像處理約3秒左右。對于圖像的最外圈邊緣也難以處理。
四、實驗心得
總結
以上是生活随笔為你收集整理的MATLAB数字图像处理 实验一:图像处理基本操作(平移、放大、缩小、旋转、插值)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nfs快速配置
- 下一篇: win7如何配置java环境变量_Win