¿Cómo llenar Matrix con ceros en OpenCV?

4 minutos de lectura

Avatar de usuario de Suzan Cioc
Suzan Cioc

El siguiente código provoca una excepción. ¿Por qué?

#include <opencv2/core/core.hpp>
#include <iostream>

using namespace cv;
using namespace std;

void main() {

    try {
        Mat m1 = Mat(1,1, CV_64F, 0);
        m1.at<double>(0,0) = 0;
    }
    catch(cv::Exception &e) {
        cerr << e.what() << endl;
    }

}

El error es el siguiente:

OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in unknown function, file %OPENCV_DIR%\build\include\opencv2\core\mat.hpp, line 537

ACTUALIZAR

Si rastrea este código, veo que la línea del constructor llama al constructor

inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)

¿Por qué? Este prototipo tiene 5 parámetros, mientras que yo proporciono 4 argumentos.

  • aquí hay un ejemplo cv::Mat depthMap = cv::Mat::zeros(depthMap.rows, depthMap.cols, depthMap.type());

    – Mona Jalal

    25 mayo 2017 a las 20:03

avatar de usuario de juanchopanza
juanchopanza

¿Cómo llenar Matrix con ceros en OpenCV?

Para llenar una preexistente Mat objeto con ceros, puedes usar Mat::zeros()

Mat m1 = ...;
m1 = Mat::zeros(1, 1, CV_64F);

Para inicializar un Mat para que contenga solo ceros, puede pasar un escalar con valor 0 al constructor:

Mat m1 = Mat(1,1, CV_64F, 0.0);
//                        ^^^^double literal

La razón por la que tu versión falló es que pasar 0 como cuarto argumento coincide con la sobrecarga tomando un void* mejor que el que toma un escalar.

  • Gracias. Pero, ¿qué hace mi muestra? No 0 convertido automáticamente a Scalar?

    –Suzan Cioc

    11 de junio de 2013 a las 10:26

  • @SuzanCioc podría ser que se interprete como void*es decir, como un puntero a algunos datos.

    – juanchopanza

    11 de junio de 2013 a las 10:29

  • No veo ningún prototipo con 4 parámetros y void* al final.

    –Suzan Cioc

    11 de junio de 2013 a las 10:32

  • @SuzanCioc Veo esto: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) aquí docs.opencv.org/modules/core/doc/basic_structures.html

    – juanchopanza

    11 de junio de 2013 a las 10:36


  • Tenga en cuenta que cv::Mat::zeros() y similares crearán una nueva matriz, m1 luego apuntará a esta nueva matriz. Otras instancias que apuntan a los mismos datos que m1 seguirá apuntando allí. Para poner a cero un uso de matriz existente cv::Mat::setTo() como lo sugiere @GPPK.

    – Brandlingo

    17 de junio de 2015 a las 14:22


usar cv::mat::setto

img.setTo(cv::Scalar(redVal,greenVal,blueVal))

Avatar de usuario de LovaBill
LovaBill

Debido a que el último parámetro es opcional y también el puntero de datos debe apuntar a algún lugar apropiado:

//inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
double mydata[1];
Mat m1 = Mat(1,1, CV_64F, mydata); 
m1.at<double>(0,0) = 0;

Pero mejor hazlo directamente con este constructor basado en plantillas:

//inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
Mat m1 = Mat(1,1, CV_64F, cvScalar(0.));

//or even
Mat m1 = Mat(1,1, CV_64F, double(0));

Avatar de usuario de James Koo
james koo

Puede elegir llenar cero datos o crear cero Mat.

  1. Llenar cero datos con ajustado a():

    img.setTo(Scalar::all(0));
    
  2. Crear cero datos con ceros():

    img = zeros(img.size(), img.type());
    

La img cambia la dirección de la memoria.

Avatar de usuario de Nik Ved
nik ved

Si eres más de programar con plantillas, también puedes hacerlo de esta manera…

template<typename _Tp>
... some algo ...
cv::Mat mat = cv::Mat_<_Tp>::zeros(rows, cols);
mat.at<_Tp>(i, j) = val;

Avatar de usuario de Shameel Mohamed
Shameel Mohamed

Puede usar esto para llenar ceros en un objeto Mat que ya contiene datos:

image1 = Scalar::all(0);

Por ejemplo, si lo usa de esta manera:

Mat image,image1;
image = imread("IMG_20160107_185956.jpg", CV_LOAD_IMAGE_COLOR);   // Read the file

if(! image.data )                              // Check for invalid input
{
    cout <<  "Could not open or find the image" << std::endl ;
    return -1;
}
cvtColor(image,image1,CV_BGR2GRAY);
image1 = Scalar::all(0);

Funcionará bien. Pero no puede usar esto para Mat no inicializado. Para eso, puede optar por otras opciones mencionadas en las respuestas anteriores, como

Mat drawing = Mat::zeros( image.size(), CV_8UC3 );

Avatar de usuario de Lonewolf
Lobo solitario

Estera img;

img=Mat::zeros(tamaño de la imagen,CV_8UC3);

si quieres que sea de una imagen img1

img=Mat::ceros(img1.tamaño,CV_8UC3);

¿Ha sido útil esta solución?