区域生长算法
1.理论基础
区域生长算法的基本思想是将有相似性质的像素点合并到一起。对每一个区域要先指定一个种子点作为生长的起点,然后将种子点周围领域的像素点和种子点进行对比,将具有相似性质的点合并起来继续向外生长,直到没有满足条件的像素被包括进来为止。这样一个区域的生长就完成了。这个过程中有几个关键的问题:
a> 给定种子点(种子点如何选取?)
种子点的选取很多时候采用人工交互的方法实现,也有用其他方式的,比如寻找物体并提取物体内部点作为种子点
b> 确定在生长过程中能将相邻像素包括进来的准则
灰度值的差值,彩色图像的颜色等等,是关于像素与像素之间的关系描述
c> 生长的停止条件
2.灰度差值的区域生长算法实现
a> 创建一个空白的图像(全黑);
b> 将种子点存入vector中,vector中存储待生长的种子点;
c> 依次弹出种子点并判断种子点如周围8领域的关系(生长规则),相似的点则作为下次生长的种子点;
d> vector中不存在种子点后就停止生长。
简单实现:
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;
}
3.区域生长算法的一种C++实现
首先,定义种子点的类
class Point2D
{
public:
Point2D(){}
Point2D(int ix,int iy)
{
this->x=ix;
this->y=iy;
}
~Point2D(){}
Point2D operator+(const Point2D& a)const
{
return Point2D(x+a.x,y+a.y);
}
Point2D operator-(const Point2D& a)const
{
return Point2D(x-a.x,y-a.y);
}
bool operator=(const Point2D& a)
{
return(x==a.x&&y==a.y);
}
int x;
int y;
然后,定义种子点的邻域信息
const Point2D PointShift2D[8]=
{
Point2D(1,0),
Point2D(1,-1),
Point2D(0,-1),
Point2D(-1,-1),
Point2D(-1,0),
Point2D(-1,1),
Point2D(0,1),
Point2D(1,1)
};
然后,定义区域生长算法类的头文件
class RegionGrowing
{
public:
RegionGrowing();
~RegionGrowing();
void SetInputData(chat *pData,int width,int height);
void SetSeedPoint(Point2D &p);
void SetThreshold(int low,int height);
bool RegionGrow2D();
char* GetOutput();
private:
int LowThreshold;
int HighThreshold;
int Width;
int Height;
char *InputData;
char *OutputData;
Point2D SeePoint;
}
然后,是区域生长算法类的实现
#include"RegionGrowing.h"
#include<stack。
RegionGrowing::RegionGrowing()
{
this->InputData=nullptr;
this->OutputData=nullptr();
}
RegionGrowing::~RegionGrowing()
{
}
void RegionGrowing::SetInputData(char *pData,int width,int height)
{
this->InputData=pData;
this->Width=width;
this->Height=height;
}
void RegionGrowing::SetSeedPoint(Point2D &p)
{
this->SeedPoint=p;
}
void RegionGrowing::SetThreshold(int low,int high)
{
this->LowThreshold=low;
this_HighThreshold=high;
}
bool RegionGrowing::RegionGrow2D()
{
if(this->InputData==nullptr||this->OutputData==nullptr)
{
return false;
}
int index=this->SeedPoint.y*this->Width+this->SeedPoint.x;
int seedValue=this->InputData[index];
std::stack<Point2D>pointStack;
pointStack.push(this->SeedPoint);
memset(this->OutputData,0,sizeof(char)*this->Width*this-Height);
while(!pointStack.empty())
{
Point2D topPoint=pointStack.top();
pointStack.pop();
for(int i=0;i<8;i++)
{
Point2D p=topPoint+PointShift2D[i];
index=p.y*this->width+p.x;
if(this->InputData[index]>this->LowThreshold&&
this->InputData[index]<this->HighThreshold&&
this->OutputData[index]==0)
{
this->OutputData[index]=126;
pointStack.push(p);
}
}
}
return true;
}
char* RegionGrowing::GetOutput()
{
return this->OutputData;
}
参考:https://blog.csdn.net/robin__chou/article/details/50071313
https://www.cnblogs.com/xuhui24/p/6262011.html
https://blog.csdn.net/webzhuce/article/details/81412508