OpenCvSharp函数:ConnectedComponents、ConnectedComponentsWithStats、ConnectedComponentsEx

二值图像分析时黑色(0)为背景,白色(非0)为前景

邻域、邻接

对于任意像素(x,y),把像素的集合{(x+p,y+q)}(p、q是一对适当的整数)叫做像素(x,y)的邻域。即像素(x,y)附近的像素形成的区域。

邻域是指某像素p的周围像素,p与他们间的欧式距离不超过“根号2”即对角线的距离。如果q在p的某种邻域中,则p,q为某种邻接。

4-邻域:即对于像素(x,y),上下左右4个像素称为4-邻域,即以下元素:(x-1,y)(x,y-1)(x+1,y)(x,y+1)。

D-邻域:即对于像素(x,y),其中(max-1>x>1,max-1>y>1)。其D-邻域为以下元素:(x-1,y-1)(x+1,y-1)(x-1,y+1)(x+1,y+1)。

8-邻域:即对于像素(x,y),其中(max-1>x>1,max-1>y>1),上下左右4个元素以及4个对角线像素,称为8-邻域。为以下元素:(x-1,y-1)(x-1,y)(x-1,y+1)(x,y-1)(x,y+1)(x+1,y-1)(x+1,y)(x+1,y+1)

二值图像的邻接

4-邻接:如果q点在p点的4-邻域集合中,则p,q为4-邻接。即互为4-邻域的两个像素叫4-邻接。

8-邻接:如果q点在p点的8-邻域集合中,则p,q为8-邻接。即互为8-邻域的两个像素叫8-邻接。

D-邻接:如果q点在p点的D-邻域集合中,则p,q为D-邻接

m-邻接:如果q在p的4-邻域中,或者q在p的D-邻域中,且q的4-邻域与p的4-邻域交集为空,则p,q为m-邻接。

m-邻域的目的是消除8-邻域的二义性。

联通组件:像素值相同,通过4-领域或8-邻域相互连通的像素块。

联通组件分析过程:

(图片来源于https://edu.csdn.net/learn/38286/608274

  1. (左图)第一行:从左到右,从上到下,扫描白色(前景),像素(0,0)、(0,1)标记为联通块1;(0,2)不联通;(0,3)、(0,4)、(0,5)为新的联通块标为2;(0,6)不通道;(0,7)为新的联通块标为3;

  1. (左图)第二行:(1,0)、(1,1)与上一行联通也标为1,依次类推。

  1. (右图)等价类合并:高标识符与低标识符相联时,将高标识符合为低标识符,2合并为1,6合并为4,7合并为3

ConnectedComponents函数

//函数原型1
int ConnectedComponents(InputArray image,
    OutputArray labels,
    PixelConnectivity connectivity = PixelConnectivity.Connectivity8)

//函数原型2
int ConnectedComponents(InputArray image, 
    out int[,] labels, 
    PixelConnectivity connectivity)

//函数原型3
int ConnectedComponents(InputArray image,
    OutputArray labels,
    PixelConnectivity connectivity,
    MatType ltype)

ConnectedComponents获取不带统计信息的联通组件

返回值(int):返回标签总数N,[0,N-1],0为背景

参数

说明

InputArray image

待标记图像:8位单通道,黑色背景

OutputArray labels

输出标记图像:与输入图像大小一样,对应的联通区域会标记上对应的数字

0为背景,其它数字为对应的联通区域

PixelConnectivity connectivity

通联域:默认是8联通

MatType ltype

输出标记图像的类型:默认是CV_32S,还支持CV_16U

ConnectedComponentsWithStats函数

//函数原型1
int ConnectedComponentsWithStats(InputArray image,
    OutputArray labels,
    OutputArray stats,
    OutputArray centroids,
    PixelConnectivity connectivity,
    MatType ltype)

//函数原型2(ltype=CV_32S)
int ConnectedComponentsWithStats(InputArray image,
    OutputArray labels,
    OutputArray stats,
    OutputArray centroids,
    PixelConnectivity connectivity = PixelConnectivity.Connectivity8)

ConnectedComponentsWithStats获取带统计信息的通道组件

返回值(int):返回标签总数N,[0,N-1],0为背景

参数

说明

InputArray image

待标记图像:8位单通道,黑色背景

OutputArray labels

输出标记图像:与输入图像大小一样,对应的联通区域会标记上对应的数字

0为背景,其它数字为对应的联通区域

OutputArray stats

各通道组件信息(含背景):N*5*ltype

对应各个通道组件的外接矩形的x,y,width,height和像素点个数

OutputArray centroids

通道组件中心点位置:N*2*CV_64F

PixelConnectivity connectivity

通联域:默认是8联通

MatType ltype

输出标记图像的类型:默认是CV_32S,还支持CV_16U

ConnectedComponentsWithAlgorithm可指定算法的不带统计通道组件获取

//函数原型,多了ccltype参数,可指定通道组件分析算法,其它与ConnectedComponents相同
int ConnectedComponentsWithAlgorithm(InputArray image,
    OutputArray labels,
    PixelConnectivity connectivity,
    MatType ltype,
    ConnectedComponentsAlgorithmsTypes ccltype)

ConnectedComponentsWithStatsWithAlgorithm可指定算法的带统计通道组件获取

//函数原型,多了ccltype参数,可指定通道组件分析算法,其它与ConnectedComponentsWithStats相同
int ConnectedComponentsWithStatsWithAlgorithm(InputArray image,
    OutputArray labels,
    OutputArray stats,
    OutputArray centroids,
    PixelConnectivity connectivity,
    MatType ltype,
    ConnectedComponentsAlgorithmsTypes ccltype)

ConnectedComponentsEx对ConnectedComponentsWithStatsWithAlgorithm封装

该函数是OpenCvSharp特有的?使用ConnectedComponents的Blob属性访问更便捷。

//函数源码
public static ConnectedComponents ConnectedComponentsEx(InputArray image,
    PixelConnectivity connectivity = PixelConnectivity.Connectivity8,
    ConnectedComponentsAlgorithmsTypes ccltype = ConnectedComponentsAlgorithmsTypes.Default)
{
    using Mat<int> mat = new Mat<int>();
    using Mat<int> mat2 = new Mat<int>();
    using Mat<double> mat3 = new Mat<double>();
    int num = ConnectedComponentsWithStatsWithAlgorithm(image, mat, mat2, mat3, connectivity, 4, ccltype);
    int[,] labels = mat.ToRectangularArray();
    int[,] array = mat2.ToRectangularArray();
    double[,] array2 = mat3.ToRectangularArray();
    ConnectedComponents.Blob[] array3 = new ConnectedComponents.Blob[num];
    for (int i = 0; i < num; i++)
    {
        array3[i] = new ConnectedComponents.Blob
        {
            Label = i,
            Left = array[i, 0],
            Top = array[i, 1],
            Width = array[i, 2],
            Height = array[i, 3],
            Area = array[i, 4],
            Centroid = new Point2d(array2[i, 0], array2[i, 1])
        };
    }

    return new ConnectedComponents(array3, labels, num);
}

源码示例

public void Run(ParamBase paramBase)
{
    using var srcGray = Cv2.ImRead(ImagePath.Shapes, ImreadModes.Grayscale);
    if (srcGray.Empty()) throw new Exception("图像读取有误");
    Cv2.ImShow("srcGray", srcGray);

    //需要去除噪声的话,可应用相关的模糊函数
    Cv2.GaussianBlur(srcGray, srcGray, new Size(3, 3), 0);
    //用大律法二值化
    Cv2.Threshold(srcGray, srcGray, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

    #region ConnectedComponents相关
    //通道组件标记
    using var labels = new Mat();
    //componentsCount=实际联通区域个数+1(背景)
    //labels大小与srcGray,在相同的联通区域标记为对应的数字(1至N-1)
    var componentsCount = Cv2.ConnectedComponents(srcGray, labels, PixelConnectivity.Connectivity8, MatType.CV_32S);
    //Cv2.ConnectedComponentsWithAlgorithm

    //生成随机颜色填充颜色
    List<Vec3b> colors = new List<Vec3b>();
    for (int i = 0; i < componentsCount; i++)
    {
        colors.Add(Scalar.RandomColor().ToVec3b());
    }
    //用于绘制结果
    Mat colorResult = Mat.Zeros(labels.Size(), MatType.CV_8UC3);
    for (int row = 0; row < labels.Rows; row++)
    {
        for (int col = 0; col < labels.Cols; col++)
        {
            //注意类型必须与labels.MatType一致
            var color = labels.At<Int32>(row, col);//CV_32S
            //var color = labels.At<Int16>(row, col);//CV_16U

            if (color == 0) continue;//为0是背景
            colorResult.At<Vec3b>(row, col) = colors[color];
        }
    }
    Cv2.ImShow("ColorResult:ConnectedComponents", colorResult);
    #endregion

    #region ConnectedComponentsWithStats相关
    //各通道组件外接矩形信息(含背景)
    using var stats = new Mat();
    //各通道组件中心点信息(含背景)
    using var centroids = new Mat();
    componentsCount = Cv2.ConnectedComponentsWithStats(srcGray, labels, stats, centroids, PixelConnectivity.Connectivity8, MatType.CV_32S);
    //Cv2.ConnectedComponentsWithStatsWithAlgorithm

    colorResult = srcGray.CvtColor(ColorConversionCodes.GRAY2BGR);
    for (int i = 1; i < componentsCount; i++)
    {
        //通道组件的中心点
        Cv2.Circle(colorResult, new Point(centroids.At<double>(i, 0), centroids.At<double>(i, 1)), 2, Scalar.Blue, -1);
        //通道组件的外接矩形
        Cv2.Rectangle(colorResult, new Rect(stats.At<int>(i, 0), stats.At<int>(i, 1), stats.At<int>(i, 2), stats.At<int>(i, 3)), Scalar.Red);
    }
    Cv2.ImShow("ColorResult:ConnectedComponentsWithStats", colorResult);
    #endregion

    #region ConnectedComponentsEx对ConnectedComponentsWithStatsWithAlgorithm封装
    var componentsEx = Cv2.ConnectedComponentsEx(srcGray, PixelConnectivity.Connectivity8, ConnectedComponentsAlgorithmsTypes.Default);
    colorResult = srcGray.CvtColor(ColorConversionCodes.GRAY2BGR);
    foreach (var blob in componentsEx.Blobs)
    {
        //背景跳过
        if (blob.Label == 0) continue;
        //通道组件的中心点
        Cv2.Circle(colorResult, blob.Centroid.ToPoint(), 2, Scalar.Blue, -1);
        //通道组件的外接矩形
        Cv2.Rectangle(colorResult, blob.Rect, Scalar.Red);
    }
    Cv2.ImShow("ColorResult:ConnectedComponentsEx", colorResult);
    #endregion

    Cv2.WaitKey();
    Cv2.DestroyAllWindows();
}

OpenCvSharp函数示例(目录)

参考

https://edu.csdn.net/learn/38286/608274

https://docs.opencv.org/

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: opencv中的mat::zeros函数是用来创建一个指定大小和类型的全零矩阵的函数。它的语法如下: cv::Mat cv::Mat::zeros(int rows, int cols, int type) 其中,rows和cols分别表示矩阵的行数和列数,type表示矩阵的类型,可以是CV_8UC1、CV_8UC3、CV_32FC1等等。函数返回一个指定大小和类型的全零矩阵。 ### 回答2: opencv中的mat::zeros函数是一个用于创建一个指定大小和类型的矩阵的函数。该函数的原型如下: Mat cv::Mat::zeros(int rows, int cols, int type) 其中,rows表示矩阵的行数,cols表示矩阵的列数,type表示矩阵的数据类型,常用的数据类型包括CV_8U、CV_8S、CV_16U、CV_16S、CV_32S、CV_32F、CV_64F等。该函数返回一个新创建的矩阵,初始化所有元素为0。 使用Mat::zeros函数可以快速创建一个指定大小和类型的矩阵,并且初始化为0,而不用手动遍历矩阵并设置每个元素的值。这在一些图像处理的操作中非常有用,例如在创建掩膜矩阵时,可以使用该函数创建一个大小和图像一样的全零矩阵,然后在需要的位置设置为1或其他值。 下面是一个示例代码,使用mat::zeros函数创建了一张大小为512x512,类型为CV_8UC1的全零图像: Mat img = Mat::zeros(512, 512, CV_8UC1); 需要注意的是,mat::zeros函数创建的矩阵所有元素的值都是0,而不是默认值。如果需要创建一个矩阵并且初始化为其它默认值,可以使用其重载函数,例如: Mat img = Mat::zeros(512, 512, CV_8UC3); Mat img2 = Mat::zeros(Size(512, 512), CV_8UC3); Mat img3 = Mat::zeros(img.size(), img.type()); 其中,img2使用了Size类型来指定矩阵的大小,img3则使用现有的矩阵来指定矩阵的大小和类型。 ### 回答3: opencv中的mat::zeros函数是用于创建一个具有指定行数、列数和类型的矩阵,并将所有像素的值设置为0的函数。这个函数可以创建单通道或多通道的矩阵,可以是8位、16位、32位或64位浮点型,也可以是8位、16位或32位整数型。该函数返回一个与所创建矩阵相同类型的空矩阵。 该函数有两种格式,第一种格式是: Mat dst = Mat::zeros(int rows, int cols, int type); 参数说明: rows:矩阵的行数; cols:矩阵的列数; type:矩阵的类型,包括如下几种: CV_8U:8位无符号整数型; CV_8S:8位有符号整数型; CV_16U:16位无符号整数型; CV_16S:16位有符号整数型; CV_32S:32位有符号整数型; CV_32F:32位浮点型; CV_64F:64位浮点型。 第二种格式是: void cv::Mat::zeros(InputArray _src, Scalar value=Scalar::all(0)) 参数说明: _src:矩阵,用于接收零矩阵; value:可选的参数,用于设置矩阵像素的值,默认值为Scalar::all(0),即所有像素设置为0。 总之,mat::zeros函数是一种非常方便的创建空矩阵并初始化像素值的方法。它可以用于图像处理、计算机视觉、机器学习等众多领域。在许多opencv应用中,需要先创建一个空矩阵,并将其作为输出参数传递给其他函数。因此,mat::zeros函数可以简化代码,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图南科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值