【從零學習OpenCV 4】分割影象——Mean-Shift分割演算法
本文首發於“小白學視覺”微信公眾號,歡迎關注公眾號
本文作者為小白,版權歸人民郵電出版社發行所有,禁止轉載,侵權必究!
經過幾個月的努力,小白終於完成了市面上第一本OpenCV 4入門書籍《OpenCV 4開發詳解》。為了更讓小夥伴更早的瞭解最新版的OpenCV 4,小白與出版社溝通,提前在公眾號上連載部分內容,請持續關注小白。
Mean-Shift演算法又被稱為均值漂移法,是一種基於顏色空間分佈的影象分割演算法。該演算法的輸出是一個經過濾色的“分色”影象,其顏色會變得漸變,並且細紋紋理會變得平緩。
在Mean-Shift演算法中每個畫素點用一個五維的向量$(x,y,b,g,r)$表示,前兩個量是畫素點在影象中的座標$(x,y)$,後三個量是每個畫素點的顏色分量(藍、綠、紅)。在顏色分佈的峰值處開始,透過滑動視窗不斷尋找屬於同一類的畫素點並統一畫素點的畫素值。滑動視窗由半徑和顏色幅度構成,半徑決定了滑動視窗的範圍,即座標$(x,y)$的範圍,顏色幅度決定了半徑內畫素點分類的標準。這樣透過不斷地移動滑動視窗,實現基於畫素點顏色的影象分割。由於分割後同一類畫素點具有相同畫素值,因此Mean-Shift演算法的輸出結果是一個顏色漸變、紋理平緩的影象。
OpenCV 4中提供了實現Mean-Shift演算法分割影象的pyrMeanShiftFiltering()函式,該函式的函式原型在程式碼清單8-23中給出。
程式碼清單
8
-
23
pyrMeanShiftFiltering
()
函式原型
1。
void
cv
::
pyrMeanShiftFiltering
(
InputArray
src
,
2。
OutputArray
dst
,
3。
double
sp
,
4。
double
sr
,
5。
int
maxLevel
=
1
,
6。
TermCriteria
termcrit
=
7。
TermCriteria
(
TermCriteria
::
MAX_ITER
+
TermCriteria
::
EPS
,
5
,
1
)
8。
)
src:待分割的輸入影象,必須是三通道CU_8U的彩色影象
dst:分割後的輸出影象,與輸入影象具有相同的尺寸和資料型別
sp:滑動視窗的半徑
sr:滑動視窗顏色幅度
maxLevel:分割金字塔縮放層數
termcrit:迭代演算法終止條件。
該函式基於彩色影象的畫素值實現對影象的分割,函式的輸出結果是經過顏色分佈平滑的影象。經過該函式分割後的影象具有較少的紋理資訊,可以利用邊緣檢測函式Canny()以及連通域查詢函式findContours()進行進一步細化分類和處理。函式前兩個引數是待分割的輸入影象和分割後的輸出影象,兩個影象具有相同的尺寸並且必須是CV_8U的三通道彩色影象。第三個引數為滑動視窗的半徑,第四個引數為滑動視窗的顏色幅度。第五個引數為分割金字塔縮放層數,當引數大於1時構建maxLevel + 1層高斯金字塔。該演算法首先在尺寸最小的影象層中進行分類,之後將結果傳播到尺寸較大的影象層,並且僅在顏色與上一層顏色差異大於滑動視窗顏色幅度的畫素上再次進行分類,從而使得顏色區域的邊界更清晰。當分割金字塔縮放層數為0時表示直接在整個原始影象時進行均值平移分割。函式最後一個引數表示演算法迭代停止的條件,該引數的資料型別是TermCriteria,該資料型別是OpenCV 4中用於表示迭代演算法終止條件的資料型別,在所有涉及到迭代條件的函式中都有該引數,用於表示在滿足某些條件時函式將停止迭代並輸出結果。TermCriteria變數可以透過TermCriteria()函式進行賦值,該函式的函式原型在程式碼清單8-24中給出。
程式碼清單
8
-
24
TermCriteria
()
函式原型
1。
cv
::
TermCriteria
::
TermCriteria
(
int
type
,
2。
int
maxCount
,
3。
double
epsilon
4。
)
type:終止條件的型別標誌,可以選擇的引數及含義在表8-6中給出。
maxCount:最大迭代次數或者元素數。
epsilon:迭代演算法停止時需要滿足的精度或者引數變化。
該函式可以表示迭代演算法的終止條件,主要分為滿足迭代次數和滿足計算精度兩種。函式第一個引數是終止條件的型別標誌,其可選引數在表8-6中給出,這幾個標誌可以互相結合使用,需要注意的是,由於該引數在TermCriteria類中,因此在使用時需要在變數前面添類名字首。函式第二個引數表示最大迭代次數,在epsilon== TermCriteria::COUNT時發揮作用。函式第三個引數表示停止迭代時需要滿足的計算精度,在epsilon== TermCriteria::EPS時發揮作用。
表8-6 TermCriteria()函式中終止條件的型別標誌可選引數及含義
為了瞭解pyrMeanShiftFiltering()函式的使用方法以及分割效果,在程式碼清單8-25中給出了利用該函式進行影象分割的示例程式。程式中對影象連續進行兩次處理,並對分割結果提取Canny邊緣,比較分割前後對影象邊緣的影響,發現經過多次分割處理後的影象邊緣明顯變少,影象分割區域也更加整齊和平滑,程式的執行結果在圖8-15、圖8-16和圖8-17中給出。
程式碼清單
8
-
25
myPyrMeanShiftFiltering
。
cpp利用均值漂移法分割影象
1。
#
include
<
opencv2
/
opencv
。
hpp
>
2。
#
include
<
iostream
>
3。
4。
using
namespace
cv
;
5。
using
namespace
std
;
6。
7。
int
main
()
8。
{
9。
Mat
img
=
imread
(
“coin。png”
);
10。
if
(
!
img
。
data
)
11。
{
12。
cout
<<
“請確認影象檔名稱是否正確”
<<
endl
;
13。
return
-
1
;
14。
}
15。
16。
//分割處理
17。
Mat
result1
,
result2
;
18。
TermCriteria
T10
=
TermCriteria
(
TermCriteria
::
COUNT
|
TermCriteria
::
EPS
,
10
,
0。1
);
19。
pyrMeanShiftFiltering
(
img
,
result1
,
20
,
40
,
2
,
T10
);
//第一次分割
20。
pyrMeanShiftFiltering
(
result1
,
result2
,
20
,
40
,
2
,
T10
);
//第一次分割的解僱再次分割
21。
22。
//顯示分割結果
23。
imshow
(
“img”
,
img
);
24。
imshow
(
“result1”
,
result1
);
25。
imshow
(
“result2”
,
result2
);
26。
27。
//對影象提取Canny邊緣
28。
Mat
imgCanny
,
result1Canny
,
result2Canny
;
29。
Canny
(
img
,
imgCanny
,
150
,
300
);
30。
Canny
(
result1
,
result1Canny
,
150
,
300
);
31。
Canny
(
result2
,
result2Canny
,
150
,
300
);
32。
33。
//顯示邊緣檢測結果
34。
imshow
(
“imgCanny”
,
imgCanny
);
35。
imshow
(
“result1Canny”
,
result1Canny
);
36。
imshow
(
“result2Canny”
,
result2Canny
);
37。
waitKey
(
0
);
38。
return
0
;
39。
}
圖8-15 myPyrMeanShiftFiltering。cpp程式中原圖及Canny邊緣
圖8-16 myPyrMeanShiftFiltering。cpp程式中處理一次影象及Canny邊緣
圖8-17 myPyrMeanShiftFiltering。cpp程式中處理兩次影象及Canny邊緣
經過幾個月的努力,市面上第一本OpenCV 4入門書籍《OpenCV 4開發詳解》將春節後由人民郵電出版社發行。如果小夥伴覺得內容有幫助,希望到時候多多支援!
關注小白的小夥伴可以提前看到書中的內容,我們建立了學習交流群,歡迎各位小夥伴新增小白微信加入交流群,新增小白時請備註“學習OpenCV 4”。