matlab——识别图像中的圆形目标
文章目錄
- 說明
- Figure 1
- imread函數
- imshow函數
- Figure 2
- rgb2gray函數
- graythresh函數
- im2bw函數
- figure函數
- Figure 3
- bwareaopen函數
- Figure 4
- strel函數
- imclose函數
- imfill函數
- Figure 5
- bwboundaries函數
- label2rgb函數
- 檢測算法
- regionprops函數
- diff函數
- sprintf函數
- text函數
- 最后我們來換個圖試試
- 第一幅圖
- 第二幅圖
- 第三幅圖
說明
資料來自《詳解MATLAB圖像函數及其應用》
作者:張倩,占君,陳珊
出版社:電子工業出版社
出版時間:2011-04
這是我對MTALAB圖像處理整理出來的學習筆記,望與君共勉
采用部分只有代碼,其他的我自己收集來的資料,萌新一枚,侵權即刪
內容來自書的第十九章1457頁的圖像特征提取實戰2
——————————————————————
本次會出現5個圖像窗口,所以我會根據每一次出現的圖像窗口來進行分段解釋
Figure 1
首先讀取圖像
RGB=imread('1234.png'); imshow(RGB);imread函數
- A=imread(filename)
從指定的圖像中讀取灰度圖像或真彩色圖像
filename是表示文件名全名的字符串(包括擴展名)
也就是***.jpg啊,***.png啊這些圖像文件名字
imshow函數
- imshow(I)
顯示真彩色圖像RGB,
RGB為三維數組,第三維的維數為3
其他用語說明
這一個三維數組在本次案例中是指imread函數操作來的三維數組,如RGB,顯示如下
再打開
這個圖是
Figure 2
然后對圖像進行閾值分割
將圖像轉換為灰度圖像,設置閾值,對圖像進行閾值分割,生成二值圖像
rgb2gray函數
- I=rgb2gray(RGB)
將真彩色RGB圖像或索引圖像轉換為灰度圖像
參量RGB是一個維數為MxNx3的數組,表示RGB圖像,上方已經展示出來
graythresh函數
- level=graythresh(I)
計算全局圖像閾值
level為標準化灰度值,范圍是[0 1]
其他用語解釋
即臨界值,是為轉化二值圖像做準備來的
而這一次把上圖進行計算全局閾值后得到的level值為
而這個計算全局圖像閾值的方式是大津法——Otsu方法,又稱最大類間方差法
Otsu算法
- 對于圖像I(x,y)
前景(即目標)和背景的分割閾值記作T
前景像素點數占整幅圖像的比例記為ω0,其平均灰度μ0;
背景像素點數占整幅圖像的比例記為ω1,其平均灰度為μ1。
圖像的總平均灰度記為μ,類間方差記為g。 - 假設圖像的背景較暗,并且圖像的大小為M×N
圖像中像素的灰度值小于閾值T的像素個數記作N0
像素灰度大于閾值T的像素個數記作N1
則有:
ω0=N0/ M×N (1)
ω1=N1/ M×N (2)
N0+N1=M×N (3)
ω0+ω1=1 (4)
μ=ω0μ0+ω1μ1 (5)
g=ω0(μ0-μ)2+ω1(μ1-μ)2 (6)
將式(5)代入式(6),得到等價公式:
g=ω0ω1(μ0-μ1)^2 (7)
這就是類間方差
采用遍歷的方法得到使類間方差g最大的閾值T,即為所求。
內容學習來源
作為一個熱愛學習的人,我當然得去看看這個函數在干些啥
于是我去畫了個圖
于是
那如果我用三色呢
于是
我們再次引用這里的的概念來解釋平均灰度
im2bw函數
- BW=im2bw(I,level)
閾值法轉換圖像為二值圖像
將灰度圖像I轉換成二值圖像BW
level為閾值,即標準化灰度值,范圍為[0 1]
I中大于level的像素設為1(白色),小于的像素為0(黑色)
結果當然會得到二值圖像
繼續打開
figure函數
- figure
創建新的圖形對象,在屏幕上單獨顯示的窗口,且窗口中可以輸出圖形
可以看到想要提高效率(偷懶),可以只打一個figure代碼,就可以按順序新建一個圖像窗口,如下圖(本次代碼產生的)
本次產生的圖是
Figure 3
然后去除圖像中的噪聲,開運算去除小于30個像素的目標
bw=bwareaopen(bw,30); figure; imshow(bw);bwareaopen函數
- BW2=bwareaopen(BW,P)
- 移除二值圖像BW中所有少于P個像素的連通元素,生成另一個二值圖像BW2
- 對二值圖像進行形態學開運算,用于移除小目標
- 對于二維圖像默認采用8連通鄰域
三維采用26連通鄰域
本次bwareaopen會對bw進行操作,故之前我展示出來的bw的邏輯矩陣已經是經過變化了的矩陣,有一些地方的1可能變成了0,但是我們只是為了看看這個圖片在電腦里是怎么解釋的(我就是沒看過,我就是想看)
第一次的實戰案例里我們了解到,開運算就是可以去除孤立的小點、毛刺這些東西,P就是結構元素,用于作為濾波的標準,BW就是濾波對象,接下來我們看看濾波的結果如何
然后我們再來看看兩副圖像的區別
開運算后的圖片:
之前的圖片:
很明顯,一些很小的點被填補上了,這里被移除的是白點,故可以說是去掉了黑點周圍的毛刺,使邏輯矩陣里的1(白)變成了0(黑),在圖片的其他地方也是有變化的,我們就說一處
Figure 4
填充圖像縫隙(洞孔)
se=strel('disk',2); bw=imclose(bw,se); bw=imfill(bw,'holes'); figure; imshow(bw);strel函數
- SE=strel(shape,parameters)
創建形態學結構元素對象
shape可是square方形,line線形,disk圓盤形,ball球形和rectangle長方形等
parameters是對shape的大小描述
結果得到的se是什么呢,我們來看看
我們繼續打開
可以看到還有兩個按鈕可以繼續點開
再開!
另外一個也不會放過的
查閱資料知道,se為strel函數創造的形態學結構元素對象——strel對象,代表一個扁平的形態結構元素,那么這個strel函數就牽涉到strel的對象功能,如下表
| imdilate | 膨脹圖像 |
| imerode | 腐蝕圖像 |
| imclose | 形態接近圖像 |
| imopen | 形態上開放的圖像 |
| imbothat | 底帽過濾 |
| imtophat | 高帽過濾 |
| bwhitmiss | 二進制未命中操作 |
| decompose | 分解后的結構元素的返回順序 |
| reflrct | 反映結構元素 |
| translate | 翻譯結構元素 |
| imfill(BW,‘holes’) | 空洞填充 |
圖表內容來源
另外我們還看到,繼續打開的兩個圖中,一個是0,1矩陣,1組合起來的形狀我們就當做圓盤狀吧,然后另一個圖里只有一個數字2,這個2就來自代碼中后邊我們輸入的2。實際上如果把disk變成square,就會使整個矩陣變成1,變成line,就還需要一個角度,若角度設定為45度,則會讓1從左下角連續到右上角去,也就是一條線的形狀(矩陣畫圖太難了)
接下來我們看本次用到的strel的對象
imclose函數
- IM2=imclose(IM,SE)
對圖像進行形態學閉運算
對灰度圖像或二值圖像IM進行形態學閉運算,返回閉運算結果圖像IM2
SE為由strel函數生成的結構元素對象
imfill函數
- BW2=imfill(BW,‘holes’)
顯示二值圖像BW,對二值圖像BW中的目標點孔進行填充點
來看看這一次的圖像的變化
我們可以看到一些很明顯的變化,人物耳朵的輪廓沒了,用這幅圖感覺看不出是怎么填的洞
那我們把imfiil函數劃掉看看
可以看到耳朵的輪廓還在
那我們來看看那個imclose閉運算的結果
閉運算之后:
閉運算之前:
可以看到經過閉運算,黑色(0)的線條作為白色(1)的裂縫,被彌補了,也就是補1了
所以我們可以知道,這個過程中,開運算使1變0,閉運算使0變1,正好是兩個基本算子,多少理解了一點吧
Figure 5
接下來提取圖像中的各種目標的幾何特征,利用幾何特征及圓形檢測算法判斷每個目標是否是圓形目標。當目標的面積和周長滿足公式ε=4piS/L^2,ε接近于1時,則認為該目標為圓形目標
[B,L]=bwboundaries(bw,'noholes'); figure; imshow(label2rgb(L,@jet,[.5 .5 .5]));%5bwboundaries函數
- B=bwboundaries(BW)
搜索二值圖像BW的外邊界和內邊界
BW為矩陣,其元素為0或1(即二值圖像)
該函數將0視為背景像素點,1視為待提取邊界的目標
B為Px1細胞矩陣,P為目標和洞的個數
B中的每個細胞元素均為Qx2矩陣,Q為邊界所含像素點的個數
故該矩陣中每一行包含邊界像素點的行坐標和列坐標
我們來看看B里有什么
一個元胞數組,然后打開
套娃游戲,然后我們繼續打開可以看到的是,這就是邊界像素點的坐標
- 而本次代碼中使用的方式是
[B,L]=bwboundaries(BW,conn,options)
返回標識矩陣L,用于標識二值圖像中被邊界所劃分的區域,包括目標和洞
conn指定搜索算法中所使用的連通方法,可選4連通和8連通,其中8為默認值
字符串參量options指定算法的搜索方式,可選holes和noholes
默認使用holes,算法搜索目標的內邊界和外邊界,noholes只搜索目標的外邊界
那么我們打開L
我好氣啊全是0,純屬來占內存的?
然后我發現它列有點多…
這就是標識矩陣,用于下邊循環繪制每個邊界
label2rgb函數
- RGB=label2rgb(L,map,zerocolor)
定義輸入標注矩陣L中標注為0的元素的RGB顏色
zerocolor為字符串或三元向量
本題內為三元向量,分表代表R、G、B的顏色,默認為[1 1 1],即白色 - 聯合imshow函數使用
即imshow(RGB),顯示真彩色圖像RGB,RGB為三維數組,第三維的維數為3
這里的@jet是colormap,解釋是說默認大值為紅,小為藍,還可以用colormap(flipud(jet))進行顛倒,但是…
那問題出在哪呢,我認為是后邊的zerocolor的問題,于是我去修改參數
改成.1 .5 .9之后的樣子,其他顏色有待挖掘呀,然后接下來是圖中耳朵位置的metric值,本圖只有一個地方可以計算,我們待會換個圖
檢測算法
hold on; for k=1:length(B)boundary=B{k};plot(boundary(:,2),boundary(:,1),'w','LineWidth',2); end stats=regionprops(L,'Area','Centroid'); threshold=0.94; for k=1:length(B)boundary=B{k};delta_sq=diff(boundary).^2;perimeter=sum(sqrt(sum(delta_sq,2)));area=stats(k).Area;metric=4*pi*area/perimeter^2;metric_string=sprintf('%2.2f',metric);if metric>thresholdcentroid=stats(k).Centroid;plot(centroid(1),centroid(2),'ko');endtext(boundary(1,2)-35,boundary(1,1)+13,metric_string,'Color','y','FontSize',14,'FontWeight','bold'); end title(['Metrics closer to 1 indicate that','the object is approximately round']);先給出流程圖
具體的區別我用第三幅圖來觀察了,有需要可以從目錄跳到最后的那個第三幅圖去觀察
regionprops函數
- STATS=regionprops(L,properties)
測量每個標簽區域L的屬性
L為標識矩陣,L中的正整數元素對應不同的區域
properties可以是逗號分隔的字符串、包含字符串的細胞矩陣、字符串all或字符串basic
此處計算測量值Area(區域像素點個數)、Centroid(區域的質心)
代碼說明:
獲取標識區域的面積和質心屬性
我們打開stats來看
再打開
area即面積,centroid即質心
threshold=0.94是在手動設置圓的閾值,可以觀察下方對比metric和threshold
然后是用循環檢測每一個標識目標
利用邊界坐標計算目標周長
area=states(k).Area即獲取目標面積屬性
打開area
然后計算metric值,保存計算結果,將檢測出的圓形目標用黑圈標識出其質心,判斷其是否為圓
diff函數
- Y=diff(X)
計算沿大小不等于1的第一個數組維度的X相鄰元素之間的差分
這個函數在這次算法里比較玄學吧,算著算著周長就出來了,我也是看了半天,我們先來看看diff函數是在干些啥
它的用途有這些
那結果呢
我們可以看到,
對于一維向量,diff函數會用右減左,即相鄰數的增量
對于二維的矩陣
- 對于diff(A,1,1),就相當于diff(A),并且是用矩陣的下行作被減數,上行作減數
- 對于diff(A,2,1),就相當于diff(diff(A)),并且是用矩陣的下行作被減數,上行作減數
- 對于diff(A,1,2),就相當于diff(A),并且是用矩陣的右列-左列
- 對于diff(A,2,2),就相當于diff(diff(A),并且是用矩陣的右列-左列
所以本次算法中就是把boundary作為邊緣坐標,然后下減上,得到的幾乎都是(0,1)(1,0)(-1,0)和(0,-1),因為是連續的離散點,然后平方變為正,再求和,第一個sum計算得到數行一列的1,sqrt之后還是1,行數甚至不變,然后最后一個sum得到周長
sprintf函數
- str=sprintf(formatSpec,A1,…,An)
使用formatSpec指定的格式化操作符格式化數組A1,…,An中的數據,并在str中返回結果文本
text函數
- text(___,Name,Value)
最后我們來換個圖試試
第一幅圖
我去用ps畫了圖,如下
于是我們開始吧
按順序來
第二幅圖
被暗算了一波,我們換個顏色再來
第三幅圖
只到最后一個imshow操作,連邊都沒有描
描完邊之后就沒了,明明figure里是有描邊的,我也不知道為什么保存后就沒了白邊
分別把threshold修改為0.5和0.1
可以看到計算metric大于threshold的就會在質心出現黑圓圈
那我們再繼續,這次把string_metric去掉
可以看到每個標記都相同了
我們來看最終結果
總結
以上是生活随笔為你收集整理的matlab——识别图像中的圆形目标的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows下的csrss.exe进程
- 下一篇: 赛程安排 单循环赛 matlab程序