0

I'm trying to create a connected components labeling prototype to use in my graduation project. it works mostly, only it results in using large numbers for labels while skipping the smaller ones.

my code connects similar values from the given array (similarity measured via chi-square), and then there are some threshold to decide how much should the central array value be compared to its 8 neighbors. then, according to that I created a new array "cluster" which sums the value of the central value with its similar neighbor and divide by 2. then according to that, all similar values must be labeled.

this is the result:

as you can see, there are 4 objects, only the highest number us 26 not 4. so how can I fix this issue?

        #include<iostream>
    #include<math.h>
    #include "timer.h"
    #include <openacc.h>
    using namespace std;
    int main()
    {
    #if _OPENACC
        acc_init(acc_device_nvidia);
    #endif


        double array[8][8]=
        {
            {33,30,30,0,28,27,25,22}
            ,{32,30,29,0,26,25,23,21}
            ,{31,29,28,0,27,24,22,20}
            ,{30,28,27,0,25,23,20,19}
            ,{30,27,25,0,24,22,18,15}
            ,{27,25,21,0,22,4,16,13}
            ,{25,23,22,0,20,25,17,12}
            ,{24,23,22,0,19,17,15,11}

        } ;
        int height = 8;
        int width = 8;
        double cc[9][9];
        double top_right[9][9]= {};
        double thresh_array[9][9]= {};
        double top[9][9]= {};
        double top_left[9][9]= {};
        double left[9][9]= {};
        double center[9][9]= {};
        double right[9][9]= {};
        double bot_right[9][9]= {};
        double bot[9][9]= {};
        double bot_left[9][9]= {};
        int label [9][9] = {} ;
        double cluster[9][9] = {};
        double cluster_v;



        // Dis-Similarity Check via Chi-Square equation to find the similarity between central pixel and 8-neighbors
        // i+2 so it would only compare central pixels with its neighbors,to reduce the calculations needed
        for (int i=1; i<8; i+=2)
        {
            for (int j=0; j <( width); j++)

            {
                if (array[i][j]!= 0)
                {
                    top_left[i-1][j] =  (  (pow((array[i][j] - array[i-1][j-1]),2.0)) / (array[i][j] + array[i-1][j-1])                 );

                    top[i-1][j] =       (     (pow((array[i][j]-array[i-1][j]),2.0)) / (array[i][j] + array[i-1][j])                     );

                    top_right[i-1][j] = ( (pow((array[i][j]- array[i-1][j+1]),2.0)) / (array[i][j] + array [i-1][j+1])                            );

                    left[i-1][j] = ( (pow((array[i][j]-array[i][j-1]),2.0)) / (array[i][j] + array[i][j-1])             );

                    right[i-1][j] = ( (pow((array[i][j]-array[i][j+1]),2.0))/(array[i][j] + array[i][j+1]));

                    bot_left [i-1][j] = ((pow((array[i][j]-array[i+1][j-1]),2.0)) / (array[i][j] + array[i+1][j-1]));

                    bot [i-1][j] = ( (pow((array[i][j]-array[i+1][j]),2.0))/(array[i][j] + array[i+1][j]));

                    bot_right [i-1][j] = ( (pow((array[i][j]-array[i+1][j+1]),2.0))/(array[i][j] + array[i+1][j+1]));


                }

            }

        }

        double threshold=1000;

    // calculating the smallest threshold to construct a new array with only similar neighbors showing
        for (int i=1; i<(height); i+=2)
        {

            for (int j=0; j < (width); j++)
            {

                threshold = 1000;
                (threshold <= top_left[i-1][j])? : threshold = top_left[i-1][j];
                (threshold <= top[i-1][j])? : threshold = top[i-1][j];
                (threshold <= top_right[i-1][j])? : threshold = top_right[i-1][j];
                (threshold <=left[i-1][j])? : threshold = left[i-1][j];
                (threshold <= right[i-1][j])? : threshold = right[i-1][j];
                (threshold <= bot[i-1][j])? : threshold = bot[i-1][j];
                (threshold <= bot_left[i-1][j])? : threshold = bot_left[i-1][j];
                (threshold <=bot_right[i-1][j])? : threshold = bot_right[i-1][j];
                thresh_array[i-1][j] = threshold;

            }
        }

    // constructing the new array "cluster"
    // if the pixels are less that a threshold of 0.016, it is summed with the central pixel and divided by 2
        for (int i=1; i<height; i+=2)
        {

            for (int j=0; j < (width); j++)
            {
                if ( thresh_array[i-1][j] <0.016 && array[i-1][j] !=0)
                {


                    cluster_v =0;
                    if(top_left[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i-1][j-1] + array[i][j])/2);
                        cluster[i-1][j-1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (top[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i-1][j] + array[i][j])/2);
                        cluster[i-1][j] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (top_right[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i-1][j+1] + array[i][j])/2);
                        cluster[i-1][j+1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (left[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i][j-1] + array[i][j])/2);
                        cluster[i][j-1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (right[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i][j+1] + array[i][j])/2);
                        cluster[i][j+1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (bot_left[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i+1][j-1] + array[i][j])/2);
                        cluster[i+1][j-1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (bot[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i+1][j] + array[i][j])/2);
                        cluster[i+1][j] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                    if (bot_right[i-1][j] == thresh_array[i-1][j])
                    {
                        cluster_v = ((array[i+1][j+1] + array[i][j])/2);
                        cluster[i+1][j+1] = cluster_v;
                        cluster[i][j] = cluster_v;

                    }
                }

            }
        }

        // First pass of connected components labeling, checks the current pixel with top and left pixels from the new array
        // according to conditions
        int x=1, y=0;
        for (int i=0; i<height; i++)
        {
            for(int j=0; j<width; j++)
            {
                if(cluster[i][j] >0)
                {
                    if(cluster[i-1][j] >0 )
                        label[i][j] = x;
                    if (cluster[i-1][j+1] >0)
                        label[i][j] = x;
                    if(cluster[i-1][j-1] >0)
                        label[i][j] = x;
                    if(cluster [i][j-1] >0)
                        label[i][j] = x;
                    if (cluster[i+1][j] >0)
                        label[i][j] = x;
                    if(cluster [i][j+1] >0)
                        label[i][j] = x;
                    if(cluster [i+1][j+1] >0)
                        label[i][j] = x;
                    if(cluster [i+1][j-1] >0)
                        label[i][j] = x;
                    x+=1;

                }
                if(cluster[i][j] ==0)
                    label[i][j]=0;

                cout << cluster[i][j] <<" ";
            }
            cout << endl;
        }

        cout << endl;
        cout << "First pass" << endl;
        for (int i=0; i<8; i++)
        {
            for (int j=0; j<8; j++)
            {

                cout << label[i][j] <<" "   ;
            }
            cout << endl;
        }
        cout << endl;

    // second pass of connected components labeling
        int z=0;
        while (z<(1000))
        {


            for(int j=0; j<height; j++)
            {
                for(int i=(width-1); i>=0; i--)
                {
                    if(label[i][j] >0 )
                    {
                        if(label[i-1][j] >0 )
                            label[i][j] = min(label[i][j],label[i-1][j]);
                        if (label[i-1][j+1] >0)
                            label[i][j] = min(label[i][j],label[i-1][j+1]);
                        if(label[i-1][j-1] >0)
                            label[i][j] = min(label[i][j],label[i-1][j-1]);
                        if(label [i][j-1] >0)
                            label[i][j] = min(label[i][j],label[i][j-1]);
                        if (label[i+1][j] >0)
                            label[i][j] = min(label[i][j], label[i+1][j]);
                        if(label [i][j+1] >0)
                            label[i][j] = min(label[i][j], label[i][j+1]);
                        if(label [i+1][j+1] >0)
                            label[i][j] = min(label[i][j], label[i+1][j+1]);
                        if(label [i+1][j-1] >0)
                            label[i][j] = min(label[i][j], label[i+1][j-1]);
                    }
                }
            }

            z+=1;
        }

        cout << "Second Pass" << endl;

        for (int i=0; i<8; i++)
        {
            for (int j=0; j<8; j++)
            {

                cout << label[i][j] <<" "   ;
            }
            cout << endl;
        }
    }

notice, that I loop the second pass to get the best possible result.

Ibrahim
  • 152
  • 2
  • 9
  • Is that a problem? If you want to use lower numbers you can just relabel them `0, 1, 2, 3`. I'm not going to read through your entire code, but normally connected component labeling algorithms assign intermediate labels that end up getting overwritten as you find that components belong together. – beaker Apr 05 '17 at 14:03
  • @beaker yes that's the issue, I tried lowering them but always ended up doing complicated coding that gets me nowhere. can you suggest me something ? – Ibrahim Apr 05 '17 at 14:30
  • After your second pass, replace all `1`s with `1`, replace all `4`s with `2`, replace all `11`s with `3` and all `26`s with `4`. – beaker Apr 07 '17 at 22:43
  • @beaker what if I wanted to apply this on a larger array, say a pgm image ? my tests show so much unused labels and labeling one by one is very inefficient. – Ibrahim Apr 08 '17 at 14:31
  • Again, why are the unused labels a problem? As for relabeling, at worst you would have to make one more pass over the image once with a look-up table. But I guess to answer your question directly, I don't see any way to modify the connected component algorithm to use only the lowest-numbered labels. – beaker Apr 08 '17 at 14:39
  • my supervisor wants me to shade each object differently, so if we say there are like 8 different rectangles with the same color, each rectangle should get a separate shade. so it would be difficult to know which labels are being used for each rectangle and shade it differently. @beaker – Ibrahim Apr 09 '17 at 11:59
  • of course, I cannot use any library such as openCV, unfortunately. – Ibrahim Apr 09 '17 at 12:02
  • I don't mean to seem dense, but you've got distinct values for each component. How are you assigning colors to each of those? How is having the components labeled `{1,2,3,4]` better than having them labeled `{1,4,11,26}`? I honestly don't understand what problem you're trying to fix. – beaker Apr 09 '17 at 13:39
  • @beaker the code i'm using and the results are just prototypes for my real code, which handles images. what my supervisor wants me to do, is that I connect components and label these components (objects) then shade them. so if we have an image with 100 stars, there will be too many unused labels, which will make shading very difficult. and if I do manage to do it correctly on the 100 stars image, it'll never work on another image with different shapes inside. so what I want to do, is to make each object has its unique label without having unused labels. – Ibrahim Apr 09 '17 at 14:44
  • Why does having unused labels make shading very difficult? This is what I do not understand. Tell me exactly what the problem is. – beaker Apr 09 '17 at 14:48
  • @beaker I want labels to be shaded automatically. like object 1 gets a 0 pixel value while object 10 gets a 230 pixel value. problem is, object 10's label could be 2 or x, where x is a variable. so it's very hard to know which label is actually used on object 10 or any object. – Ibrahim Apr 09 '17 at 15:06
  • Okay, I guess I see what you mean. You do realize that what's labeled the 10th object in one image is going to be very different from the 10th object in another image, right? As to your problem, you will probably need to make another pass through the image and assign new labels as you find new components. If you kept a list of pixels for each component you *might* be able to speed it up for a sparse image, but I'm not sure it's worth the bother. – beaker Apr 09 '17 at 15:20
  • @beaker that also has crossed my mind, and honestly I've been spending too much time thinking and googling with no results. thanks mate – Ibrahim Apr 09 '17 at 15:26

0 Answers0