4.1影象分割之區域生長法
阿新 • • 發佈:2019-02-01
我們將討論以區域為基礎的影象分割處理技術。傳統的區域分割方法有區域生長和區域分裂與合併,
其中最基礎的是區域生長法。
區域生長法
區域生長是根據事先定義的準則將畫素或者子區域聚合成更大區域的過程。其基本思想是從一組生長點開始(生長點可以是單個畫素,也可以是某個小區域),將與該生長點性質相似的相鄰畫素或者區域與生長點合併,形成新的生長點,重複此過程直到不能生長為止。生長點和相似區域的相似性判斷依據可以是灰度值、紋理、顏色等影象資訊。所以區域生長演算法關鍵有三個:
1、選擇合適的生長點
2、確定相似性準則即生長準則
3、確定生長停止條件
下面給出一個區域生長的例項:圖(a)為原始影象,數字表示畫素的灰度。以灰度值為8的畫素為初始的生長點,記為f(i,j)。在8鄰域內,生長準則是待測點灰度值與生長點灰度值相差為1或0.那麼圖(b)是第一次區域生長後,f(i-1,j)、f(i,j-1)、f(i,j+1)和生長點灰度值相差都是1,因而被合併。圖(c)是第二次生長後,f(i+1,j)被合併。圖(d)為第三次生長後,f(i+1,j-1)、f(i+2,j)被合併,至此,已經不存在滿足生長準則的畫素點,生長停止。
示例演示
我們實現一個功能,滑鼠選擇一個初始生長點,生長準則是待測點灰度值與初始生長點灰度值差的絕對值不大於8。示例程式碼中regionGrow函式參考了《數字影象處理與機器學習》第九章第五節,regionGrowFast函式是優化過的實現,程式碼如下:
cv::Mat MainWindow::regionGrowFast(const cv::Mat &src, const cv::Point2i seed, int throld)
{
//convert src to gray for getting gray value of every pixel
cv::Mat gray;
cv::cvtColor(src,gray, cv::COLOR_RGB2GRAY);
// set every pixel to black
cv::Mat result = cv::Mat::zeros(src.size(), CV_8UC1);
if((seed.x < 0) || (seed.y < 0))
return result;
result.at<uchar>(seed.y, seed.x) = 255;
//gray value of seed
int seed_gray = gray.at<uchar>(seed.y, seed.x);
//grow direction sequenc
int grow_direction[8 ][2] = {{-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0}};
//seeds collection
std::vector<cv::Point2i> seeds;
seeds.push_back(seed);
//start growing
while(! seeds.empty()){
//get a seed
cv::Point2i current_seed = seeds.back();
seeds.pop_back();
for(int i = 0; i < 8; ++i){
cv::Point2i neighbor_seed(current_seed.x + grow_direction[i][0], current_seed.y + grow_direction[i][1]);
//check wether in image
if(neighbor_seed.x < 0 || neighbor_seed.y < 0 || neighbor_seed.x > (gray.cols-1) || (neighbor_seed.y > gray.rows -1))
continue;
int value = gray.at<uchar>(neighbor_seed.y, neighbor_seed.x);
if((result.at<uchar>(neighbor_seed.y, neighbor_seed.x) == 0) && (abs(value - seed_gray) <= throld)){
result.at<uchar>(neighbor_seed.y, neighbor_seed.x) = 255;
seeds.push_back(neighbor_seed);
}
}
}
return result;
}