Pregunta

Estoy tratando de aprender a usar la nueva interfaz c ++ de openCV.

¿Cómo accedo a los elementos de una matriz multicanal? 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 forma más fácil de hacer esto? Algo así como cvSet2D de la interfaz anterior
¿Cuál es la forma más eficiente? Similar al uso de punteros directos en la interfaz anterior.

Gracias

¿Fue útil?

Solución

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. elija un tipo para representar el elemento

Mat (o CvMat) tiene 3 dimensiones: fila, col, canal.
Podemos acceder a un elemento (o píxel) en la matriz especificando la fila y la columna.

CV_32FC2 significa que el elemento es un valor de coma flotante de 32 bits con 2 canales.
Entonces, elem en el código anterior es una representación aceptable de Vec<float,2>.

Puede usar otras representaciones que desee. Por ejemplo:

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

OpenCV2.0 agrega algunos tipos nuevos para representar el elemento en la matriz, como:

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

Entonces podemos usar Vec2f para representar <=>, o usar:

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

Vea el código fuente para obtener más tipos que puedan representar su elemento.
Aquí usamos <=>

2. acceder al elemento

La forma más fácil y eficiente de acceder al elemento en la clase Mat es Mat :: at.
Tiene 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 anterior

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;

Otros consejos

Vic debes usar 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;
        }
    }
}

Puede acceder a la matriz de datos subyacente 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

depende del tipo de datos del tapete que esté utilizando, si es numérico como CV_32FC1 puedes usar:

myMat.at<float>(i, j)

si es un tipo uchar, puede acceder a un elemento usando

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

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

La mejor manera de acceder a la matriz multicanal con la api de c ++ es creando un puntero a una fila específica utilizando el método ptr.

Por ejemplo;

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

where

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

Para obtener información sobre otras conversiones de c - > c ++, consulte este enlace: Fuente

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top