精华内容
下载资源
问答
  • 图像中,已知了某连通域的一个像素点,如何根据该像素点确定像素点所在的连通域(比如图像中有多个连通域,而现在只知一个连通域像素点,如何根据该点反推像素点所在的连通域,并标记出来)
  • Matlab实现连通域标记算法求图像连通域连通域连通域标记算法 连通域 连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Region,Blob)。连通区域分析(Connected...

    Matlab实现连通域标记算法求图像连通域

    连通域

    连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Region,Blob)。连通区域分析(Connected Component Analysis,Connected Component Labeling)是指将图像中的各个连通区域找出并标记。
    连通区域分析是一种在CVPR和图像分析处理的众多应用领域中较为常用和基本的方法。例如:OCR识别中字符分割提取(车牌识别、文本识别、字幕识别等)、视觉跟踪中的运动前景目标分割与提取(行人入侵检测、遗留物体检测、基于视觉的车辆检测与跟踪等)、医学图像处理(感兴趣目标区域提取)、等等。也就是说,在需要将前景目标提取出来以便后续进行处理的应用场景中都能够用到连通区域分析方法,通常连通区域分析处理的对象是一张二值化后的图像。

    连通域标记算法

    选用图像:
    在这里插入图片描述

    A=imread('d:\Temp\test.png');
    [m,n]=size(A);
    B=zeros(m,n);%标记矩阵
    label=1; %不同连通域标记值
    q=zeros(9999,2);%模拟队列
    head=1;
    tail=1;
    neighbour=[-1,-1;-1,0;-1,1;0,-1;0,1;1,-1;1,0;1,1];  %与某像素点相加得到该像素点的邻域像素点
    
    for j=1:n
        for i=1:m
            if A(i,j)~=0&&B(i,j)==0
                B(i,j)=label;
                q(tail,:)=[i,j]; %用元组模拟队列,当前坐标入列
                tail=tail+1;
                
                while head~=tail  %该循环由连通域中一像素点得到一整个连通域
                    pix=q(head,:);
                    for k=1:8
                        pix1=pix+neighbour(k,:);
                        if pix1(1)>=1&&pix1(1)<=m&&pix1(2)>=1&&pix1(2)<=n
                            if A(pix1(1),pix1(2))~=0&&B(pix1(1),pix1(2))==0
                                B(pix1(1),pix1(2))=label;
                                q(tail,:)=[pix1(1) pix1(2)];
                                tail=tail+1;
                            end
                        end
                    end
                    head=head+1;
                end
                label=label+1;
                head=1;
                tail=1;
            end
        end
    end
    imshow(mat2gray(B));
    
    
    

    代码效果:
    在这里插入图片描述

    展开全文
  • 二值图像连通域二值图像分析最基础的也是最重要的方法之一就是连通域标记,它是所有二值图像分析的基础。它通过对二值图像中目标像素的标记,让每个单独的连通区域形成一个被标识的块,进一步的我们就可以获取这些块...

    二值图像连通域

    二值图像分析最基础的也是最重要的方法之一就是连通域标记,它是所有二值图像分析的基础。它通过对二值图像中目标像素的标记,让每个单独的连通区域形成一个被标识的块,进一步的我们就可以获取这些块的轮廓、外接矩形、质心、不变矩等几何参数。

    连通区域的定义一般有两种,分为4邻接和8邻接。下面这幅图中,如果考虑4邻接,则有3个连通域,8邻接则是2个连通域。

    从连通区域的定义可以知道,一个连通域是由具有相同像素值的相邻像素组成像素集合,因此,我们就可以通过这两个条件在图像中寻找连通区域,对于找到的每个连通域,我们赋予其一个唯一的标识( Label ),以区别其他连通域。

    连通域分析的基本算法有两种: 1) Two-Pass 两遍扫描 2) Seed-Filling 种子填充法。

    Two-Pass 算法

    两遍扫描法( Two-Pass ),正如其名,指的就是通过扫描两遍图像,将图像中存在的所有连通域找出并标记。

    (1)第一次扫描:

    访问当前像素 B(x,y) ,如果 B(x,y) == 1:

    a、如果 B(x,y) 的领域中标签值都为0,则赋予 B(x,y) 一个新的 label :

    label += 1, B(x,y) = label;

    b、如果B(x,y)的领域中有像素值 > 1的像素Neighbors:

    1)将Neighbors中的最小值赋予给 B(x,y) :

    B(x,y) = min{Neighbors}

    2)记录Neighbors中各个值(label)之间的相等关系,即这些值(label)同属同一个连通区域;

    (2)第二次扫描:

    访问当前像素 B(x,y) ,如果 B(x,y) > 1:

    a、找到与 label = B(x,y) 同属相等关系的一个最小 label 值,赋予给 B(x,y) ;

    完成扫描后,图像中具有相同 label 值的像素就组成了同一个连通区域。

    另外,我在代码实现的过程中想到另外一种 Two-Pass 的方式(即扫描两遍图像的方式)实现,就是第二次扫描与 (1) 同样的过程,只是方向换成从右下到左上。我后面的 Two-Pass 代码是使用我自己想到的方法实现的,自己使用了几个例子测试了下,目前没出现啥问题。

    Seed-Filling 算法

    种子填充方法来源于计算机图形学,常用于对某个图形进行填充。它基于区域生长算法。我的理解就是递归遍历。

    附上两种方法的 Python 的实现

    import cv2

    import numpy as np

    # 4邻域的连通域和 8邻域的连通域

    # [row, col]

    NEIGHBOR_HOODS_4 = True

    OFFSETS_4 = [[0, -1], [-1, 0], [0, 0], [1, 0], [0, 1]]

    NEIGHBOR_HOODS_8 = False

    OFFSETS_8 = [[-1, -1], [0, -1], [1, -1],

    [-1, 0], [0, 0], [1, 0],

    [-1, 1], [0, 1], [1, 1]]

    def reorganize(binary_img: np.array):

    index_map = []

    points = []

    index = -1

    rows, cols = binary_img.shape

    for row in range(rows):

    for col in range(cols):

    var = binary_img[row][col]

    if var < 0.5:

    continue

    if var in index_map:

    index = index_map.index(var)

    num = index + 1

    else:

    index = len(index_map)

    num = index + 1

    index_map.append(var)

    points.append([])

    binary_img[row][col] = num

    points[index].append([row, col])

    return binary_img, points

    def neighbor_value(binary_img: np.array, offsets, reverse=False):

    rows, cols = binary_img.shape

    label_idx = 0

    rows_ = [0, rows, 1] if reverse == False else [rows-1, -1, -1]

    cols_ = [0, cols, 1] if reverse == False else [cols-1, -1, -1]

    for row in range(rows_[0], rows_[1], rows_[2]):

    for col in range(cols_[0], cols_[1], cols_[2]):

    label = 256

    if binary_img[row][col] < 0.5:

    continue

    for offset in offsets:

    neighbor_row = min(max(0, row+offset[0]), rows-1)

    neighbor_col = min(max(0, col+offset[1]), cols-1)

    neighbor_val = binary_img[neighbor_row, neighbor_col]

    if neighbor_val < 0.5:

    continue

    label = neighbor_val if neighbor_val < label else label

    if label == 255:

    label_idx += 1

    label = label_idx

    binary_img[row][col] = label

    return binary_img

    # binary_img: bg-0, object-255; int

    def Two_Pass(binary_img: np.array, neighbor_hoods):

    if neighbor_hoods == NEIGHBOR_HOODS_4:

    offsets = OFFSETS_4

    elif neighbor_hoods == NEIGHBOR_HOODS_8:

    offsets = OFFSETS_8

    else:

    raise ValueError

    binary_img = neighbor_value(binary_img, offsets, False)

    binary_img = neighbor_value(binary_img, offsets, True)

    return binary_img

    def recursive_seed(binary_img: np.array, seed_row, seed_col, offsets, num, max_num=100):

    rows, cols = binary_img.shape

    binary_img[seed_row][seed_col] = num

    for offset in offsets:

    neighbor_row = min(max(0, seed_row+offset[0]), rows-1)

    neighbor_col = min(max(0, seed_col+offset[1]), cols-1)

    var = binary_img[neighbor_row][neighbor_col]

    if var < max_num:

    continue

    binary_img = recursive_seed(binary_img, neighbor_row, neighbor_col, offsets, num, max_num)

    return binary_img

    # max_num 表示连通域最多存在的个数

    def Seed_Filling(binary_img, neighbor_hoods, max_num=100):

    if neighbor_hoods == NEIGHBOR_HOODS_4:

    offsets = OFFSETS_4

    elif neighbor_hoods == NEIGHBOR_HOODS_8:

    offsets = OFFSETS_8

    else:

    raise ValueError

    num = 1

    rows, cols = binary_img.shape

    for row in range(rows):

    for col in range(cols):

    var = binary_img[row][col]

    if var <= max_num:

    continue

    binary_img = recursive_seed(binary_img, row, col, offsets, num, max_num=100)

    num += 1

    return binary_img

    if __name__ == "__main__":

    binary_img = np.zeros((4, 7), dtype=np.int16)

    index = [[0, 2], [0, 5],

    [1, 0], [1, 1], [1, 2], [1, 4], [1, 5], [1, 6],

    [2, 2], [2, 5],

    [3, 1], [3, 2], [3, 4], [3, 6]]

    for i in index:

    binary_img[i[0], i[1]] = np.int16(255)

    print("原始二值图像")

    print(binary_img)

    print("Two_Pass")

    binary_img = Two_Pass(binary_img, NEIGHBOR_HOODS_8)

    binary_img, points = reorganize(binary_img)

    print(binary_img, points)

    print("Seed_Filling")

    binary_img = Seed_Filling(binary_img, NEIGHBOR_HOODS_8)

    binary_img, points = reorganize(binary_img)

    print(binary_img, points)

    展开全文
  • opencv连通域

    2020-11-25 20:50:41
    图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找彼此相互独立的连通域并将其标记出来。提取图像中不同的连通域是图像中较为常用的方法。例如在车牌识别、文字识别、...

    opencv连通域学习

    连通域

    图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找彼此相互独立的连通域并将其标记出来。提取图像中不同的连通域是图像中较为常用的方法。例如在车牌识别、文字识别、目标检测等领域对感兴趣区域分割与识别。一般情况下,一个连通域内只包含一个像素值,因此为了防止像素值波动对提取不同连通域的影响,连通域分析常处理的是二值化后的图像。

    图像中两个像素相邻有两种定义方式,分别是4-领域和8-领域。根据两个像素相邻的定义方式不同,得到的连通域也不相同,因此在分析连通域的同时,一定要声明是在哪种领域条件下分析得到的结果。
    在这里插入图片描述

    常用的图像领域分析法有两遍扫描法和种子填充法。两遍扫描法会遍历两次图像,第一次遍历图像时会给每个非0像素赋予一个数字标签,当某个像素的上方和左侧领域内的像素已经有数字标签时,取两者中的最小值作为当前像素的标签,否则赋予当前像素一个新的数字标签。第一次遍历图像的时候同一个连通域可能会被赋予一个或者多个不同的标签,如下图所示,因此第二次遍历需要将这些属于同一个连通域的不同标签合并,最后实现同一个领域内的所有像素具有相同的标签。
    在这里插入图片描述
    种子填充法源于计算机图像学,常用于对某些图形进行填充。该方法首先将所有非0像素放到一个集合中,之后在集合中随机选出一个像素作为种子像素,根据领域关系不断扩充种子像素所在的连通域,并在集合中删除掉扩充出的像素,直到种子像素所在的连通域无法扩充,之后再从集合中随机选取一个像素作为新的种子像素,重复上述过程直到集合中没有像素。

    opencv4提供了用于提取图像中不同连通域的connectedComponents()函数,该函数用于计算二值图像中连通域的个数,并在图像中将不同的连通域用不同的数字标签标记出来,其中标签0表示图像中的背景区域,同时函数具有一个int类型的返回数据,用于表示图像中连通域的数目。函数的第一个参数时待标记连通域的输入图像,函数要求输入图像必须是数据类型为CV_8U的单通道灰度图像,而且最好是经过二值化的二值图像。函数第二个参数是标记连通域后的输出图像,图像尺寸与第一个参数的输入图像尺寸相同,图像的数据类型与函数的第四个参数相关。函数第三个参数是统计连通域时选择的领域种类,函数支持两种领域,分别用4表示4-领域,8表示8-领域。函数第四个参数为输出图像的数据类型,可以选择的参数为CV_32和CV_16U两种。函数的最后一个参数时标记连通域时使用算法的标志,目前只支持Grana(BBDT)和Wu(SAUF)两种算法。

    上述函数原型的所有参数都没有默认值,在调用时需要设置全部参数,增加了使用的复杂程度,因此opencv4提供了connectedComponents()函数的简易原型,减少了参数数量以及部分参数增加了默认。

    展开全文
  • 图像连通域连通域图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。提取图像中不同的连通域是图像处理中较为常用的方法,例如...

    图像连通域

    连通域

    图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,

    连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。

    提取图像中不同的连通域是图像处理中较为常用的方法,例如在车牌识别、文字识别、目标检测等领域对感兴趣区域分割与识别。一般情况下,一个连通域内只包含一个像素值,因此为了防止像素值波动对提取不同连通域的影响,连通域分析常处理的是二值化后的图像

    邻域

    邻域,与指定元素相邻的像素集合。常用的有4邻域和8邻域。

    b22482f4ee5b15146750f5e166377675.png

    如果像素点A与B邻接,我们称A与B连通,于是我们不加证明的有如下的结论:如果A与B连通,B与C连通,则A与C连通。

    在视觉上看来,彼此连通的点形成了一个区域,而不连通的点形成了不同的区域。这样的一个所有的点彼此连通点构成的集合,我们称为一个连通区域。下面这副图中,如果考虑4邻接,则有3个连通区域;如果考虑8邻接,则有2个连通区域。(注:图像是被放大的效果,图像正方形实际只有4个像素)。

    97555398b76afc59c332f93f3b169f1a.png
    示例

    连通区域分析方法

    两遍扫描法(Two-Pass)

    两遍扫描法会遍历两次图像,第一次遍历图像时会给每一个非0像素赋予一个数字标签,当某个像素的上方和左侧邻域内的像素已经有数字标签时,取两者中的最小值作为当前像素的标签,否则赋予当前像素一个新的数字标签。第一次遍历图像的时候同一个连通域可能会被赋予一个或者多个不同的标签,因此第二次遍历需要将这些属于同一个连通域的不同标签合并,最后实现同一个邻域内的所有像素具有相同的标签。

    1. 第一次扫描:

    • 如果 B(x,y) 的领域中标签值都为0,则赋予 B(x,y) 一个新的 label :label += 1, B(x,y) = label;
    • 如果B(x,y)的邻域中有像素值 > 1的像素Neighbors:将Neighbors中的最小值赋予给 B(x,y) :B(x,y) = min{Neighbors}
    • 访问当前像素 B(x,y) ,如果 B(x,y) == 1:
    • 记录Neighbors中各个值(label)之间的相等关系,即这些值(label)同属同一个连通区域;

    第二次扫描:

    • 访问当前像素 B(x,y) ,如果 B(x,y) > 1:找到与 label = B(x,y) 同属相等关系的一个最小 label 值,赋予给 B(x,y)
    • 完成扫描后,图像中具有相同 label 值的像素就组成了同一个连通区域。

    第一遍过程:

    34cbb4a765ad5d891221e1d2213a5d45.gif
    第一遍过程

    第一遍结束后,我们可以得到一个[1,2,3]的集合,来证明集合内的标签属于同一连通区域。

    第二遍过程,则是将同一连通区域内的标签合并,使每个连通域只有一个标签。

    23d01cdcb87c0a138e43bf5ae41542e3.png

    种子填充法(Seed Filling)

    种子填充法源于计算机图像学,常用于对某些图形进行填充,它基于区域生长算法。该方法首先将所有非0像素放到一个集合中,之后在集合中随机选出一个像素作为种子像素,根据邻域关系不断扩充种子像素所在的连通域,并在集合中删除掉扩充出的像素,直到种子像素所在的连通域无法扩充,之后再从集合中随机选取一个像素作为新的种子像素,重复上述过程直到集合中没有像素。

    1. 扫描图像,直到当前像素点B(x,y)==1:

    • 将B(x,y)作为种子(像素位置),并赋予其一个label,然后将该种子相邻的所有前景像素都压入栈中;

    • 弹出栈顶像素,赋予其相同的label,然后再将与该栈顶像素相邻的所有前景像素都压入栈中;

    • 重复上一步操作,直到栈为空;

      (此时,便找到了图像B中的一个连通区域,该区域内的像素值被标记为label)

    重复第(1)步,直到扫描结束;

    基本操作流程:

    0fbc159dfb4561b89d24a18ac7306cc5.gif
    种子填充法

    API

    connectedComponents

    public static int connectedComponents(Mat image, Mat labels, int connectivity, int ltype)

    参数一:image,待标记的单通道图像,数据类型必须为CV_8U。

    参数二:labels,标记连通域后的输出图像,与输入图像具有相同的尺寸。

    参数三:connectivity,标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域。

    参数四:ltype,输出图像的数据类型,目前支持CV_32S和CV_16U两种数据类型。

    public static int connectedComponents(Mat image, Mat labels)
    public static int connectedComponents(Mat image, Mat labels, int connectivity)

    以上为两个简易函数,省略的参数 :connectivity = 8ltype = CV_32S

    connectedComponentsWithAlgorithm

    public static int connectedComponentsWithAlgorithm(Mat image, Mat labels, int connectivity, int ltype, int ccltype)

    参数一:image,待标记的单通道图像,数据类型必须为CV_8U。

    参数二:labels,标记连通域后的输出图像,与输入图像具有相同的尺寸。

    参数三:connectivity,标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域。

    参数四:ltype,输出图像的数据类型,目前支持CV_32S和CV_16U两种数据类型。

    参数五:ccltype,标记连通域时使用的算法类型标志。

    //! connected components algorithm
    enum ConnectedComponentsAlgorithmsTypes {
        CCL_WU      = 0,  //!
        CCL_DEFAULT = -1//!
        CCL_GRANA   = 1   //!
    };

    connectedComponentsWithStats

    该函数能够在图像中不同连通域标记标签的同时统计每个连通域的中心位置、矩形区域大小。

    public static int connectedComponentsWithStats(Mat image, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype)

    参数一:image,待标记的单通道图像,数据类型必须为CV_8U。

    参数二:labels,标记连通域后的输出图像,与输入图像具有相同的尺寸。

    参数三:stats,每个标签(包括背景标签)的统计信息输出。通过stats(label, COLUMN)来访问对应的信息。数据类型为 CV_32S。COLUMN的类型如下:

    // C++: enum ConnectedComponentsTypes
    public static final int
    CC_STAT_LEFT = 0,
    CC_STAT_TOP = 1,
    CC_STAT_WIDTH = 2,
    CC_STAT_HEIGHT = 3,
    CC_STAT_AREA = 4,
    CC_STAT_MAX = 5;

    参数四:centroids,每个标签(包括背景标签)的中心点。X轴坐标与Y轴左边分别用centroids(label,0)和centroids(label,1)访问。数据类型为CV_64F

    参数五:connectivity,标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域。

    参数六:ltype,输出图像的数据类型,目前支持CV_32S和CV_16U两种数据类型。

    参数七:ccltype,标记连通域时使用的算法类型标志。

    connectedComponentsWithStatsWithAlgorithm

    public static int connectedComponentsWithStatsWithAlgorithm(Mat image, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype, int ccltype)

    参数基本同上,只是多出了connectedComponentsWithAlgorithm方法中最后一个算法类型的参数。

    操作

    /**
     * 连通域分析
     * author: yidong
     * 2020/6/7
     */

    class ConnectedComponentsActivity : AppCompatActivity() {
        private lateinit var mBinding: ActivityConnectedComponentsBinding
        private lateinit var mBinary: Mat

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mBinding = DataBindingUtil.setContentView(this, R.layout.activity_connected_components)

            val bgr = Utils.loadResource(this, R.drawable.number)
            val gray = Mat()
            Imgproc.cvtColor(bgr, gray, Imgproc.COLOR_BGR2GRAY)
            mBinary = Mat()
            Imgproc.threshold(gray, mBinary, 50.0255.0, Imgproc.THRESH_BINARY)
            showMat(mBinding.ivLena, mBinary)

            bgr.release()
            gray.release()
        }

        private fun showLoading() {
            mBinding.progressBar.show()
        }

        private fun dismissLoading() {
            mBinding.progressBar.hide()
        }

        override fun onCreateOptionsMenu(menu: Menu?)Boolean {
            menuInflater.inflate(R.menu.menu_connected_componenets, menu)
            return true
        }

        override fun onOptionsItemSelected(item: MenuItem)Boolean {
            when (item.itemId) {
                R.id.connected_components -> {
                    connectedComponent()
                }
                R.id.connected_components_with_algorithm_4_wu -> {
                    connectedComponentsWithAlgorithm(4, Imgproc.CCL_WU)
                }
                R.id.connected_components_with_algorithm_8_wu -> {
                    connectedComponentsWithAlgorithm(8, Imgproc.CCL_WU)
                }
                R.id.connected_components_with_algorithm_4_grana -> {
                    connectedComponentsWithAlgorithm(4, Imgproc.CCL_GRANA)
                }
                R.id.connected_components_with_algorithm_8_grana -> {
                    connectedComponentsWithAlgorithm(8, Imgproc.CCL_GRANA)
                }
                R.id.connected_components_with_stats_with_algorithm -> {
                    connectedComponentsWithStatsWithAlgorithm()
                }
            }
            return true
        }

        private fun showMat(view: ImageView, source: Mat) {
            val bitmap = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)
            Utils.matToBitmap(source, bitmap)
            view.setImageBitmap(bitmap)
        }

        private fun connectedComponent() {
            val labels = Mat()
            val count = Imgproc.connectedComponents(mBinary, labels)
            labels.convertTo(labels, CvType.CV_8U)
            showLoading()
            GlobalScope.launch(Dispatchers.IO) {
                drawConnectedComponent(count, labels)
            }
        }

        private fun connectedComponentsWithAlgorithm(connectivity: Int, algorithm: Int) {
            val labels = Mat()
            val count = Imgproc.connectedComponentsWithAlgorithm(
                mBinary,
                labels,
                connectivity,
                CvType.CV_32S,
                algorithm
            )
            labels.convertTo(labels, CvType.CV_8U)
            showLoading()
            GlobalScope.launch(Dispatchers.IO) {
                drawConnectedComponent(count, labels)
            }
        }

        private fun connectedComponentsWithStatsWithAlgorithm() {
            val labels = Mat()
            val stats = Mat()
            val centroids = Mat()
            val labelCount = Imgproc.connectedComponentsWithStatsWithAlgorithm(
                mBinary,
                labels,
                stats,
                centroids,
                8,
                CvType.CV_32S,
                Imgproc.CCL_GRANA
            )
            labels.convertTo(labels, CvType.CV_8U)
            val statList = mutableListOf()for (count in 0 until labelCount) {val stat = Stat(
                    centroids.get(count, 0)?.get(0) ?: 0.0,
                    centroids.get(count, 1)?.get(0) ?: 0.0,
                    stats.get(count, 0)?.get(0)?.toInt() ?: 0,
                    stats.get(count, 1)?.get(0)?.toInt() ?: 0,
                    stats.get(count, 2)?.get(0)?.toInt() ?: 0,
                    stats.get(count, 3)?.get(0)?.toInt() ?: 0,
                    count
                )
                statList.add(stat)
            }
            showLoading()
            GlobalScope.launch(Dispatchers.IO) {
                drawConnectedComponentWithStats(labelCount, labels, statList)
            }
        }private fun drawConnectedComponent(count: Int, labels: Mat) {val result = Mat.zeros(labels.rows(), labels.cols(), CvType.CV_8UC3)val color = arrayListOf()for (index in 0..count) {val scalar = Scalar(
                    (Math.random() * 255) + 1,
                    (Math.random() * 255) + 1,
                    (Math.random() * 255) + 1
                )
                color.add(scalar)
            }for (row in 0..labels.rows()) {for (col in 0..labels.cols()) {val label = labels.get(row, col)?.get(0)?.toInt() ?: 0if (label == 0) {continue
                    } else {
                        result.put(
                            row,
                            col,
                            color[label].`val`[0],
                            color[label].`val`[1],
                            color[label].`val`[2]
                        )
                    }
                }
            }
            GlobalScope.launch(Dispatchers.Main) {
                dismissLoading()
                showMat(mBinding.ivResult, result)
                result.release()
            }
            labels.release()
        }private fun drawConnectedComponentWithStats(
            count: Int,
            labels: Mat,
            statList: MutableList<Stat>
        )
     {val result = Mat.zeros(labels.rows(), labels.cols(), CvType.CV_8UC3)val color = arrayListOf()for (index in 0..count) {val scalar = Scalar(
                    (Math.random() * 255) + 1,
                    (Math.random() * 255) + 1,
                    (Math.random() * 255) + 1
                )
                color.add(scalar)
            }for (row in 0..labels.rows()) {for (col in 0..labels.cols()) {val label = labels.get(row, col)?.get(0)?.toInt() ?: 0if (label == 0) {continue
                    } else {
                        result.put(
                            row,
                            col,
                            color[label].`val`[0],
                            color[label].`val`[1],
                            color[label].`val`[2]
                        )
                    }
                }
            }for (index in 0 until statList.size) {val stat = statList[index]val rect = Rect(stat.left, stat.top, stat.width, stat.height)
                Imgproc.rectangle(result, rect, color[stat.label], 10)
            }
            GlobalScope.launch(Dispatchers.Main) {
                dismissLoading()
                showMat(mBinding.ivResult, result)
                result.release()
            }
            labels.release()
        }
    }

    效果

    fce4e4ccfb552b177e61a13b37627f15.png
    简单标记出连通域
    95e2ada91340a53c1eaa672c2f948a58.png
    根据连通域数据信息,标记出连通域以及矩形边框

    源码

    https://github.com/onlyloveyd/LearningAndroidOpenCV

    展开全文
  • 二值图像连通域二值图像分析最基础的也是最重要的方法之一就是连通域标记,它是所有二值图像分析的基础。它通过对二值图像中目标像素的标记,让每个单独的连通区域形成一个被标识的块,进一步的我们就可以获取这些块...
  • 通过以上函数,确定出二值图片中的一些连通域,接下来通过一些筛选条件,即连通域宽高比的无用连通域过滤掉,想把无用的连通域设置为背景色(黑色)。请问如何将这些区域设置为黑色?????? 已有思路:得到的...
  • 连通域标记

    千次阅读 2017-06-22 14:53:27
       所谓连通域标记,就是将一副二值图像中的每个白色像素进行标记,属于同一个连通域的白色像素标记相同,不同连通域的白色像素有不同的标记,从而能将图像中每个连通域提取出来。    连通域标记的算法有很多...
  • 连通域求解

    千次阅读 2018-03-18 17:25:56
    图像处理中连通域指由前景相同像素,并且相同像素邻接的像素组成的域。图像处理中一般都是对二值图像(1白色,0为黑色,一般前景为0黑色)做连通域分析。连通域分析指把连通域找出来并且标记出来。连通域标记方法:...
  • 1.思路是用深度遍历,对图片进行二值化处理,先找到一个黑色像素,然后对这个像素的周围8个像素进行判断,如果没有访问过,就保存...def cfs(img):"""传入二值化后的图片进行连通域分割"""pixdata = img.load()w,h =...
  • 机器学习AI算法工程 公众号:datayx二值图像连通域二值图像分析最基础的也是最重要的方法之一就是连通域标记,它是所有二值图像分析的基础。它通过对二值图像中目标像素的标记,让每个单独的连通区域形成一个被标识...
  • 连通域分析其实是一个路径搜索问题,搜索方式就看...对他进行连通域搜寻,将搜寻到的整个连通域内的像素点标为2(为了避免与本来的颜色1冲突)继续搜索像素值为1的点(之前联通域分析过的已经将像素值改为大于1的值,...
  • python中验证码连通域分割的方法详解这篇文章主要给大家介绍了关于python中验证码连通域分割的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用python具有一定的参考学习价值,需要的朋友们下面随着小...
  • 连通域分析

    千次阅读 2019-05-23 21:48:11
    连通域分析是指找出图中图像中的各个连通区域并标记。 连通域分析存在两种基本算法,Two-Pass算法,Seed-Filling算法。 Two-Pass算法 目标图像为二值化图像,前景像素为255,背景像素为0 第一遍扫描 访问当前...
  • 实现思路是用深度遍历,对图片进行二值化处理,先找到一个黑色像素,然后对这个像素的周围8个像素进行判断,如果没有访问过,...示例代码def cfs(img):"""传入二值化后的图片进行连通域分割"""pixdata = img.load()w...
  • 实现思路是用深度遍历,对图片进行二值化处理,先找到一个黑色像素,然后对这个像素的周围8个像素进行判断,如果没有访问过,...示例代码def cfs(img):"""传入二值化后的图片进行连通域分割"""pixdata = img.load()w...
  • OpenCV—python 连通域标记

    千次阅读 2020-12-18 15:01:34
    图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。提取图像中不同的连通域是图像处理中较为常用的方法,在目标检测等领域对感...
  • 连通域相关

    2017-02-14 15:05:57
    OpenCV统计米粒数目-计算联通区域的个数及联通区域内像素的个数 ...二值图像连通域标记算法与代码 二值图像连通域标记 二值图像连通区域标记(OpenCV版) 数字图像处理-编程实现染色体计数 C语言实现
  • 这篇文章主要给大家介绍了关于python中验证码连通域分割的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用python具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 实现思路是用...
  • 上一篇我们讲到了MATLAB中的bwlabel连通域标记...简单点说就是每次以一个需要标记的像素点为种子,然后不断向其周围扩散,找出其他的与其相连通的可标记的像素点,这样就能标记出一个连通域,然后再以另一个连通域...
  • 图像处理 连通域标记

    千次阅读 2017-05-12 13:34:22
      所谓连通域标记,就是将一副二值图像中的每个白色像素进行标记,属于同一个连通域的白色像素标记相同,不同连通域的白色像素有不同的标记,从而能将图像中每个连通域提取出来。   连通域标记的算法有很多种,...
  • 四连通就是指一个像素值为1的元素,如果其上下左右任一元素为1,那么这两个元素就属于同一个连通域。 八连通就是指一个像素值为1的元素,如果其上下左右,左上,左下,右上,右下任一元素为1,那么这两个元素就属于...
  • 基本概念在数字图像处理中,有个连通域的概念连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Region,Blob)。在图像中,最小的单位是像素,每个像素周围有 8 ...
  • 基本概念在数字图像处理中,有个连通域的概念连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Region,Blob)。在图像中,最小的单位是像素,每个像素周围有 8 个...
  • python 验证码连通域分割

    千次阅读 2018-06-03 15:49:59
    1.思路是用深度遍历,对图片进行二值化处理,先找到一个黑色像素,然后对这个像素的周围8个像素进行判断,如果没有访问过,就保存起来,...传入二值化后的图片进行连通域分割""" pixdata = img.l...
  • 二值图像在图像分析与识别中有着举足轻重的地位,因为其模式简单,对像素在空间上的关系有着极强的表现力。在实际应用中,很多图像的分析最终都转换为二值图像的分析,比如:医学图像分析、前景检测、字符识别,形状...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 258
精华内容 103
关键字:

像素连通域