У меня есть задание, которое направлено на извлечение самого большого объекта из черно-белого изображения, где черный является фоном. Я использую алгоритм 2-проходной, вот ссылка, которая объясняет, как это работает:
http://en.wikipedia.org/wiki/Connected-component_labeling#Two-pass
Мои проблемы:
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;
}
Часть кода отсутствует, поэтому я делаю следующее предположение: height
, width
а также image
являются членами класса 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 ++, и еще один в питон), а затем вы реализуете свои, как только поняли.
РЕДАКТИРОВАТЬ: я только что нашел другую реализацию здесь ТАК.
- Как я могу использовать таблицу эквивалентности для «перемаркировки пикселей в
Второй проход? Как я могу написать код второго прохода?
Насколько я понял, алгоритм работает следующим образом: на первом проходе он маркирует каждый пиксель переднего плана значением, однако может случиться так, что части BLOB-объектов в конечном итоге будут содержать разные метки. Во втором проходе мы хотим добиться, чтобы каждый пиксель, принадлежащий BLOB-объекту, был помечен одинаковым значением.
Однако в таблице эквивалентности для каждой метки вы можете легко найти наименьшую метку, которая эквивалентна ей, то есть она находится в той же группе.
Рассмотрим пример в связанной статье Википедии. (Особенно таблица после шага 2.) Здесь, если вы просматриваете изображение во втором проходе, и находите, например, метка, значение которой равно 5, тогда с помощью таблицы эквивалентности вы сможете узнать, что она эквивалентна метке 3 (и, таким образом, изменить все пиксели с меткой 5 на 3).