圖像分割的目的是將圖像劃分為多個不同的區(qū)域,所以我們可以直接從尋找圖像中的區(qū)域來設(shè)計(jì)分割算法。區(qū)域生長正是一種基于區(qū)域?qū)ふ业膫鹘y(tǒng)圖像分割算法。
區(qū)域生長基本原理
區(qū)域生長(Region Growth)算法是一種基于區(qū)域的傳統(tǒng)圖像分割算法。區(qū)域生長可以根據(jù)預(yù)先定義的生長規(guī)則將像素或者小區(qū)域不斷組合為更大區(qū)域的過程。具體地,區(qū)域生長是從一組初始種子點(diǎn)出發(fā),通過預(yù)先定義的區(qū)域生長規(guī)則,將與種子點(diǎn)性質(zhì)相似的領(lǐng)域像素不斷添加到每個種子點(diǎn)上,并且滿足區(qū)域生長的終止條件時形成最終生長區(qū)域的過程。假設(shè)為待分割的輸入圖像陣列,為一組種子點(diǎn)陣列,其中種子點(diǎn)處位置為1,其他位置為0,并且假設(shè)和具有相同的尺寸。表示在每個像素點(diǎn)的相關(guān)屬性?;?連接的區(qū)域生長算法的流程描述如下:
在種子陣列中找到所有的連通分量,將每個連通分量腐蝕為一個像素,并將腐蝕成功的像素標(biāo)記為1,其他像素標(biāo)記為0.
在坐標(biāo)形成圖像,如果輸入圖像在該點(diǎn)坐標(biāo)處滿足給定的屬性,則令,否則令。
將中為8連通種子點(diǎn)的所有為1的點(diǎn)添加到s中的每個種子點(diǎn)中直至滿足生長結(jié)束條件。
最后在不同區(qū)域標(biāo)記出每個連通分量形成最終的分割圖像。
下面我們通過一個簡單的計(jì)算例子來更加直觀地理解區(qū)域生長算法。
假設(shè)有如圖所示的5×5圖像陣列,選定陣列中最大值9作為初始種子點(diǎn)(圖中橙色像素塊),區(qū)域生長的像素閾值為2,現(xiàn)按照區(qū)域生長算法對該圖像陣列進(jìn)行分割。
按照區(qū)域生長閾值2,取值范圍為[7,11],生長后的區(qū)域像素均值為7.8。第一次生長效果如圖2所示,藍(lán)色區(qū)域即第一次生長后的區(qū)域。
第一次生長后的區(qū)域均值為7.8,按照生長閾值為2,第二次生長的像素取值范圍應(yīng)為[5.8,9.8],如圖3所示,綠色部分為第二次生長的區(qū)域結(jié)果。
第二次生長后的區(qū)域均值為7.1,按照生長閾值為2,第三次生長的像素取值范圍應(yīng)為[5.1,9.1],如圖4所示,黃色部分為第三次生長的區(qū)域結(jié)果。
第三次生長后的區(qū)域均值為6.9,按照生長閾值為2,第三次生長的像素取值范圍應(yīng)為[4.9,8.9],周邊已沒有滿足繼續(xù)生長的像素點(diǎn),到此我們停止生長。將生長后的區(qū)域標(biāo)記為1,其他區(qū)域標(biāo)記為0,最終的分割區(qū)域如圖5所示。
區(qū)域生長分割示例
給定一張NBA球星科比的圖像(如圖6所示),我們嘗試實(shí)現(xiàn)一個區(qū)域生長圖像分割算法來對該圖像進(jìn)行前景與背景的分割。
現(xiàn)嘗試基于C++代碼來實(shí)現(xiàn)一個區(qū)域生長分割算法。按照前述基于8連接的區(qū)域生長算法的流程描述,實(shí)現(xiàn)過程如下代碼所示。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
// 定義區(qū)域生長分割算法
bool RegionGrowing(Mat img, Mat& result, Point2i seed, int threshold) {
// 將圖像全部設(shè)置為黑
result = Mat::zeros(img.size(), CV_8UC1);
// 設(shè)置種子點(diǎn)范圍條件
if (seed.x < 0 || seed.y < 0 || seed.y > img.rows - 1 || seed.x > img.cols - 1) {
return false;
}
// 種子點(diǎn)集
vector<Point2i> seeds;
// 壓入初始種子點(diǎn)
seeds.push_back(seed);
// 種子點(diǎn)設(shè)置為白
result.ptr<uchar>(seed.y)[seed.x] = 255;
// 8連接生長方向
int growDirections[8][2] = { {-1,-1}, {0,-1}, {1,-1}, {-1,0}, {1,0}, {-1,1}, {0,1}, {1,1} };
// 開始生長
while (!seeds.empty()) {
// 取出一個種子點(diǎn)作為現(xiàn)在循環(huán)的初始種子點(diǎn)
Point2i seed_current = seeds.back();
seeds.pop_back();
// 遍歷各生長方向的鄰點(diǎn)
for (int i = 0; i < 8; i++) {
Point2i neighborPoint = { seed_current.x + growDirections[i][0], seed_current.y + growDirections[i][1] }; // 鄰點(diǎn)
if (neighborPoint.x < 0 || neighborPoint.y < 0 || neighborPoint.x > img.cols - 1 || neighborPoint.y > img.rows - 1) { // 鄰點(diǎn)超出范圍
continue;
}
if ((result.ptr<uchar>(neighborPoint.y)[neighborPoint.x] == 0) && abs(img.ptr<uchar>(neighborPoint.y)[neighborPoint.x] - img.ptr<uchar>(seed.y)[seed.x]) < threshold) {
// 設(shè)置為種子點(diǎn)
result.ptr<uchar>(neighborPoint.y)[neighborPoint.x] = 255; // 設(shè)置為白色
seeds.push_back(neighborPoint); // 壓入種子集
}
}
}
return true;
}
基于上述代碼分割后的圖像如圖7所示??梢钥吹?,區(qū)域生長算法基本上能分割出目標(biāo)區(qū)域,但因?yàn)閳D像本身復(fù)雜性,在分割效果上仍有待提升的地方。
參考資料:
岡薩雷斯 數(shù)字圖像處理
https://gy23333.github.io/2020/01/18/%E5%9F%BA%E4%BA%8E%E5%8C%BA%E5%9F%9F%E7%9A%84%E5%9B%BE%E5%83%8F%E5%88%86%E5%89%B2%E2%80%94%E2%80%94%E5%8C%BA%E5%9F%9F%E7%94%9F%E9%95%BF/
往期精彩:
《機(jī)器學(xué)習(xí):公式推導(dǎo)與代碼實(shí)現(xiàn)》1-7章PPT下載
《機(jī)器學(xué)習(xí) 公式推導(dǎo)與代碼實(shí)現(xiàn)》隨書PPT示例
?時隔一年!深度學(xué)習(xí)語義分割理論與代碼實(shí)踐指南.pdf第二版來了!
?新書首發(fā) | 《機(jī)器學(xué)習(xí) 公式推導(dǎo)與代碼實(shí)現(xiàn)》正式出版!文章來源:http://www.zghlxwxcb.cn/news/detail-445460.html
《機(jī)器學(xué)習(xí)公式推導(dǎo)與代碼實(shí)現(xiàn)》將會配套PPT和視頻講解!文章來源地址http://www.zghlxwxcb.cn/news/detail-445460.html
到了這里,關(guān)于基于區(qū)域生長的圖像分割算法!的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!