Ask Your Question
0

Looking for ways to speed up pixel scanning

asked 2019-03-13 20:18:25 -0500

drcurry gravatar image

updated 2019-03-14 02:44:14 -0500

berak gravatar image

So I am trying to implement a pixel scanner, where I go through every pixel and check if it is white (the image has already been threshold-ed at this point) and if it is white get the pixel's respective x and y coordinate which I use to calculate distances. So far I have been doing it the double for-loop way, and it is adding significant slowdowns compared to the rest of my pipeline. I would like to speed this up. I have looked into using cv::findNonZero(), it gives me a vector of cv::Point, when I try and access the vector at some interation like vec[ i ] the output is [ rowValue, colValue ] which is expected but I don't know how to access the "rowValue" or "colValue" independently that I need in order to calculate distances. I have heard about using cv::LUT() but I'm having some trouble understanding how to use it. Thanks is advanced and let me know if more info is needed. Code below:

   cv::Mat W; // approx 1000 x 1000
    for (int i = 0; i < W.cols; i++)
    {
        for (int j = 0; j < W.rows; j++)
        {
            cv::Scalar pixelColor = counter.at<uchar>(j, i);
            if (pixelColor.val[0] == 255)
            {
                // pixelLocations are defined as a ROS message, A B C D are constants
                // used to calculate distances in meters
                pixelLocation.x = (A * i) + B; // distance in x direction relative to robot
                pixelLocation.y = (C * j) + D; // distance in front of robot 
            }
       }
    }
edit retag flag offensive close merge delete

Comments

use parallel_loop _body

LBerger gravatar imageLBerger ( 2019-03-21 03:13:32 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
0

answered 2019-03-14 01:59:25 -0500

gino0717 gravatar image

updated 2019-03-14 02:02:40 -0500

use .at<uchar>(j,i) would be slowly, try use

(faster) do something scanline-like scan

    for (int i = 0; i < W.rows; i++)  //row first!
    {
     *uchar data=W.ptr(i);

       for (int j = 0; j < W.cols; j++)
       {
         //do something with data[j];
       }
    }

or

(fastest) if your mat is continuous you can treat it as 1-d array

uchar* data = (uchar*) W.data; 

for(int i=0; i< W.cols*W.rows;i++) 
{
         //do something with data[i]; 
}
edit flag offensive delete link more
0

answered 2019-03-20 12:11:22 -0500

drcurry gravatar image

So I managed to ultilize the cv::findNonZero() function, to get the coordinates of the white pixels.

cv::Mat A;  
std::vector<cv::Point> pixelCoordinates;
std::vector<int> xp, yp;
cv::findNonZero(A, pixelCoordinates);
for (size_t i = 0; i < pixelCoordinates.size(); i++)
{
     xp.push_back(pixelCoordinates[i].x);
     yp.push_back(pixelCoordinates[i].y);
}
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2019-03-13 20:18:25 -0500

Seen: 80 times

Last updated: Mar 20