此示例說明如何自動檢測圖像中的圓形目標并可視化檢測到的圓。
步驟 1:加載圖像
讀取并顯示包含各種顏色的圓形塑料片的圖像。除了有大量要檢測的圓之外,從圓檢測的角度來看,此圖像還有一些有趣的特點:
有不同顏色的塑料片,它們相對于背景有不同對比度。一方面,藍色和紅色塑料片在此背景上形成強烈的對比。另一方面,一些黃色塑料片與背景的對比不明顯。
請注意一些塑料片重疊在一起,而另一些塑料片則靠得很近,幾乎互相接觸。對于目標檢測來說,場景中存在重疊的對象邊緣和對象遮擋通常具有挑戰性。
rgb
= imread
('coloredChips.png'); %加載圖像
imshow
(rgb
);
title
('coloredChips');
步驟 2:確定搜索圓的半徑范圍
使用 drawline 函數找到合適的圓半徑范圍。在塑料片的近似直徑上繪制一條線。
rgb
= imread
('coloredChips.png'); %加載圖像
imshow
(rgb
);
title
('coloredChips');
d
= drawline
; %使用 drawline 函數找到合適的圓半徑范圍
pos
= d.Position
;
diffPos
= diff
(pos
);
diameter
= hypot
(diffPos
(1),diffPos
(2));
步驟 3:尋找圓的初步嘗試
imfindcircles 函數搜索符合半徑范圍的圓。搜索半徑在 20 到 25 個像素范圍內的圓。在此之前,最好要清楚對象是比背景亮還是比背景暗。要回答該問題,請看此圖像的灰度版本。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(1,2,1
);
imshow
(rgb
);
title
('coloredChips');
%d
= drawline
; %使用 drawline 函數找到合適的圓半徑范圍
% pos
= d.Position
;
% diffPos
= diff
(pos
);
% diameter
= hypot
(diffPos
(1),diffPos
(2));
gray_image
= rgb2gray
(rgb
); %轉為灰度圖像
subplot
(1,2,2
);
imshow
(gray_image
); %顯示灰度圖像
title
('coloredChips灰度圖');
背景相當亮,大多數塑料片比背景暗。但是,默認情況下,imfindcircles 會找到比背景亮的圓形目標。因此,在 imfindcircles 中將參數 ‘ObjectPolarity’ 設置為 ‘dark’ 以搜索較暗的圓。
>> [centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark') %在 imfindcircles 中將參數
'ObjectPolarity' 設置為
'dark' 以搜索較暗的圓centers
=[]radii
=[]
請注意,輸出 centers 和 radii 為空,這意味著未找到圓。這種情況經常發生,因為 imfindcircles 是圓形檢測器,與大多數檢測器類似,imfindcircles 有內部檢測閾值決定其敏感度。簡而言之,這意味著檢測器對某個(圓形)檢測的信心必須大于某個水平,才將其視為有效檢測。imfindcircles 有參數 ‘Sensitivity’,可用于控制此內部閾值,從而控制算法的敏感度。較高的 ‘Sensitivity’ 值會將檢測閾值設置得較低,并導致檢測到更多圓。這類似于家庭安全系統中使用的運動檢測器的敏感度控制。
步驟 4:提高檢測敏感度
回到塑料片圖像,在默認敏感度水平下,可能所有圓都低于內部閾值,因此未檢測到圓。‘Sensitivity’ 是介于 0 和 1 之間的數字,默認設置為 0.85。將 ‘Sensitivity’ 提高到 0.9。
>> [centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.9
) %將
'Sensitivity' 設置為
0.9centers
=146.1895 198.5824328.8132 135.5883130.3134 43.8039175.2698 297.0583312.2831 192.3709327.1316 297.0077243.9893 166.4538271.5873 280.8920radii
=23.160422.571022.957623.735622.955122.999522.905523.0298
這次,imfindcircles 發現了一些圓 - 準確地說是八個。centers 包含圓心的位置,radii 包含這些圓的估計半徑。
步驟 5:在圖像上繪制圓
函數 viscircles 可用于在圖像上繪制圓。來自 imfindcircles 的輸出變量 centers 和 radii 可以直接傳遞給 viscircles。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(2,2,1
);
imshow
(rgb
);
title
('coloredChips');[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.9
);
subplot
(2,2,2
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %在圖像上繪制靈敏度為0.9時找到的圓
title
('靈敏度為0.9時找到的圓');
a1
= length
(centers
) %計算找到繪制靈敏度為0.9時的圓的個數
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.92
);
subplot
(2,2,3
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %在圖像上繪制靈敏度為0.92時找到的圓
title
('靈敏度為0.92時找到的圓');
a2
= length
(centers
) %計算找到繪制靈敏度為0.92時的圓的個數
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.95
);
subplot
(2,2,4
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %在圖像上繪制靈敏度為0.95時找到的圓
title
('靈敏度為0.95時找到的圓');
a3
= length
(centers
) %計算找到繪制靈敏度為0.95時的圓的個數%計算結果
a1
=8a2
=16a3
=22
步驟 6:使用第二種方法(兩階段)尋找圓
此方法的結果看起來更好。imfindcircles 有兩種不同尋找圓的方法。到當前為止,默認方法(稱為相位編碼方法)用于檢測圓。在 imfindcircles 中還可以使用另一種方法,通常稱為兩階段方法。使用兩階段方法并顯示結果。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(2,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.9
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用相位編碼方法在圖像上繪制靈敏度為0.9時找到的圓
title
('相位編碼方法:靈敏度為0.9時找到的圓');
a1
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.9時的圓的個數subplot
(2,2,2
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.9,
'Method',
'twostage');
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用兩階段方法在圖像上繪制靈敏度為0.9時找到的圓
title
('兩階段方法:靈敏度為0.9時找到的圓');
a2
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.9時的圓的個數subplot
(2,2,3
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.92
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用相位編碼方法在圖像上繪制靈敏度為0.92時找到的圓
title
('相位編碼方法:靈敏度為0.92時找到的圓');
a3
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.92時的圓的個數subplot
(2,2,4
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.92,
'Method',
'twostage');
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用兩階段方法在圖像上繪制靈敏度為0.92時找到的圓
title
('兩階段方法:靈敏度為0.92時找到的圓');
a4
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.92時的圓的個數
!%統計結果
a1
=8 %相位編碼方法找到繪制靈敏度為0.9時的圓的個數為8個a2
=22 %兩階段方法找到繪制靈敏度為0.9時的圓的個數為22個a3
=16 %相位編碼方法找到繪制靈敏度為0.92時的圓的個數為16個a4
=22 %兩階段方法找到繪制靈敏度為0.92時的圓的個數為22個
兩階段方法使用敏感度0.9和 0.92 檢測更多圓。一般來說,這兩種方法是互補的,因為它們有不同優點。相位編碼方法通常比兩階段方法更快,抗噪聲的穩定性稍強。但是,它也可能需要更高的 ‘Sensitivity’ 水平才能實現與兩階段方法相同數量的檢測。例如,如果 ‘Sensitivity’ 水平提高到 0.95,相位編碼方法也會找到相同的塑料片。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(1,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.95
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用相位編碼方法在圖像上繪制靈敏度為0.95時找到的圓
title
('相位編碼方法:靈敏度為0.95時找到的圓');
a1
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.95時的圓的個數subplot
(1,2,2
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.95,
'Method',
'twostage');
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用兩階段方法在圖像上繪制靈敏度為0.95時找到的圓
title
('兩階段方法:靈敏度為0.95時找到的圓');
a2
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.95時的圓的個數%統計結果
a1
=22 %相位編碼方法找到繪制靈敏度為0.95時的圓的個數為22個a2
=22 %兩階段方法找到繪制靈敏度為0.95時的圓的個數為22個
請注意,imfindcircles 中的兩種方法都能準確找到部分可見(遮擋)塑料片的中心和半徑。
步驟 7:為什么有些圓仍檢測不到?
查看最后一個結果,很奇怪 imfindcircles 沒有在圖像中找到黃色塑料片。黃色塑料片與背景的對比不夠強烈。事實上,它們看起來和背景的強度非常相似。是不是黃色塑料片并沒有想象中的那樣比背景“更暗”?要確認這一點,請再次顯示該圖像的灰度版本。
步驟 8:在圖像中找到“明亮”的圓
查看圖像的灰度圖,可發現與背景相比,黃色塑料片的強度幾乎相同,甚至更亮。因此,要檢測黃色塑料片,請將 ‘ObjectPolarity’ 更改為 ‘bright’。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(1,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92
);
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用相位編碼方法在圖像上繪制靈敏度為0.92時找到的圓
title
('相位編碼方法:靈敏度為0.92時找到的圓');
a1
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.92時的圓的個數subplot
(1,2,2
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92,
'Method',
'twostage');
imshow
(rgb
);
h
= viscircles
(centers,radii
); %用兩階段方法在圖像上繪制靈敏度為0.92時找到的圓
title
('兩階段方法:靈敏度為0.92時找到的圓');
a2
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.92時的圓的個數%統計結果
a1
=3a2
=5
步驟 9:用不同顏色繪制 ‘Bright’ 圓
通過更改 viscircles 中的 ‘Color’ 參數,以不同顏色繪制明亮的圓。
h
= viscircles
(centers,radii,
'Color',
'b'); %將上面程序中的代碼改為此代碼即可
請注意,找到了三個原先未檢測到的黃色塑料片,但仍有黃色塑料片未檢測到。這些黃色塑料片很難檢測到,因為在這種背景下,它們沒有呈現出與眾不同。
步驟 10:降低 ‘EdgeThreshold’ 的值
在這里還可以使用 imfindcircles 中的另一個參數,即 ‘EdgeThreshold’。要查找圓,imfindcircles 僅使用圖像中的邊緣像素。這些邊緣像素基本上是具有高梯度值的像素。‘EdgeThreshold’ 參數控制像素的梯度值必須有多高,才能將其視為邊緣像素并包含在計算中。該參數的高值(更接近 1)只允許包含強邊緣(較高梯度值),而低值(更接近 0)的寬容度更高,可在計算中包含較弱的邊緣(較低梯度值)。對于檢測不到黃色塑料片的情況,是因為對比度低,一些邊界像素(在塑料片的圓周上)預期具有低梯度值。因此,請降低 ‘EdgeThreshold’ 參數,以確保黃色塑料片的大多數邊緣像素都包含在計算中。
rgb
= imread
('coloredChips.png'); %加載圖像
subplot
(1,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92,
'EdgeThreshold',0.1
);
imshow
(rgb
);
h
= viscircles
(centers,radii,
'Color',
'b'); %用相位編碼方法在圖像上繪制靈敏度為0.92時找到的圓
title
('相位編碼方法:靈敏度為0.92時找到的圓');
a1
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.92時的圓的個數subplot
(1,2,2
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92,
'Method',
'twostage',
'EdgeThreshold',0.1
);
imshow
(rgb
);
h
= viscircles
(centers,radii,
'Color',
'b'); %用兩階段方法在圖像上繪制靈敏度為0.92時找到的圓
title
('兩階段方法:靈敏度為0.92時找到的圓');
a2
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.92時的圓的個數%統計結果
a1
=5a2
=6
步驟 11:同時繪制“暗”和“亮”圓
現在 imfindcircles 找到了所有黃色圓,還找到了一個綠色圓。用藍色繪制這些塑料片,用紅色繪制之前發現的其他塑料片(‘ObjectPolarity’ 設置為 ‘dark’)。
用相位編碼法找到的所有圓
**
rgb
= imread
('coloredChips.png'); %加載圖像
%subplot
(2,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92
);
imshow
(rgb
);
h
= viscircles
(centers,radii,
'color',
'b'); %用相位編碼方法在圖像上繪制靈敏度為0.92時找到
"亮"圓
title
('相位編碼方法:靈敏度為0.92時找到的圓');
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.92
);
h
= viscircles
(centers,radii
); %找到
"暗"圓
a1
= length
(centers
) %計算相位編碼方法找到繪制靈敏度為0.92時的圓的個數%統計個數
a1
=16
用兩階段法找到的圓
rgb
= imread
('coloredChips.png'); %加載圖像
%subplot
(2,2,1
);
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'bright',
'Sensitivity',0.92,
'Method',
'twostage');
imshow
(rgb
);
h
= viscircles
(centers,radii,
'color',
'b'); %用兩階段方法在圖像上繪制靈敏度為0.92時找到
"明"圓
title
('兩階段方法:靈敏度為0.92時找到的圓');
[centers,radii
] = imfindcircles
(rgb,
[20 25],
'ObjectPolarity',
'dark',
'Sensitivity',0.92,
'Method',
'twostage');
h
= viscircles
(centers,radii
); %找到
"暗"圓
a2
= length
(centers
) %計算兩階段方法找到繪制靈敏度為0.92時的圓的個數%統計結果
a2
= 22
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的1.2 检测和测量图像中的圆形目标的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。