schrödinbug
schrödinbug

Reputation: 871

Apply Mask in OpenCV

I start out with this image:enter image description here

for which I want to color in the lane markings directly in front of the vehicle (yes this is for a Udacity online class, but they want me to do this in python, but I'd rather do it in C++)

Finding the right markers is easy: enter image description here

This works for coloring the markers:

  cv::MatIterator_<cv::Vec3b> output_pix_it = output.begin<cv::Vec3b>(); 
  cv::MatIterator_<cv::Vec3b> output_end = output.end<cv::Vec3b>();

  cv::MatIterator_<cv::Vec3b> mask_pix_it = lane_markers.begin<cv::Vec3b>(); 

  //auto t1 = std::chrono::high_resolution_clock::now();

  while (output_pix_it != output_end)
  {
    if((*mask_pix_it)[0] == 255)
    {
      (*output_pix_it)[0] = 0;
      (*output_pix_it)[1] = 0;
      (*output_pix_it)[2] = 255;
    }

    ++output_pix_it;
    ++mask_pix_it;
  }

correctly producing enter image description here

however I was a little surprised that it seemed to be kind of slow, taking 1-2 ms (on a core i7-7700HQ w/ 16gb ram, compiled with -O3) for the image which is 960 x 540

Following "the efficient way" here: https://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#howtoscanimagesopencv

I came up with:

    unsigned char *o; // pointer to first element in output Mat
    unsigned char *m; //pointer to first element in mask Mat
    o = output.data;
    m = lane_markers.data;
    size_t pixel_elements = output.rows * output.cols * output.channels();

    for( size_t i=0; i < pixel_elements; i+=3 )
    {
      if(m[i] == 255)
      {
        o[i] = 0;
        o[i+1] = 0;
        o[i+2] = 255;
      }
    }

which is about 3x faster....but doesn't produce the correct results: enter image description here

All cv::Mat objects are of type 8UC3 type (standard BGR pixel format). As far as I can tell the underlying data of the Mat objects should be an array of unsigned chars of the length pixel width * pixel height * num channels. But it seems like I'm missing something. isContinuous() is true for both the output and mask matrices. I'm using openCV 3.4.4 on Ubuntu 18.04. What am I missing?

Upvotes: 1

Views: 1989

Answers (1)

slawekwin
slawekwin

Reputation: 6310

Typical way of setting a masked area of a Mat to a specific value is to use Mat::setTo function:

cv::Mat mask;
cv::cvtColor(lane_markers, mask, cv::COLOR_BGR2GRAY); //mask Mat has to be 8UC1
output.setTo(cv::Scalar(0, 0, 255), mask);

Upvotes: 3

Related Questions