OpenCV:区域生长法实现

时间:2024-10-13 20:43:57

1、基本思想:区域生长法的懋鲕壶迎基本思想是:将具有相似性质的像素点合并到一起;在每一个区域内首先要指定一个种子点作为生长的起点;收墩芬蓥然后将种子点周围邻域的像素点与种子点进行比较,对具有相似性质的点合并之后继续向外生长,直到没有满足条件的像素被包括进来为止;这样一个区域的生长就完成了。下图是:发在PAMI上的LSD直线检测算法中的关键一步就是找line support regions.这个区域的查找就是利用区域生长法则,生长的条件就是梯度的方向角度;图中第一张图是原始图像,第二张是计算梯度角度,第三张是根据梯度角度区域生长的结果,相同颜色就是一个区域生长结果。

OpenCV:区域生长法实现

2、关键点在于:①给定种子点(种子点如何选取)种子点的选取很多时候都采用人工交互的方法实现,也有用其他方式的,比如寻找物体并提取物体内部点作为种子点。②确定在生长过程中能将相邻像素包括进来的准则(相似性质准则)灰度图像的差值;彩色图像的颜色等等。都是关于像素与像素间的关系描述。③生长的停止条件:四连通与八连通

OpenCV:区域生长法实现

3、区域生长流程:①给出种子点,这里一次给出一个种子点②给出相似性准则,这里采用灰度差;③将种子点与其八邻域像素点进行相似性比较;相似点则作为下次生长的种子点;④停止生长:八邻域内没有合并的像素点时,即没有新的种子点时,停止。如图所示:

OpenCV:区域生长法实现

4、示例程序:OpenCV没有自带区域生长函数;为了说明区域是如何生长的,#include <opencv2\opencv.hpp>#include &造婷用痃lt;opencv2\highgui\highgui.hpp>#include <opencv2\features2d\features2d.hpp>#include <opencv2\core\core.hpp>using namespace std;using namespace cv;void RegionGrowing(Mat srcImg,Mat& dstImg,Point pt,int thre){ Point ptGrowing;//生长点像素坐标 int nGrowLabel=0;//是否被标记 int startPtValue=0;//生长起始点灰度值 int currPtValue=0;//当前生长点灰度值 //8邻域 int mDir[8][2]={{-1,-1},{0,-1},{1,-1},{-1,0},{1,0},{-1,1},{0,1},{1,1}}; vector<Point> growPtVec;//生长点堆栈 growPtVec.push_back(pt);//将初始生长点压入堆栈 Mat markImg=Mat::zeros(srcImg.size(),CV_8UC1);//标记点 unsigned char *pData = (unsigned char *)(markImg.data+pt.y*markImg.step); pData[pt.x]=255;//标记初始生长点 startPtValue = ((unsigned char*)(srcImg.data+pt.y*srcImg.step))[pt.x]; while (!growPtVec.empty()) { Point currPt = growPtVec.back();//返回当前vector最末一个元素 growPtVec.pop_back();//弹出最后压入的数据 for (int i=0;i<8;i++) { ptGrowing.x = currPt.x+mDir[i][0]; ptGrowing.y = currPt.y+mDir[i][1]; //判断是否是边缘点 if (ptGrowing.x<0||ptGrowing.y<0||(ptGrowing.x>srcImg.cols-1)||(ptGrowing.y>srcImg.rows)) continue;//继续执行下一次循环 //判断是否已被标记 nGrowLabel = ((unsigned char*)(markImg.data+ptGrowing.y*markImg.step))[ptGrowing.x]; if (nGrowLabel==0)//没有被标记 { currPtValue = ((unsigned char*)(srcImg.data+ptGrowing.y*srcImg.step))[ptGrowing.x]; if (abs(currPtValue-startPtValue)<=thre) { ((unsigned char*)(markImg.data+ptGrowing.y*markImg.step))[ptGrowing.x]=255; growPtVec.push_back(ptGrowing); } } } } markImg.copyTo(dstImg);}int main(){ Mat srcImg = imread("1.jpg",0); if (srcImg.empty()) printf("image read error"); Mat srcImg1=srcImg.clone(); Mat outImg1,outImg2; RegionGrowing(srcImg1,outImg1,Point(241,258),10); RegionGrowing(srcImg1,outImg2,Point(302,118),80); add(outImg1,outImg2,outImg1); imshow("p1p2",outImg1); Mat resultImg; srcImg.copyTo(resultImg,~outImg1); imshow("outImg",resultImg); waitKey(0); return 0;}

OpenCV:区域生长法实现
OpenCV:区域生长法实现

5、算法效果:这里首先人为选取一个种子点,在其八邻域内,由相似性准则进行判断并更新种子点;当不再产生新的种子点时,截止;当区分多目标是,可以认为选取多个种子点,然后将每个种子点分割区域合并;即可分割出多目标。

OpenCV:区域生长法实现

6、给出一个比较好区域生长法的程序://仅根据纹理分割图闻赙酵枭像,纹理特征是四维集合;void segmentTexture(Mat texture){ Mat regions(texture.rows荑樊综鲶, texture.cols, CV_8UC1, 0.0); Mat mark(texture.rows, texture.cols, CV_8UC1, 0.0); int min_regions = 10; RNG rng(25); Point seedPoint, now; Vec4b curr, next, seed; queue<Point> Q; vector<pair<pair<Point, Vec3b>, int> > Points; int pixelCount=0;//pixel covered in a segment for(int i =250; i>10; i -= 250/min_regions) { rng(12345); do { seedPoint.x = rng.uniform(0, texture.cols); seedPoint.y = rng.uniform(0, texture.rows); seed = texture.at<Vec4b>(seedPoint.y, seedPoint.x); } while(mark.at<uchar>(seedPoint.y, seedPoint.x) !=0 ); mark.at<uchar>(seedPoint.y, seedPoint.x) = i; Q.push(seedPoint); while(!Q.empty()) { now = Q.front(); Q.pop(); curr=texture.at<Vec4b>(now.y, now.x); for(int p=-1; p<=1; p++) { for(int q=-1; q<=1; q++) { if(0<=now.x+p && now.x+p<texture.cols && 0<=now.y+q && now.y+q<texture.rows) { next=texture.at<Vec4b>(now.y+q, now.x+p); if(mark.at<uchar>(now.y+q, now.x+p)==0 && (textureDifference(next, seed)==1 || farTextureDifference(next, curr)==2)) { Q.push(Point(now.x+p, now.y+q)); mark.at<uchar>(now.y+q, now.x+p)=i; //segm.at<Vec3b>(now.y, now.x)=image.at<Vec3b>(seedPoint.y, seedPoint.x); } } } } } } ///namedWindow("texture segment",2); ///imshow("texture segment",mark); imwrite("textureSegment.bmp",mark);}

© 手抄报圈