Bootstrap

4.1图像分割之区域生长法

 我们将讨论以区域为基础的图像分割处理技术。传统的区域分割方法有区域生长和区域分裂与合并,
 其中最基础的是区域生长法。

区域生长法

区域生长是根据事先定义的准则将像素或者子区域聚合成更大区域的过程。其基本思想是从一组生长点开始(生长点可以是单个像素,也可以是某个小区域),将与该生长点性质相似的相邻像素或者区域与生长点合并,形成新的生长点,重复此过程直到不能生长为止。生长点和相似区域的相似性判断依据可以是灰度值、纹理、颜色等图像信息。所以区域生长算法关键有三个:
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,因而被合并。图©是第二次生长后,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;
}

运行结果:

这里写图片描述

[代码下载]

;