Применить маску в OpenCV - PullRequest
       3

Применить маску в OpenCV

1 голос
/ 28 октября 2019

Я начинаю с этого изображения: enter image description here

, для которого я хочу раскрасить разметку полос перед автомобилем (да, это для онлайн-класса Udacity, но они хотят, чтобы я делал это на python, но я бы предпочел сделать это на C ++)

Найти нужные маркеры легко: enter image description here

Этоработает для окраски маркеров:

  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;
  }

правильно производит enter image description here

однако я был немного удивлен, что это казалось медленным, принимая 1-2 мс (на ядре i7-7700HQ с оперативной памятью 16 ГБ, скомпилировано с -O3) для изображения, которое составляет 960 x 540

Следуя «эффективному способу» здесь: https://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#howtoscanimagesopencv

Я придумал:

    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;
      }
    }

, что примерно в 3 раза быстрее .... но не дает правильных результатов: enter image description here

Все резюме:: Объекты Mat имеют тип 8UC3 (стандартный пиксельный формат BGR). Насколько я могу судить, базовые данные объектов Mat должны быть массивом unsigned char s длины пикселя ширина * высота пикселя * количество каналов. Но похоже, что я что-то упустил. isContinuous() верно для матриц вывода и маски. Я использую openCV 3.4.4 на Ubuntu 18.04. Чего мне не хватает?

1 Ответ

3 голосов
/ 28 октября 2019

Типичным способом установки маскированной области Mat на конкретное значение является использование функции Mat::setTo:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...