我有一项任务,旨在从黑白图像中提取最大的物体,其中黑色是背景。我正在使用2遍算法,这里是一个解释它是如何工作的链接: http://en.wikipedia.org/wiki/Connected-component_labeling#Two-pass
我的问题: 1.我正在使用一个结构数组,我想将它的尺寸定义为与输入图像相同的#34;所以{我怎么能这样做}
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;
}
答案 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)
缺少部分代码,因此我做出以下假设:height
,width
和image
是类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找到了另一个实现。
- 如何使用等价表来重新标记像素中的像素 第二遍?我怎么写第二遍的代码?
醇>
据我所知,算法的工作原理如下:在第一遍中,它用一个值标记每个前景像素,但是,可能会发生斑点的某些部分最终包含不同的标签。在第二遍中,我们希望实现属于blob的每个像素都标有相同的值。
但是,在等价表中,对于每个标签,您可以轻松找到与其等价的最小标签,即它在同一组内。
考虑链接的维基百科文章中的example。 (特别是步骤2之后的表格。)这里,如果您在第二遍中浏览图像,并查找例如一个标签,其值为5,然后,使用等价表,您将能够发现它等同于标签3(从而更改标记为5到3的所有像素)。