實現一個函數 s = scanLine4e(f, I, loc), 其中 f是一個灰度影象,I 是一個整數,loc 是一個字 符串。當 loc 為’row’時,I 代表行數。當 loc 為’column’時,I 代表列數。輸出 s 是對應的相 關行或者列的畫素灰度向量。
呼叫該函數,提取 cameraman.tif 和 einstein.tif 的中心行和中心列的畫素灰度向量並將掃描 得到的灰度序列繪製成圖。
1. 程式
①scanLine4e(f, I, loc)函數
function [s] = scanLine4e(f, I, loc)
[row,column]=size(f);
if loc=='row'
% I 代表行數
s=f(I,:);
elseif loc=='column'
% I 代表列數
s=f(:,I);
end
end
②主程式
img=imread("資原始檔\cameraman.tif");
[centerRow,centerColum]=size(img);
centerRow=round(centerRow/2);
centerColum=round(centerColum/2);
cameramanRow=scanLIne4e(img,centerRow,"row")
cameramanColum=scanLIne4e(img,centerColum,"column")
% 畫圖
x = linspace(0,256, 256); % 橫座標軸
y1 = cameramanRow;
y2 = cameramanColum;
% 繪圖
figure
plotyy(x, y1, x,y2)
scanLIne4e(img,centerRow,"row")
2.執行效果
①cameraman.tif圖片
圖1 cameraman.tif圖片行列掃描
②einstein.tif圖片
圖2 cameraman.tif圖片行列掃描
影象處理中的一個常見問題是將彩色RGB影象轉換成單色灰度影象,第一種常用的方法是 取三個元素R,G,B 的均值。第二種常用的方式,又稱為 NTSC 標準,考慮了人類的彩色感知體驗,對於 R,G,B 三通道分別採用了不同的加權係數,分別是 R 通道 0.2989,G通道0.5870,B通道0.1140.
實現一個函數g = rgb1gray(f, method).函數功能是將一幅24位元的RGB影象,f,轉換成灰度影象,g.引數 method 是一個字串,當其值為’average’ 時,採用 第一種轉換方法,當其值為’NTSC’時,採用第二種轉換方法。將’NTSC’做為預設方式。
呼叫該函數,將提供的影象mandril_color.tif和 lena512color.tiff 用上述兩種方法轉換成單色 灰度影象,對於兩種方法的結果進行簡短比較和討論。
1. 程式碼
①rgb1gray函數
function [outputArg] = rgb1gray(f, method)
%函數g = rgb1gray(f, method).函數功能是將一幅24位元的RGB影象,f,轉換成灰度影象,g.
%引數 method 是一個字串,當其值為’average’ 時,採用 第一種轉換方法,
%當其值為’NTSC’時,採用第二種轉換方法。將’NTSC’做為預設方式。
%獲取3通道
red=f(:,:,1);
green=f(:,:,2);
blue=f(:,:,3);
gray=f;
if method=='average'
%採用 第一種轉換方法:取三個元素R,G,B 的均值
gray=(red+green+blue)/3;
elseif method=='NTSC'
gray=0.2989*red+0.5870*green+0.1140*blue
else
outputArg = "輸入引數method錯誤";
end
outputArg = gray;
end
②主呼叫函數
img=imread("資原始檔\mandril_color.tif");
gray=rgb1gray(img,"average");
imshow(gray)
2.輸出結果
①mandril_color.tif
圖3(左) mandril_color.tif取3通道平均值作為灰度(右)加權NTSC模式
②lena512color.tiff
圖4(左)lena512color圖片取3通道平均值作為灰度(右)加權NTSC模式
3.結論
簡單的將3通道的畫素值進行平均後得到的灰度圖會損失大量細節,圖片變得幾乎不可見,僅僅保留了少部分密集的深色區域。而用NTSC加權模式後得到的灰度圖由於G通道佔有最大的權重0.5870,綠色通道能保留較多的細節,因此灰度圖在細節保留上幾乎不受影響。
實現一個函數 g = twodConv(f, w), 其中 f是一個灰度源影象,w是一個矩形折積核。要求輸出影象g與源影象f大小(也就是畫素的行數和列數)一致。請注意,為滿足這一要求,對於源影象f需要進行邊界畫素填補(padding)。這裡請實現兩種方案。第一種方案是畫素複製,對應的選項定義為‘replicate’,填補的畫素拷貝與其最近的影象邊界畫素灰度。第二種方案是補零,對應的選項定義為‘zero’,填補的畫素灰度為0,將第二種方案設定為預設選擇。
1.程式碼
①twodConv函數程式碼
function [outputArg] = twodConv(f, w,method)
[size_w,t]=size(w)
num=round(size_w/2) -1% 根據折積核的大小決定要填充多少排
addrow=num*2 %addrow是要新增的圈數,如核大小為3時,新增兩圈。核大小為5時,新增4圈
width=size(f, 1)
height=size(f, 2)
if method=='replicate'
% 增加兩圈
top=f(1:width,1); %提取影象的上下左右畫素
bottom=f(1:width,height);
left=f(1,1:height);
right=f(width,1:height)
% addrow=2
temp = zeros(addrow*2 +width, addrow*2 + height);
for i=1:addrow
temp(addrow+1:width+addrow,i)=top; %賦值
temp(addrow+1:width+addrow,height+addrow+i)=bottom;
temp(i,addrow+1:height+addrow)=left;
temp(width+addrow+i,addrow+1:height+addrow)=right;
end
temp(addrow+1:width+addrow,addrow+1:height+addrow)=f(1:width,1:height) %中間部分保留為原圖
% 影象4個角的賦值
temp(1:addrow,1:addrow)=f(1,1)
temp(width+addrow:width+addrow*2,1:addrow)=f(width,1)
temp(width+addrow:width+addrow*2,height+addrow:height+addrow*2)=f(width,height)
temp(1:addrow,height+addrow:height+addrow*2)=f(1,height)%temp是複製完畫素後得到的圖片,核為3*3時,會複製兩圈
P = zeros(addrow*2 +width,addrow + height);
for i = size_w:(addrow + width) %迴圈進行折積操作
for j = size_w:(addrow + height)
for m = 1:size_w
for n = 1:size_w
P(i, j) = P(i, j) + temp(i + m-2, j + n-2)*w(m, n);
end
end
end
end
P = P(size_w:width + addrow, size_w:height);
elseif method=='zero'
%畫素填補0
temp = zeros(addrow, addrow*2 +height ); %建立一張temp影象
temp(size_w:(width +addrow), 1:addrow) = 0;
temp(size_w:(width + addrow),size_w:(height +addrow)) = f;
temp(size_w:(width+ addrow),width + size_w:width+ addrow*2) = 0;
temp(width + size_w:width+ addrow*2, 1:width + addrow*2) = 0;
P = zeros(addrow*2 +width,addrow + height);
for i = size_w:(addrow + width)
for j = size_w:(addrow + height)
for m = 1:size_w
for n = 1:size_w
P(i, j) = P(i, j) + temp(i + m-2, j + n-2)*w(m, n);
end
end
end
end
P = P(size_w:width + addrow, size_w:height);
end
outputArg = P;
end
②主程式程式碼
img=imread("資原始檔\cameraman.tif");
w=[0 0 1 0 0;
0 0 1 0 0;
1 1 -4 1 1;
0 0 1 0 0;
0 0 1 0 0];
% w=[0 1 0;
% 1 -4 1;
% 0 1 0];
convimg=twodConv(img, w,"zero");
% convimg2=convn(img,w);
% convimg2=conv2(img,w);
convimg=uint8(convimg)
imshow(convimg)
2.實驗效果
①複製影象邊緣畫素的折積
圖5 (左)折積核大小為3時 (右)折積核大小為5時
②填充0
大小為3*3折積核折積效果與matlab自帶的conv2函數對比。
圖6 (左)折積核大小為3時填充0的折積(右)使用conv2
大小為5維折積核折積效果與matlab自帶的conv2函數對比。
圖7 (左)折積核大小為5時填充0的折積(右)使用conv2
實現一個高斯濾波核函數 w = gaussKernel(sig,m),其中 sig 對應於高斯函數定義中的σ,w 的大小為 m×m。請注意,這裡如果m沒有提供,需要進行計算確定。如果m已提供但過小, 應給出警告資訊提示。w要求歸一化,即全部元素加起來和為1
二維高斯濾波核函數如下,其中σx 與σy 相等。
1.程式碼
function [outputArg] = gaussKernel(sig,m)
%高斯濾波核函數 w = gaussKernel(sig,m),
%其中 sig 對應於高斯函數定義中的σ,w 的大小為 m×m。
%請注意,這裡如果m沒有提供,需要進行計算確定。
%如果m已提供但過小, 應給出警告資訊提示。
%w要求歸一化,即全部元素加起來和為1
if isempty(m)
%m為空,計算其大小
m=1+2*ceil(3*sig); %若m為空,則定義濾波視窗的大小
elseif m<2
outputArg='m(視窗大小)過小,請重新輸入引數!'
else
%sig定義高斯函數的標準差
nCenter =floor(m/2); %定義濾波視窗中心的索引
% w 大小為m*m
w=zeros(m,m)
for i=-1*nCenter:nCenter
for j=-1*nCenter:nCenter
w(i+1+nCenter,j+1+nCenter)=exp(-1*((i)^2+(j)^2)/(2*sig^2))/(2*pi*sig^2);
end
end
%歸一化
dSum=sum(sum(w));
w=w/dSum;
outputArg = w;
end
end
2. 實驗結果
當σ=1時,視窗大小為3*3時,得到的高斯核如下:
呼叫上面實現的函數,對於問題 1 和 2 中的灰度影象(cameraman, einstein, 以及 lena512color 和mandril_color 對應的NTSC 轉換後的灰度影象)進行高斯濾波,採用σ=1,2,3,5。任選一種畫素填補方案。
對於σ=1 下的結果,與直接呼叫相關函數的結果進行比較(可以簡單計算差值影象)。然後, 任選兩幅影象,比較其他引數條件不變的情況下畫素複製和補零下濾波結果在邊界上的差別。
1. 程式碼
% 第5題
%問題1和2中的灰度影象
img1=imread("資原始檔\cameraman.tif");%einstein.tif
%對應NTSC轉化後的灰度影象
img2=imread("資原始檔\mandril_color.tif");%lena512color.tiff
gray=rgb1gray(img2,"NTSC");
sigma=1 %2,3,5
w=gaussKernel(sigma,3);
%折積
result=twodConv(img1, w,"replicate");%複製畫素填充
result=uint8(result)
imshow(result)
2.實驗效果
①σ=1,2,3,5時cameraman.tif圖片濾波效果如圖9所示。
圖8 cameraman.tif視窗大小為3,σ分別取1,2,3,5時濾波效果
圖9 (左)σ取2,視窗大小為5,(右)σ取2,視窗大小為7時濾波效果
視窗大小為3,σ=1,2,3,5時,einstein.tif濾波效果如圖10所示。
圖10 視窗大小為3,σ分別取1,2,3,5時濾波效果
視窗大小為5,σ=1,2,3,5時,經過NTSC灰度處理後的mandril_color.tif圖片濾波效果如圖11所示。
圖11 視窗大小為5,σ=1,2,3,5時mandril_color.tif灰度圖濾波
視窗大小為7,σ=1,2,3,5時,經過NTSC灰度處理後的lena512color.tiff圖片濾波效果如圖12所示。
圖12 視窗大小為5,σ=1,2,3,5時lena512color.tiff灰度圖濾波
在視窗大小為7,σ=1的情況下直接呼叫高斯濾波相關函數,程式碼如下:
%直接呼叫相關函數
img2=imread("資原始檔\lena512color.tiff");%lena512color.tiff
img2=rgb1gray(img2,"NTSC");
ksize=[7,7]
sigma=1
filter=fspecial('gaussian',ksize, sigma); % 構建高斯函數
result2=imfilter(img2, filter, 'replicate');
result2
subimg=result2-result1
subimg=uint8(subimg)
imshow(subimg)
兩圖對比以及做差得到的影象如圖13所示。
(a)手動編寫的高斯濾波器效果(b)呼叫自帶函數得到效果
(c)兩圖做差得到結果
圖13 視窗大小為7,σ=1實現的函數與matlab自帶函數對比
使用影象cameraman.tif,其他引數條件不變的情況下畫素複製和補零下濾波結果在邊界上的差別如圖14所示,可以看到在填充0的情況下濾波得到的圖片會有一圈黑色邊框。
圖14 (左)複製畫素(右)填充0
cameraman影象畫素複製和補零下濾波差別
在更換一張青椒影象後發現並沒有出現cameraman影象的黑邊情況,肉眼很難觀察出差別,如圖15所示。
圖15(左)複製畫素(右)填充0
但是兩圖的邊緣畫素整體來看,用複製(replicate)方式得到的影象,邊緣灰度值更大,填0方式得到的灰度值更小,如圖16所示。
圖16 (上)複製方式(下)填0方式 青椒影象邊緣畫素對比