Ask Your Question
0

[C++] Efficient element-by-element pixel access?

asked 2015-05-05 13:12:01 -0600

TPB gravatar image

updated 2015-05-05 16:41:29 -0600

SR gravatar image

Hello,

I know this has been asked many times and I've gone over the docs here but cannot seem to find an answer to my specific issue. I am trying to map the results from k-means clustering back into an image with reduced colors.

My old code works and does this using the Mat.at accessor, but it is very slow. I am trying to re-write this using pointers to improve performance, but right now the clustered image has many diagonal lines and the colors/pixels are not in the right place.

This works but is slow

for( int y = 0; y < resized.rows; y++ ){
    for( int x = 0; x < resized.cols; x++ ){
        {
            pixelPos =y + x*resized.rows;
            cluster_idx = labels.at<int>(pixelPos,0);
            clusteredImg.at<Vec3b>(y,x)[0] = centers.at<float>(cluster_idx, 0);
            clusteredImg.at<Vec3b>(y,x)[1] = centers.at<float>(cluster_idx, 1);
            clusteredImg.at<Vec3b>(y,x)[2] = centers.at<float>(cluster_idx, 2);
        }
    }

}

EDIT: The below code is working I had a silly mistake where I forgot that labels was M*Nx1 rather than MxNx1.

If there is any room for improvement please let me know!

for (int i = 0; i < resized.rows; ++i)
{
    cv::Vec3b* destPix = clusteredImg.ptr<cv::Vec3b>(i);
    int* labelPix = labels.ptr<int>(i);
    for (int j = 0; j < resized.cols; ++j)
    {
        pixelPos = i + j*resized.rows;
        cluster_idx = *labels.ptr<int>(pixelPos,0);
        float * centroidPtr = centers.ptr<float>(cluster_idx);

        destPix[j][0] = *centroidPtr++;
        destPix[j][1] = *centroidPtr++;
        destPix[j][2] = *centroidPtr++;
    }
}

Sorry if this is a stupid question, I am very new to C++.

I'm sure I have something wrong with how the destination data is assigned. I've checked the source data by printing debug statements and that seems to be correct.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2015-05-05 16:43:36 -0600

SR gravatar image

You are mixing types. You have a float * centroidPtr but assign it to one element of destPix[j] in destPix[j][0] = *centroidPtr++;. However, destPix[j] is a uchar so the values are truncated and meaningless.

edit flag offensive delete link more

Comments

Thank your for your answer.

This code actually is working right now though. Isn't the float just rounded so it will fit?

To make it explicit, is this correct?

destPix[j][0] =(int) *centroidPtr++;
TPB gravatar imageTPB ( 2015-05-05 22:45:46 -0600 )edit

Yes that makes it expclit. The values is never rounded but truncated to [0, 255] though. I do not know if that's correct for your application.

SR gravatar imageSR ( 2015-05-06 08:42:26 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-05-05 13:12:01 -0600

Seen: 443 times

Last updated: May 05 '15