Ask Your Question
0

How to use C-style scan to check pixel neighbors ?

asked 2017-06-16 01:44:27 -0600

Nbb gravatar image

updated 2017-06-16 02:25:43 -0600

Hey all,

I am trying to scan an image using the efficient C-style pointer access. For every pixel of a 16-bit unsigned image, i

1. look at its right and bottom neighbor and perform some operations if they are not the same.
2. accumulate the color information of the pixel i am at

The problem appears when the pixel is at the border of the image because the neighbor to its right l[j+1] is the first pixel of the next row.

http://docs.opencv.org/2.4/doc/tutori...

Is there a solution for this ?

int n_rows = label.rows;
int n_cols  = label.cols;

for (int i = 0; i < 1; ++i)
{
    ushort* l = label.ptr<ushort>(i);
    cv::Vec3b* c = color.ptr<cv::Vec3b>(i);
    for (int j = 0; j < n_cols * n_rows; ++j)
    {
        //labels
        int mid    = l[j], 
            right  = l[j + 1], 
            bottom = l[j + n_cols];

        //accumulate color
        cluster[mid].color += c[i];

        //do something if (mid label != right label_ || (mid label != bottom label)
        if(mid != right)  //increment_boundary(mid,right);
        if(mid != bottom) //increment_boundary(mid,bottom);
    }
}

This is the unoptimized version

    //label = ushort, color = cv::Vec3b
    cv::Mat label, color;

    //fill up color and label

    //pad label
    cv::copyMakeBorder(label, label_padded, 0, 2, 0, 2, cv::BORDER_REPLICATE);

    //use dimensions of unpadded image
    int n_rows = label.rows,
        n_cols = label.cols;

    for(int row = 0; row < n_rows; row++)
    for(int col = 0; col < n_cols; col++)
    {
        //labels
        int mid    = label_padded.at<ushort>(row, col),
            right  = label_padded.at<ushort>(row, col + 1),
            bottom = label_padded.at<ushort>(row + 1, col);

        //update cluster statistics
        //cluster[mid] += color.at<cv::Vec3b>(row, col);

        if(mid != right) //update boundary
        if(mid != bottom) //update boundary
    }
edit retag flag offensive close merge delete

Comments

so, optimizing quite often leads to "shooting your own foot", especially, if you did not plan the whole thing properly.

what were your original plans for the last 2 pixels of each row ? (skip them ?)

for (int i = 0; i < 1; ++i) <-- what's the use of this ?

imho, we can only try to understand it, if we see the "unoptimized" version

berak gravatar imageberak ( 2017-06-16 01:57:13 -0600 )edit

hi sorry I should have had the proper code. I still need to access every pixel because I am accumulating the information at every pixel

Nbb gravatar imageNbb ( 2017-06-16 02:16:07 -0600 )edit

again, let's start with the original, unoptimized version, and let's try to accelerate that.

right now, you force us to reverse engineer your broken attempt, to find out, what was meant in the 1st place.

berak gravatar imageberak ( 2017-06-16 02:18:27 -0600 )edit

Maybe the simplest way is to just pad the borders http://docs.opencv.org/2.4/modules/im... borderInterpolate(int p, int len, int borderType) and to not iterate through the array as if it was a 1D array ?

Nbb gravatar imageNbb ( 2017-06-16 02:19:01 -0600 )edit
1

Hi berak ! Thanks for the help. I have updated my post to include the unoptimized version

Nbb gravatar imageNbb ( 2017-06-16 02:25:09 -0600 )edit

what are you trying to do with the clusters ? where do the labels come from ? how are they different from "ordinary indexing" ?

berak gravatar imageberak ( 2017-06-16 02:53:28 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2017-06-16 04:08:59 -0600

Ice_T02 gravatar image

updated 2017-06-16 04:15:51 -0600

I guess you are trying to implement your solution from this post.

Here is an alternative way to loop over the pixels. Its slower then old c-style but faster then the unoptimized version:

for (size_t y = 0; y < imageHeight - 1; ++y)
{
    for (size_t x = 0; x < imageWidth - 1; ++x)
    {
        idx = y * imageWidth + x;
        //Look straigth right
        pimg[idx + 1]
        //Look straigth down
        pimg[idx + imageWidth];
        //Look down right
        pimg[idx + imageWidth + 1]
    }
}

Ofcourse you have to stop at maxCol-1/maxRow-1 so you stay within the boundaries of image. You can add a special case for the last row, where you just look at the right side or something like this. Dont get me wrong you can also use old c-style but you need aditional checks inorder to know when a new row starts.

Hope this helps.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-06-16 01:44:27 -0600

Seen: 1,388 times

Last updated: Jun 16 '17