双通算法的第二遍(连通组件4-连通性)

时间:2015-01-31 17:58:21

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

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

我的问题: 1.我正在使用一个结构数组,我想将它的尺寸定义为与输入图像相同的#34;所以{我怎么能这样做}

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

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

    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;
    
    }
    

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分:0)

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

关于你的问题:

  

1.我正在使用一个结构数组,我想将它的尺寸定义为&#34;输入图像&#34;所以{我怎么能这样做   }

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. 如何使用等价表来重新标记像素中的像素   第二遍?我怎么写第二遍的代码?
  2.   

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

但是,在等价表中,对于每个标签,您可以轻松找到与其等价的最小标签,即它在同一组内。

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