一、實(shí)驗(yàn)?zāi)康?/h2>
1、熟悉并掌握MATLAB工具的使用;?
2、實(shí)現(xiàn)圖像的讀取、顯示、存儲(chǔ)、平移、鏡像、放大、縮小及旋轉(zhuǎn)操作;
3、掌握常用的插值方法,并了解其優(yōu)缺點(diǎn)。
二、實(shí)驗(yàn)環(huán)境
Matlab 2020B
三、實(shí)驗(yàn)內(nèi)容
題目
1、讀入一幅RGB圖像,變換為灰度圖像和二值圖像,并在同一個(gè)窗口內(nèi)分別顯示RGB圖像和灰度圖像,注上文字標(biāo)題,并將結(jié)果以文件形式存到磁盤上。
2、對(duì)圖像執(zhí)行平移、鏡像(水平鏡像、垂直鏡像)放大、縮小及旋轉(zhuǎn)操作,其中放大、旋轉(zhuǎn)操作分別采用最近鄰插值及雙線性插值方法實(shí)現(xiàn),要求根據(jù)算法自己編寫代碼實(shí)現(xiàn),并分析兩種插值方法的優(yōu)缺點(diǎn)。
相關(guān)知識(shí)
在matlab環(huán)境中,調(diào)用imread()函數(shù)可讀入圖像,默認(rèn)的存儲(chǔ)方式為的矩陣,分RGB三個(gè)通道。值類型為uint8,即取值范圍為0~255。
rgb2gray()函數(shù)將RGB三個(gè)通道存儲(chǔ)的圖像消除色調(diào)和飽和度,保留亮度,將RGB圖像轉(zhuǎn)為灰度圖。
im2bw(I,level)函數(shù)基于閾值將圖像轉(zhuǎn)化為二值圖像。輸入圖像可以為RGB圖像,也可以為灰度圖像。level參數(shù)為閾值取值范圍為0到1之間的小數(shù),將大于閾值的像素點(diǎn)變?yōu)榘咨?),其他像素點(diǎn)變?yōu)楹谏?)。
圖像平移時(shí),設(shè)某個(gè)像素點(diǎn)坐標(biāo)為 ( x 0 , y 0 ) (x_0,y_0) (x0?,y0?),經(jīng)過平移 ( t x , t y ) (t_x,t_y) (tx?,ty?),達(dá)到坐標(biāo)為 ( x 1 , y 1 ) (x_1,y_1) (x1?,y1?)。該關(guān)系可記為: { x 1 = x 0 + t x y 1 = y 0 + t y \begin{cases}x_1=x_0+t_x\\y_1=y_0+t_y\end{cases} {x1?=x0?+tx?y1?=y0?+ty??,用矩陣形式可以記作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( 1 0 0 0 1 0 t x t y 1 ) \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? ?。在實(shí)現(xiàn)時(shí),記圖像的高為 h h h,寬為 w w w,需要判斷 x 1 , y 1 x_1,y_1 x1?,y1?與 h , w h,w h,w的大小關(guān)系,不能發(fā)生下標(biāo)越界。
圖像水平鏡像時(shí),記圖像寬為 w w w。則原像素點(diǎn) ( x 0 , y 0 ) (x_0,y_0) (x0?,y0?)變?yōu)?span id="n5n3t3z" class="katex--inline"> ( w ? x 0 , y 0 ) (w-x_0,y_0) (w?x0?,y0?),即: { x 1 = w ? x 0 y 1 = y 0 \begin{cases}x_1=w-x_0\\y_1=y_0\end{cases} {x1?=w?x0?y1?=y0??。用矩陣形式記作: { x 1 = x 0 + t x y 1 = y 0 + t y \begin{cases}x_1=x_0+t_x\\y_1=y_0+t_y\end{cases} {x1?=x0?+tx?y1?=y0?+ty??,用矩陣形式可以記作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( ? 1 0 0 0 1 0 w 0 1 ) \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? ?。
圖像垂直鏡像時(shí),記圖像高為 h h h。則原像素點(diǎn) ( x 0 , y 0 ) (x_0,y_0) (x0?,y0?)變?yōu)?span id="n5n3t3z" class="katex--inline"> ( x 0 , h ? y 0 ) (x_0,h-y_0) (x0?,h?y0?),即: { x 1 = x 0 y 1 = h ? y 0 \begin{cases}x_1=x_0\\y_1=h-y_0\end{cases} {x1?=x0?y1?=h?y0??。用矩陣形式記作: ( x 1 y 1 1 ) = ( x 0 y 0 1 ) ( 1 0 0 0 ? 1 0 0 h 1 ) \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? ?。
圖像放大分為兩個(gè)步驟:1.創(chuàng)建新的像素點(diǎn)位。2.給新的像素點(diǎn)位的對(duì)應(yīng)位置賦值。
在使用最近鄰插值法時(shí),直接用原圖中最近的像素點(diǎn)位給新圖賦值。
在使用雙線性插值法時(shí),記原圖大小
m
?
n
m*n
m?n,新圖大小
a
?
b
a*b
a?b,則新圖的坐標(biāo)
(
x
0
′
,
y
0
′
)
(x_0',y_0')
(x0′?,y0′?)對(duì)應(yīng)原圖
(
x
0
,
y
0
)
=
(
x
0
′
?
m
/
a
,
y
0
′
?
n
/
b
)
(x_0,y_0)=(x_0'*m/a,y_0'*n/b)
(x0?,y0?)=(x0′??m/a,y0′??n/b)。找到與
(
x
0
,
y
0
)
(x_0,y_0)
(x0?,y0?)最近的四個(gè)整數(shù)點(diǎn)位記作
(
x
1
,
y
1
)
,
(
x
1
,
y
2
)
,
(
x
2
,
y
1
)
,
(
x
2
,
y
2
)
(x_1,y_1),(x_1,y_2),(x_2,y_1),(x_2,y_2)
(x1?,y1?),(x1?,y2?),(x2?,y1?),(x2?,y2?),其對(duì)應(yīng)點(diǎn)位上的灰度值記為
P
11
,
P
12
,
P
21
,
P
22
P_{11},P_{12},P_{21},P_{22}
P11?,P12?,P21?,P22?。
則
(
x
0
′
,
y
0
′
)
(x_0',y_0')
(x0′?,y0′?)的灰度值為
y
2
?
y
0
y
2
?
y
1
(
x
2
?
x
0
x
2
?
x
1
P
11
+
x
0
?
x
1
x
2
?
x
1
P
21
)
+
y
0
?
y
1
y
2
?
y
1
(
x
2
?
x
0
x
2
?
x
1
P
12
+
x
0
?
x
1
x
2
?
x
1
P
22
)
\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?)
在實(shí)現(xiàn)時(shí),可能需要去掉邊框上的像素點(diǎn)值,以防止下標(biāo)越界等情況。若 ( x 0 , y 0 ) = ( x 0 ′ ? m / a , y 0 ′ ? n / b ) (x_0,y_0)=(x_0'*m/a,y_0'*n/b) (x0?,y0?)=(x0′??m/a,y0′??n/b)為整數(shù),則直接取該點(diǎn)灰度值賦給 ( x 0 ′ , y 0 ′ ) (x_0',y_0') (x0′?,y0′?)而無需進(jìn)行雙線性插值。
圖像縮小算法與放大類似,只要新圖像大小 a ? b a*b a?b小于原圖像大小 m ? n m*n m?n即可。
在對(duì)圖像進(jìn)行旋轉(zhuǎn)時(shí),為了對(duì)圖像中心進(jìn)行旋轉(zhuǎn),需要先把坐標(biāo)系平移到中心。記原中心點(diǎn)
(
x
′
,
y
′
)
=
(
0
,
0
)
(x',y')=(0,0)
(x′,y′)=(0,0),則變換后的中心點(diǎn)
(
x
,
y
)
(x,y)
(x,y)與原中心點(diǎn)關(guān)系為
(
x
y
1
)
=
(
x
′
y
′
1
)
(
1
0
0
0
?
1
0
?
0.5
w
0.5
h
1
)
\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?
?.則旋轉(zhuǎn)分為三個(gè)步驟:將
x
′
o
′
y
x'o'y
x′o′y變成
x
o
y
xoy
xoy,將該點(diǎn)順時(shí)針轉(zhuǎn)
α
\alpha
α度,最后將
x
o
y
xoy
xoy變回
x
′
o
′
y
′
x'o'y'
x′o′y′。則完整的變換為:
(
x
y
1
)
=
(
x
′
y
′
1
)
=
(
1
0
0
0
?
1
0
?
0.5
w
o
l
d
0.5
h
o
l
d
1
)
(
cos
?
α
?
sin
?
α
0
sin
?
α
cos
?
α
0
0
0
1
)
(
1
0
0
0
?
1
0
?
0.5
w
n
e
w
0.5
h
n
e
w
1
)
\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?
?
由于前后圖像大小不一定相等。所以需要進(jìn)行插值處理,可以使用上文中提到的兩種插值算法。新圖像寬為
w
′
=
∣
cos
?
α
∣
?
w
+
∣
sin
?
α
∣
?
h
w'=|\cos\alpha|*w+|\sin\alpha|*h
w′=∣cosα∣?w+∣sinα∣?h。新圖像的高為
h
′
=
∣
sin
?
α
∣
?
w
+
∣
cos
?
α
∣
?
h
h'=|\sin\alpha|*w+|\cos\alpha|*h
h′=∣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("實(shí)驗(yàn)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圖像,變換為灰度圖像和二值圖像,并在同一個(gè)窗口內(nèi)分別顯示RGB圖像和灰度圖像,注上文字標(biāo)題,并將結(jié)果以文件形式存到磁盤上。
I=imread("test.jpg");
[R,C,color]=size(I);
res=zeros(R,C,color);
for color=1:3
for i=1:R
for j=1:C
newx=i+60;
newy=j+60;
if ((newx<=R) && (newy<=C))
res(newx,newy,color)=I(i,j,color);
end
end
end
end
imshow(uint8(res))
完成了對(duì)圖像的平移操作,對(duì)圖像向右下平移60個(gè)像素。對(duì)于每個(gè)像素點(diǎn),先平移,再判斷下標(biāo)是否越界,最后將像素點(diǎn)填入。
I=imread("test.jpg");
[R,C,ch]=size(I);
res=zeros(R,C,ch);
for color=1:3
for i=1:R
for j=1:C-1
res(i,j,color)=I(i,C-j,color);
end
end
end
imshow(uint8(res))
完成了對(duì)圖像的垂直翻轉(zhuǎn)操作。沒有使用矩陣運(yùn)算。
I=imread("test.jpg");
[R,C,ch]=size(I);
res=zeros(R,C,ch);
for color=1:3
for i=1:R-1
for j=1:C
res(i,j,color)=I(R-i,j,color);
end
end
end
imshow(uint8(res))
完成了對(duì)圖像的水平翻轉(zhuǎn)操作。沒有使用矩陣運(yùn)算。
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:height
for j=1:width
for c=1:3
oldi=round(i/multh);
oldj=round(j/multw);
if (oldi>=1&&oldi<=h&&oldj>=1&&oldj<=w)
newimg(i,j,c)=I(oldi,oldj,c);
end
end
end
end
imshow(uint8(newimg))
完成了對(duì)圖像的放大/縮小操作。使用最近鄰插值法。先把新圖中的像素點(diǎn)除以放大倍數(shù)映射得到其在原圖中的位置,將該位置值四舍五入找到最近鄰,直接將最近鄰的值填入。
I=imread('test2.jpg');
[m,n,ch]=size(I);
width=100;
height=100;
newimg = uint8(zeros(width,height,3));
% 計(jì)算放大/縮小倍數(shù)
widthScale = m/width;
heightScale = n/height;
for ch=1:3
for x = 1:width - 1
for y = 1:height - 1
xx = x * widthScale;%新圖像位置對(duì)應(yīng)原圖像位置
yy = y * heightScale;%新圖像位置對(duì)應(yīng)原圖像位置
if (xx/double(uint16(xx)) == 1.0) && (yy/double(uint16(yy)) == 1.0)
newimg(x,y,ch) = I(int16(xx),int16(yy),ch);%若正好對(duì)應(yīng)到整數(shù)點(diǎn),則直接賦值,不插值
else
a = double(uint16(xx));%找整數(shù)點(diǎn)
b = double(uint16(yy));
if a==0||b==0||a>=m||b>=n%下標(biāo)不能越界
continue;
end
x11 = 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));
end
end
end
end
imshow(newimg);
完成了對(duì)圖像的放大/縮小操作。使用雙線性插值法。先把新圖中的像素點(diǎn)除以放大倍數(shù)映射得到其在原圖中的位置,如果是整數(shù)則直接填入,如果不是整數(shù)則找到與其相鄰的四個(gè)點(diǎn),按照上文中的公式進(jìn)行插值,將該值填入。
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)); %像素是整數(shù)
for x=1:w2
for y=1:h2
x0 = 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 %檢測(cè)下標(biāo)不能越界
img_rotate(y,x,:) = I(y0,x0,:);
end
end
end
imshow(img_rotate)
完成了對(duì)圖像的旋轉(zhuǎn)操作。對(duì)于圖像大小會(huì)發(fā)生變化的情況,使用最近鄰插值法處理縮放。同理,按四舍五入方式找到最近鄰。
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方向的負(fù)軸超出的偏移量
dx=abs(min([leftup(2) rightup(2) leftdown(2) rightdown(2)])); %取得x方向的負(fù)軸超出的偏移量
for i=1-dy:h2-dy
for j=1-dx:w2-dx
pix=[i j 1]/M; %用變換后圖像的點(diǎn)的坐標(biāo)去尋找原圖像點(diǎn)的坐標(biāo),
yy=pix(1)-floor(pix(1));
xx=pix(2)-floor(pix(2));
if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w
x11=floor(pix(1)); %四個(gè)相鄰的點(diǎn)
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); %計(jì)算臨近四個(gè)點(diǎn)在雙線性插值中的權(quán)重
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,:);
end
end
end
imshow(uint8(img_rotate))
完成了對(duì)圖像的旋轉(zhuǎn)操作。對(duì)于圖像大小會(huì)發(fā)生變化的情況,使用雙線性插值法處理縮放。同理,先找到新圖中某點(diǎn)坐標(biāo)對(duì)應(yīng)原圖位置(利用矩陣除法),找到其相鄰的四個(gè)點(diǎn)位,按照上文中的公式進(jìn)行插值。
實(shí)驗(yàn)結(jié)果
對(duì)于題目1,完成了對(duì)圖片的讀取、灰度化、二值化操作。還生成了可以被matlab打開的.fig文件。
對(duì)于平移,正確地實(shí)現(xiàn)了圖像的平移,并且對(duì)其余部分補(bǔ)上黑色邊框。
對(duì)于左右鏡像翻轉(zhuǎn),正確地實(shí)現(xiàn)了圖像的左右鏡像翻轉(zhuǎn)。
對(duì)于上下鏡像翻轉(zhuǎn),正確地實(shí)現(xiàn)了圖像的上下鏡像翻轉(zhuǎn)。
成功將圖像放大,利用最近鄰插值。可以看到,放大的結(jié)果存在一定的鋸齒與馬賽克的現(xiàn)象。
成功將圖像縮小,利用最近鄰插值。
成功將圖像放大,利用雙線性插值??梢钥吹?,放大的結(jié)果比起最近鄰插值更為平滑,沒有存在嚴(yán)重的鋸齒現(xiàn)象。
成功將圖像縮小,利用雙線性插值??梢钥吹?,利用雙線性插值進(jìn)行縮小時(shí)也沒有出現(xiàn)失真現(xiàn)象。
利用最近鄰插值法與雙線性插值法分別對(duì)圖像進(jìn)行旋轉(zhuǎn)45°操作,并對(duì)其余區(qū)域填充為黑色。文章來源:http://www.zghlxwxcb.cn/news/detail-456072.html
分析:兩種插值法優(yōu)缺點(diǎn)
最近鄰插值法優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行速度快。缺點(diǎn):在放大圖像時(shí)可能出現(xiàn)鋸齒現(xiàn)象,圖像中一些曲線的邊緣不平滑。在放大后縮小回去還會(huì)出現(xiàn)一定的失真現(xiàn)象,使圖像看起來變得模糊了,像馬賽克。
雙線性插值法優(yōu)點(diǎn):一定程度上緩解了最近鄰插值法缺點(diǎn)出現(xiàn)的情況。放大圖像后圖像中的一些曲線看起來更平滑,對(duì)一張圖像反復(fù)放大縮小后失真現(xiàn)象不嚴(yán)重,處理效果較好。缺點(diǎn):處理速度慢,在matlab2020B實(shí)驗(yàn)環(huán)境中往往需要對(duì)一張圖像處理約3秒左右。對(duì)于圖像的最外圈邊緣也難以處理。文章來源地址http://www.zghlxwxcb.cn/news/detail-456072.html
四、實(shí)驗(yàn)心得
到了這里,關(guān)于MATLAB【數(shù)字圖像處理】 實(shí)驗(yàn)一:圖像處理基本操作(平移、放大、縮小、旋轉(zhuǎn)、插值)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!