Estoy tratando de aprender a usar openCV del nuevo c++ interfaz.

¿Cómo puedo acceder a los elementos de un multi canal matriz. por ejemplo:

Mat myMat(size(3, 3), CV_32FC2);

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
    {
        //myMat_at_(i,j) = (i,j);
    }
}

¿Cuál es la manera más fácil de hacer esto? Algo así como cvSet2D de la antigua interfaz

¿Qué es lo más efficiant manera? Similar a la utilización directa de punteros en la antigua interfaz.

Gracias

InformationsquelleAutor Yair | 2009-12-01

5 Comentarios

  1. 65
    typedef struct elem_ {
            float f1;
            float f2;
    } elem;
    elem data[9] = { 0.0f };
    CvMat mat = cvMat(3, 3, CV_32FC2, data );
    
    float f1 = CV_MAT_ELEM(mat, elem, row, col).f1;
    float f2 = CV_MAT_ELEM(mat, elem, row, col).f2;
    
    CV_MAT_ELEM(mat, elem, row, col).f1 = 1212.0f;
    CV_MAT_ELEM(mat, elem, row, col).f2 = 326.0f;

    Actualización : para OpenCV2.0

    1. seleccione un tipo para representar el elemento

    Mat (o CvMat) tiene 3 dimensiones: row, col, canal.

    Podemos acceder a un elemento (o pixel) en la matriz especificando la fila y col.

    CV_32FC2 significa que el elemento es un valor de punto flotante de 32 bits con 2 canales.

    Así elem en el código de arriba es una aceptable representación de CV_32FC2.

    Puedes usar otras representaciones que te gusta. Por ejemplo :

    typedef struct elem_ { float val[2];    } elem;
    typedef struct elem_ { float x;float y; } elem;

    OpenCV2.0 añade algunos nuevos tipos para representar el elemento de la matriz,como :

    template<typename _Tp, int cn> class CV_EXPORTS Vec //cxcore.hpp (208)

    Por lo que podemos utilizar Vec<float,2> para representar CV_32FC2, o uso :

    typedef Vec<float, 2> Vec2f; //cxcore.hpp (254)

    Ver el código fuente para obtener más tipo que puede representar su elemento.

    Aquí se utiliza Vec2f

    2. acceder al elemento

    La forma más fácil y efficiant manera de acceder al elemento en el Tapete de la clase es Mat::en.

    Dispone de 4 sobrecargas :

    template<typename _Tp> _Tp& at(int y, int x);                //cxcore.hpp (868)
    template<typename _Tp> const _Tp& at(int y, int x) const;    //cxcore.hpp (870)
    template<typename _Tp> _Tp& at(Point pt);                    //cxcore.hpp (869)
    template<typename _Tp> const _Tp& at(Point pt) const;        //cxcore.hpp (871)
    //defineded in cxmat.hpp (454-468)
    
    //we can access the element like this :
    Mat m( Size(3,3) , CV_32FC2 );
    Vec2f& elem = m.at<Vec2f>( row , col ); //or m.at<Vec2f>( Point(col,row) );
    elem[0] = 1212.0f;
    elem[1] = 326.0f;
    float c1 = m.at<Vec2f>( row , col )[0]; //or m.at<Vec2f>( Point(col,row) );
    float c2 = m.at<Vec2f>( row , col )[1];
    m.at<Vec2f>( row, col )[0] = 1986.0f;
    m.at<Vec2f>( row, col )[1] = 326.0f;

    3. interactuar con la interfaz antigua

    Mat proporciona 2 funciones de conversión:

    //converts header to CvMat; no data is copied     //cxcore.hpp (829)
    operator CvMat() const;                            //defined in cxmat.hpp
    //converts header to IplImage; no data is copied
    operator IplImage() const;
    
    //we can interact a Mat object with old interface :
    Mat new_matrix( ... );
    CvMat old_matrix = new_matrix;  //be careful about its lifetime
    CV_MAT_ELEM(old_mat, elem, row, col).f1 = 1212.0f;
    • Gracias, pero no es lo que yo estaba pidiendo. Usted está utilizando CvMat – el viejo (versión 1.1) c API. Quiero un método similar para el nuevo (2.0 a) de la API c++ usando la Estera de la clase. Hay algo como CV_MAT_ELEM para la Estera de la clase?
    • Lo siento.Se me olvida que OpenCV2.0 ha sido puesto en libertad. He descargado el 2.0 fuente y encontrado algunas formas para acercarse a su meta.Ver el código actualizado.
    • Funciona muy bien! Gracias 🙂
    • existe una mejor forma de acceder a CvMat wihtout uso de CV_MAT_ELEM como CV_MAT_ELEM(old_mat, elem, fila, col).la f1 ?? con f1 o f2 fijo, no podemos iterar mediante programación a través de la matriz es decir, i,j índice de
  2. 19

    Vic debe utilizar Vec3b en lugar de Vec3i:

    for (int i=0; i<image.rows; i++)
    {
        for (int j=0; j<image.cols; j++)
        {
            if (someArray[i][j] == 0)
            {
                image.at<Vec3b>(i,j)[0] = 0;
                image.at<Vec3b>(i,j)[1] = 0;
                image.at<Vec3b>(i,j)[2] = 0;
            }
        }
    }
  3. 6

    Puede acceder a los datos subyacentes de la matriz directamente:

    Mat myMat(size(3, 3), CV_32FC2);
    
    myMat.ptr<float>(y)[2*x]; //first channel
    myMat.ptr<float>(y)[2*x+1]; //second channel
    • Es worths diciendo que y es imagen de filas y columnas de la imagen de x es. Es necesario multiplicar x por 2, ya que tiene 2 canales y en OpenCV imagen es representada como la ALTURA x ANCHURA x CANALES de la matriz en una fila principal de la orden.
  4. 1

    depende del tipo de datos de la alfombra que está utilizando, si es numérico como CV_32FC1
    usted puede utilizar:

    myMat.at<float>(i, j)

    si se trata de un tipo uchar entonces usted puede tener acceso a un elemento mediante

    (symb.at<Vec3b>(i, j)).val[k]

    donde k es el canal, que es 0 para imágenes en escala de grises y 3 de color

  5. 0

    La mejor manera de acceder a múltiples canales de matriz con la api de c++ es mediante la creación de un puntero a una fila específica utilizando el ptr método.

    Por ejemplo;

    type elem = matrix.ptr<type>(i)[N~c~*j+c]

    donde

    • tipo: el tipo de datos(float, int, char, ect..)
    • me: fila estás interesado en
    • Nc: el número de canales de
    • j: la columna está interesado en
    • c: la columna está interesado en(0-3)

    Para obtener información sobre otros c->c++ conversión echa un vistazo a este enlace: Fuente

Dejar respuesta

Please enter your comment!
Please enter your name here