Empiezo con esta imagen: ingrese la descripción de la imagen aquí

Para lo cual quiero colorear las marcas de carril directamente en frente del vehículo (sí, esto es para una clase en línea de Udacity, pero quieren que haga esto en Python, pero prefiero hacerlo en C ++)

Encontrar los marcadores adecuados es fácil: ingrese la descripción de la imagen aquí

Esto funciona para colorear los marcadores:

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

Produciendo correctamente ingrese la descripción de la imagen aquí

Sin embargo, me sorprendió un poco que pareciera un poco lento, tomando 1-2 ms (en un núcleo i7-7700HQ con 16 gb de ram, compilado con -O3) para la imagen que es 960 x 540

Siguiendo "la forma eficiente" aquí: https: // docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#howtoscanimagesopencv

Se me ocurrio:

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

Que es aproximadamente 3 veces más rápido ... pero no produce los resultados correctos: ingrese la descripción de la imagen aquí

Todos los objetos cv :: Mat son del tipo 8UC3 (formato de píxel BGR estándar). Por lo que puedo decir, los datos subyacentes de los objetos Mat deberían ser una matriz de unsigned char s de la longitud, ancho de píxel * altura de píxel * num canales. Pero parece que me falta algo. isContinuous() es verdadero tanto para la salida como para las matrices de máscara. Estoy usando openCV 3.4.4 en Ubuntu 18.04. ¿Qué me estoy perdiendo?

1
schrödinbug 28 oct. 2019 a las 14:26

1 respuesta

La mejor respuesta

La forma típica de configurar un área enmascarada de un Mat a un valor específico es usar Mat::setTo función:

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);
3
slawekwin 28 oct. 2019 a las 12:04