【问题标题】:Second pass of the two-pass algorithm (connected components 4- Connectivity)两遍算法的第二遍(连通分量4-连通性)
【发布时间】:2015-01-31 17:58:20
【问题描述】:

我有一个任务,旨在从黑白图像中提取最大的对象,其中黑色是背景。我使用的是 2-pass 算法,这是一个解释它如何工作的链接: http://en.wikipedia.org/wiki/Connected-component_labeling#Two-pass

我的问题: 1.我正在使用一个结构数组,我想将其尺寸定义为与“输入图像”相同,所以{我该怎么做}

2.我制作了一个包含两列和行数的数组作为等价表,但我不确定我是否正确,我该如何解决?

  1. 如何使用等价表“重新标记第二遍中的像素?如何编写第二遍的代码?

我的代码:

Image Image::MaxCC()
{
    Image obj;
    obj.height = height;
    obj.width = width;
    short ** original = image;
    short ** output = new short*[height];

    for (int i = 0; i < height; i++)
    {
        output[i] = new short[width];
    }
    obj.imageHeader = imageHeader;
    obj.image = output;

    //label array
    //structure 
    struct label
    {
        int lab;
        int counter;
    };

    label L[][]; //I want to use the dimensions of the input image which is obj.height and obj.width

    //Initialize 

    for (int i = 0; i <= obj.height; i++)
    {
        for (int j = 0; j <= obj.width; j++)
        {
            L[i][j].lab = 0;
            L[i][j].counter = 0;
        }
    }
     int N = 0;
     int count = 0;

     //equivlance tabel 
     int eq[100][2];
     int row = 1;
     int x = 1;
     int s;

// conditions [FIRST ITERATION]
    for (int c = 0; c < obj.width; c++)
    {
        for (int r = 0; r < obj.height; r++)
        {
            // If the pixel is balck , add no label
            if (image[r][c] == 0)
                obj.image[r][c] = 0;

            //Do the pixel's North and West neighbors have different pixel values than current pixel?
            else if (image[r - 1][c] == 0 && image[r][c - 1] == 0)
            {
                L[r][c].lab = N++;
                L[r][c].counter = count++;
                obj.image[r][c] = L[r][c].lab;

            }

            //Does the pixel to the left (West) have the same value as the current pixel?
            else if (image[r][c - 1] == image[r][c])
            {
                L[r][c - 1].counter = count++;
                obj.image[r][c] = L[r][c - 1].lab;

            }

            //Does the pixel to the left (West) have a different value and the one to the North the same value as the current pixel?
            else if (image[r - 1][c] == image[r][c] && image[r][c - 1] != image[r][c])
            {
                L[r - 1][c].counter = count++;
                obj.image[r][c] = L[r - 1][c].lab;
            }

            //Do both pixels to the North and West have the same value as the current pixel but not the same label?
            else if (image[r - 1][c] == image[r][c] && image[r][c - 1] == image[r][c] && L[r - 1][c].lab != L[r][c - 1].lab)
            {
                obj.image[r][c] = L[r - 1][c].lab;
                eq[row][1] = x;
                if (L[r - 1][c].counter << L[r][c - 1].counter)
                {
                    L[r - 1][c].counter = count++; 
                    s = L[r - 1][c].lab;

                }
                else
                {
                    L[r][c - 1].counter = count++;
                    s = L[r][c - 1].lab;
                    eq[row][2] = s;  //..
                    x++; row++;
                }
            }

        }

        //THE SECONF ITERATION ?

        //Iteration to get the maximum counter
        label max;
        int temp;

        for (int c = 0; c < obj.width; c++)
        {
            for (int r = 0; r < obj.height; c++)
            {
                temp = L[r][c].counter;
                if (temp > max.counter)
                    max.counter = temp;
            }
        }
            //iteratio to extract the bigger object
            for (int c = 0; c < obj.width; c++)
            {
                for (int r = 0; r < obj.height; c++)
                {
                    if (max.lab == L[r][c].lab)
                        obj.image[r][c] = 255;
                    else
                        obj.image[r][c] = 0;
                }
            }

    }

    return obj;

}

【问题讨论】:

    标签: c++ arrays image-processing connected-components


    【解决方案1】:

    我还为两遍算法编写了 python 代码,并查找是否有任何与您的需求相关的内容。

    from PIL import Image, ImageOps
    %pylab inline
    
    import sys
    import random
    import numpy
    
    
    def colourize(img):
        height, width = img.shape
    
        colors = []
        colors.append([])
        colors.append([])
        color = 1
        # Displaying distinct components with distinct colors
        coloured_img = Image.new("RGB", (width, height))
        coloured_data = coloured_img.load()
    
        for i in range(len(img)):
            for j in range(len(img[0])):
                if img[i][j] > 0:
                    if img[i][j] not in colors[0]:
                        colors[0].append(img[i][j])
                        colors[1].append((random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
    
                    ind = colors[0].index(img[i][j])
                    coloured_data[j, i] = colors[1][ind]
    
        return coloured_img
    
    
    def binarize(img_array, threshold=130):
        for i in range(len(img_array)):
            for j in range(len(img_array[0])):
                if img_array[i][j] > threshold:
                    img_array[i][j] = 0
                else:
                    img_array[i][j] = 1
        return img_array
    
    
    def ccl4(img_array):
        ##### first pass #####
        print ("starting first pass")
        curr_label = 1;
        img_array = numpy.array(img_array)
        labels = numpy.array(img_array)
    
        # storing label conversions
        label_conv = []
        label_conv.append([])
        label_conv.append([])
    
        count = 0
        for i in range(1, len(img_array)):
            for j in range(1, len(img_array[0])):
    
                if img_array[i][j] > 0:
                    label_x = labels[i][j - 1]
                    label_y = labels[i - 1][j]
    
                    if label_x > 0:
                        # both x and y have a label
                        if label_y > 0:
    
                            if not label_x == label_y:
                                labels[i][j] = min(label_x, label_y)
                                if max(label_x, label_y) not in label_conv[0]:
                                    label_conv[0].append(max(label_x, label_y))
                                    label_conv[1].append(min(label_x, label_y))
                                elif max(label_x, label_y) in label_conv[0]:
                                    ind = label_conv[0].index(max(label_x, label_y))
                                    if label_conv[1][ind] > min(label_x, label_y):
                                        l = label_conv[1][ind]
                                        label_conv[1][ind] = min(label_x, label_y)
                                        while l in label_conv[0] and count < 100:
                                            count += 1
                                            ind = label_conv[0].index(l)
                                            l = label_conv[1][ind]
                                            label_conv[1][ind] = min(label_x, label_y)
    
                                        label_conv[0].append(l)
                                        label_conv[1].append(min(label_x, label_y))
    
                            else:
                                labels[i][j] = label_y
                        # only x has a label
                        else:
                            labels[i][j] = label_x
    
                    # only y has a label
                    elif label_y > 0:
                        labels[i][j] = label_y
    
                    # neither x nor y has a label
                    else:
                        labels[i][j] = curr_label
                        curr_label += 1
    
                        ##### second pass #####
        print ("starting second pass")
        count = 1
        for idx, val in enumerate(label_conv[0]):
    
            if label_conv[1][idx] in label_conv[0] and count < 100:
                count += 1
                ind = label_conv[0].index(label_conv[1][idx])
                label_conv[1][idx] = label_conv[1][ind]
    
        for i in range(1, len(labels)):
            for j in range(1, len(labels[0])):
    
                if labels[i][j] in label_conv[0]:
                    ind = label_conv[0].index(labels[i][j])
                    labels[i][j] = label_conv[1][ind]
    
        return labels
    
    
    def main():
        numpy.set_printoptions(threshold=sys.maxsize)
        # Open the image
        img = Image.open("./image1.png")
    
        # Threshold the image
        img = img.convert('L')
        img = ImageOps.expand(img, border=1, fill='white')
        img = numpy.array(img)
        img = binarize(img)
    
        
    
        img = ccl4(img)
    
        # Colour the image using labels
        coloured_img = colourize(img)
    
        # Show the coloured image
        coloured_img.show()
        
    
    
    if __name__ == "__main__": main()
    

    【讨论】:

      【解决方案2】:

      部分代码丢失,因此我做出以下假设:heightwidthimage 是类 Image 的成员。

      关于您的问题:

      1.我正在使用一个结构数组,我想将其尺寸定义为与“输入图像”相同,所以{我该怎么做 }

      label L[][]; //I want to use the dimensions of the input image which is obj.height and obj.width
      

      为什么不把它声明为指针的指针,就像你对输出所做的那样,即:

      label ** L = new label*[height];
      for (int i = 0; i < height; i++)
      {
         L[i] = new label[width];
      }
      

      2.我制作了一个包含两列和行数的数组作为等价表,但我不确定我是否正确,我该如何解决?

      关于不相交集数据结构,我认为数组应该能够动态增长(理论上是无限期的,所以我不会使用静态大小)。我建议你看看,并了解一些现有的实现(这里有一个在C++,另一个在python),然后在你理解它们之后实现你的。

      编辑:我刚刚在SO 上找到了另一个实现。

      1. 如何使用等价表“重新标记 第二遍?怎么写第二遍的代码?

      据我了解,该算法的工作原理如下:在第一遍中,它用一个值标记每个前景像素,但是,可能会发生部分 blob 最终包含不同的标签。在第二遍中,我们希望实现属于一个 blob 的每个像素都被标记为相同的值。

      但是,在等价表中,对于每个标签,你可以很容易地找到与其等价的最小标签,即它在同一个组内。

      考虑链接的维基百科文章中的example。 (尤其是步骤 2 之后的表格。)在这里,如果您在第二遍中浏览图像,并找到例如一个值为 5 的标签,然后,通过等价表,您将能够发现它等同于标签 3(从而将所有标记为 5 的像素更改为 3)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-06
        • 2012-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-19
        相关资源
        最近更新 更多