目录
连通域分割是一种图像处理技术,用于将图像中的相邻像素组成的区域划分为不同的连通域。这些像素具有相似的特性,如相近的灰度值或颜色。连通域分割可以用于物体检测、图像分割、目标跟踪等应用。
在连通域分割中,常用的领域关系有四领域和八领域。
(橙色区域为目标物体,即前景像素)
1,第一遍扫描:
a. 从上往下,从左往右遍历图像的每个像素,检查其是否属于前景像素(包括目标物体)。如果是前景像素,则进行以下操作:
检查其上方和左方的像素
(1) 如果都是前景像素, 则取两者中像素的标签的最小值作为当前像素的标签。
(2)如果只有一个是前景像素,则将当前像素标记为该前景像素的标签。
(3) 如果两个方向都没有前景像素,则将当前像素标记为新的数字标签。(数字标签 从1开始,然后不断+1递增)
第一遍扫描的结果:
2.第二遍扫描:
a. 将同一连通区域内的不同相邻标签合并,取标签的最小值,使每个连通域只有一个标签。
第二遍扫描结果:
4.1只分割连通域的函数 connectedComponents()
int cv::connectedComponents ( InputArray image,
OutputArray labels,
int connectivity =8,
int ltype = CV_32S
)
示例代码:
- void connect_f(Mat image){
- Mat rice,riceBW;
- //将图像转成二值图像,用于统计连通域
- cvtColor(image,rice,COLOR_BGR2GRAY);
- threshold(rice,riceBW,50,255,THRESH_BINARY);
- //生成随机颜色,用于区分不同连通域
- RNG rng(10086);
- Mat out;
- int number= connectedComponents(riceBW,out,8,CV_16U);//统计图像中连通域的个数
- vector<Vec4b> colors;
- for(int i=0;i<number;i++){
- //使用均匀分布的随机数确定颜色
- Vec4b vec4=Vec4b(rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256));
- colors.push_back(vec4);
- }
- //以不同颜色标记出不同的连通域
- Mat result=Mat::zeros(rice.size(),image.type());
- int w=result.cols;
- int h=result.rows;
- for(int row=0;row<h;row++){
- for(int col=0;col<w;col++){
- int label=out.at<uint16_t>(row,col);
- if(label==0){//背景的黑色不改变
- continue;
- }
- result.at<Vec4b>(row,col)=colors[label];
- }
- }
- //显示结果
- imwrite("/sdcard/DCIM/result.png",result);
- }
4.2分割并统计连通域信息的函数connectedComponentsWithStats()
int cv::connectedComponentsWithStats ( InputArray image,
OutputArray labels,
OutputArray stats,
OutputArray centroids,
int connectivity =8,
int ltype = CV_32S
)
示例代码:
-
- //统计连通域信息
- void connectedComponentsWithStats_f(Mat image){
- Mat rice,riceBW;
- //将图像转成二值图像,用于统计连通域
- cvtColor(image,rice,COLOR_BGR2GRAY);
- threshold(rice,riceBW,50,255,THRESH_BINARY);
- Mat stats,centroids,out;
- int number= connectedComponentsWithStats(riceBW,out,stats,centroids,8,CV_16U);
- vector<Vec4b> colors;
- RNG rng(10086);
- for(int i=0;i<number;i++){
- //使用均匀分别的随机数确定颜色
- Vec4b vec4=Vec4b(rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256));
- colors.push_back(vec4);
- }
- //以不同颜色标记出不同的连通域
- for(int i=1;i<number;i++){
- //中心位置
- int center_x=centroids.at<double>(i,0);
- int center_y=centroids.at<double>(i,1);
- //矩形边框
- int x=stats.at<int>(i,CC_STAT_LEFT);
- int y=stats.at<int>(i,CC_STAT_TOP);
- int w=stats.at<int>(i,CC_STAT_WIDTH);
- int h=stats.at<int>(i,CC_STAT_HEIGHT);
- int area=stats.at<int>(i,CC_STAT_AREA);
- //中心位置绘制
- circle(image,Point(center_x,center_y),2,Scalar(0,255,0),2,8,0);
- //外接矩形
- Rect rect(x,y,w,h);
- rectangle(image,rect,colors[i],1,8,0);
- putText(image, format("%d",i),Point(center_x,center_y),FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,255),1);
- ostringstream ss;
- ss << "number:" <<i<<",area:"<<area<< std::endl;
- }
- //显示结果
- imwrite("/sdcard/DCIM/image_Markers.png",image);
- }
-