I am doing a connected component operation on images: all of the pixels which are connected and have the same value will be assigned the same label.
An example is that if the input is:
1 1 2 2
2 4 4 1
1 5 1 1
it should return:
1 1 2 2
3 4 4 5
6 7 5 5
Two blobs which have value 1 has been reassigned to 1 and 5.
This code works for small images. But when applying to larger one (512x512), it usually reach the maximum number of recursive stack allowed (Python, Visual Studio C++ but not gcc C++). How to fix the problem?
vector<int> neighbors(int pixel, int height, int width)
// return neighboring pixels
{
assert(pixel < height *width);
vector<int> indexes;
if (pixel % width == width - 1)
{
indexes.push_back(pixel - 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
else if (pixel % width == 0)
{
indexes.push_back(pixel + 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
else
{
indexes.push_back(pixel + 1);
indexes.push_back(pixel - 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
vector<int> out;
for(int i = 0; i < indexes.size(); i++)
{
if (indexes[i] >= 0 && indexes[i] < height*width)
out.push_back(indexes[i]);
}
return out;
}
void floodfill(const unsigned char *im, unsigned char *out, int pixel, int height, int width, int label)
// starting from the pixel, label all connected labels to pixel
{
if (*(out + pixel) == 0)
{
*(out + pixel) = label;
vector<int> ns = neighbors(pixel, height, width);
for(int i = 0; i < ns.size(); i++)
{
if ((*(out + ns[i]) == 0) && *(im + ns[i]) == *(im + pixel))
{
floodfill(im, out, ns[i], height, width, label);
}
}
}
}
int ConnectedComponent(const unsigned char *im, unsigned char *out, int height, int width)
{
for (int i = 0; i < height*width; i++)
*(out+i) = 0;
int label = 0;
for (int i = 0; i < height *width; i++)
{
if (*(out + i) == 0)
{
label++;
floodfill(lev, out, i, height, width, label);
}
}
return label;
}
Testing code is:
TEST(testLulu, connectedcomponenet)
{
unsigned char lev[12] = {1,1,2,2,2,4,4,1,1,5,1,1};
unsigned char * out = new unsigned char[12]();
ConnectedComponent(lev, out, 3,4);
unsigned char correct[12] = {1,1,2,2,3,4,4,5,6,7,5,5};
for (int i = 0; i<12; i++)
{
EXPECT_EQ(correct[i], out[i]);
}
}