• OpenCV(二十八):连通域分割


    目录

    1.介绍连通域分割

    2.像素领域介绍

    3.两遍法分割连通域

    4.连通域分割函数


    1.介绍连通域分割

           连通域分割是一种图像处理技术,用于将图像中的相邻像素组成的区域划分为不同的连通域。这些像素具有相似的特性,如相近的灰度值或颜色。连通域分割可以用于物体检测、图像分割、目标跟踪等应用。

    2.像素领域介绍

             在连通域分割中,常用的领域关系有四领域和八领域。

    • 四领域表示一个像素与其上下左右四个相邻像素连接。
    • 八领域表示一个像素与其上、下、左、右、左上、右上、左下、右下八个相邻像素连接。

    3.两遍法分割连通域

    (橙色区域为目标物体,即前景像素)

    1,第一遍扫描:

    a. 从上往下,从左往右遍历图像的每个像素,检查其是否属于前景像素(包括目标物体)。如果是前景像素,则进行以下操作:

    • 检查其上方和左方的像素

                    (1) 如果都是前景像素, 则取两者中像素的标签的最小值作为当前像素的标签。

                    (2)如果只有一个是前景像素,则将当前像素标记为该前景像素的标签。

                     (3) 如果两个方向都没有前景像素,则将当前像素标记为新的数字标签。(数字标签                                从1开始,然后不断+1递增)

    第一遍扫描的结果:

    2.第二遍扫描:

    a. 将同一连通区域内的不同相邻标签合并,取标签的最小值,使每个连通域只有一个标签。

    第二遍扫描结果:

    4.连通域分割函数

     4.1只分割连通域的函数 connectedComponents() 

    int cv::connectedComponents ( InputArray   image,

    OutputArray labels,

    int    connectivity =8,

    int   ltype = CV_32S

    • image:待标记不同连通域的图像单通道,数据类型必须为CV 8U。
    • labels:标记不同连通域后的输出图像,与输入图像具有相同的尺寸。
    • connectivity:标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域,默认参数为8。
    • ltype:输出图像的数据类型,目前支持CV 32S和CV 16U两种数据类型,默认参数为CV 32S

     示例代码:

    1. void connect_f(Mat image){
    2. Mat rice,riceBW;
    3. //将图像转成二值图像,用于统计连通域
    4. cvtColor(image,rice,COLOR_BGR2GRAY);
    5. threshold(rice,riceBW,50,255,THRESH_BINARY);
    6. //生成随机颜色,用于区分不同连通域
    7. RNG rng(10086);
    8. Mat out;
    9. int number= connectedComponents(riceBW,out,8,CV_16U);//统计图像中连通域的个数
    10. vector<Vec4b> colors;
    11. for(int i=0;i<number;i++){
    12. //使用均匀分布的随机数确定颜色
    13. Vec4b vec4=Vec4b(rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256));
    14. colors.push_back(vec4);
    15. }
    16. //以不同颜色标记出不同的连通域
    17. Mat result=Mat::zeros(rice.size(),image.type());
    18. int w=result.cols;
    19. int h=result.rows;
    20. for(int row=0;row<h;row++){
    21. for(int col=0;col<w;col++){
    22. int label=out.at<uint16_t>(row,col);
    23. if(label==0){//背景的黑色不改变
    24. continue;
    25. }
    26. result.at<Vec4b>(row,col)=colors[label];
    27. }
    28. }
    29. //显示结果
    30. imwrite("/sdcard/DCIM/result.png",result);
    31. }

     

    4.2分割并统计连通域信息的函数connectedComponentsWithStats() 

    int cv::connectedComponentsWithStats ( InputArray   image,

    OutputArray labels,

    OutputArray stats,

    OutputArray centroids,

    int   connectivity =8,

    int    ltype = CV_32S

    )

    • image:待标记不同连通域的图像单通道,数据类型必须为CV_8U。
    • labels:标记不同连通域后的输出图像,与输入图像具有相同的尺寸。
    • stats:不同连通域的统计信息矩阵,矩阵的数据类型为CV 32S。阵中第i行是标签为i的连通域的统计特性。
    • centroids:每个连通域的质心坐标,数据类型为CV 64F。
    • connectivity:标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域,默认参数值为8。
    • ltype: 输出图像的数据类型,目前只支持CV 32S和CV 16U这两种数据类型,默认参数值为CV_32S。

    示例代码:

    1. //统计连通域信息
    2. void connectedComponentsWithStats_f(Mat image){
    3. Mat rice,riceBW;
    4. //将图像转成二值图像,用于统计连通域
    5. cvtColor(image,rice,COLOR_BGR2GRAY);
    6. threshold(rice,riceBW,50,255,THRESH_BINARY);
    7. Mat stats,centroids,out;
    8. int number= connectedComponentsWithStats(riceBW,out,stats,centroids,8,CV_16U);
    9. vector<Vec4b> colors;
    10. RNG rng(10086);
    11. for(int i=0;i<number;i++){
    12. //使用均匀分别的随机数确定颜色
    13. Vec4b vec4=Vec4b(rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256),rng.uniform(0,256));
    14. colors.push_back(vec4);
    15. }
    16. //以不同颜色标记出不同的连通域
    17. for(int i=1;i<number;i++){
    18. //中心位置
    19. int center_x=centroids.at<double>(i,0);
    20. int center_y=centroids.at<double>(i,1);
    21. //矩形边框
    22. int x=stats.at<int>(i,CC_STAT_LEFT);
    23. int y=stats.at<int>(i,CC_STAT_TOP);
    24. int w=stats.at<int>(i,CC_STAT_WIDTH);
    25. int h=stats.at<int>(i,CC_STAT_HEIGHT);
    26. int area=stats.at<int>(i,CC_STAT_AREA);
    27. //中心位置绘制
    28. circle(image,Point(center_x,center_y),2,Scalar(0,255,0),2,8,0);
    29. //外接矩形
    30. Rect rect(x,y,w,h);
    31. rectangle(image,rect,colors[i],1,8,0);
    32. putText(image, format("%d",i),Point(center_x,center_y),FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,255),1);
    33. ostringstream ss;
    34. ss << "number:" <<i<<",area:"<<area<< std::endl;
    35. }
    36. //显示结果
    37. imwrite("/sdcard/DCIM/image_Markers.png",image);
    38. }

  • 相关阅读:
    《公共管理学》考试重点及答案
    H5 <blockquote> 标签
    Rabbitmq基本使用以及与springboot集成简单示例
    solidworks怎么识别STEP文件特征?
    LeetCode 33. 搜索旋转排序数组
    少年,你可听说过MVCC?
    【UiBot科普】什么是RPA企业级框架?
    4.【刷爆LeetCode】组队竞赛(多方法、多思路)
    采用python 批量下载ocean color中的卫星数据
    【PyTorch深度学习项目实战100例】—— 基于word2vec(CBOW)方法训练词向量 | 第61例
  • 原文地址:https://blog.csdn.net/weixin_63357306/article/details/132737867