Pergunta

Estou tentando aprender a usar a nova interface C ++ da OpenCV.

Como faço para acessar elementos de uma matriz de canais multi. por exemplo:

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

Qual é a maneira mais fácil de fazer isso? Algo como cvSet2d da interface antiga
Qual é a maneira mais eficaz? Semelhante ao uso de ponteiros diretos na interface antiga.

obrigada

Foi útil?

Solução

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;

ATUALIZAÇÃO: Para OpenCv2.0

1. Escolha um tipo para representar o elemento

O MAT (ou CVMAT) possui 3 dimensões: linha, col, canal.
Podemos acessar um elemento (ou pixel) na matriz especificando a linha e o col.

CV_32FC2 significa que o elemento é um valor de ponto flutuante de 32 bits com 2 canais.
Então, elem no código acima é uma representação aceitável de CV_32FC2.

Você pode usar outras representações que você gosta. Por exemplo :

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

OpenCv2.0 adiciona alguns novos tipos para representar o elemento na matriz, como:

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

Então podemos usar Vec<float,2> representar CV_32FC2, ou uso:

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

Consulte o código -fonte para obter mais tipo que pode representar seu elemento.
Aqui nós usamos Vec2f

2. Acesse o elemento

A maneira mais fácil e eficaz de acessar o elemento na classe Mat é o tapete.
Tem 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. Interaja com a interface antiga

O MAT fornece 2 funções de conversão:

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

Outras dicas

VIC Você deve usar o VEC3B em vez do 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;
        }
    }
}

Você pode acessar a matriz de dados subjacente diretamente:

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 do tipo de dados do tapete que você está usando, se for numérico como CV_32FC1 que você pode usar:

myMat.at<float>(i, j)

Se for do tipo uchar, você pode acessar um elemento usando

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

onde k é o canal, isso é 0 para imagens em escala de cinza e 3 para colorido

A melhor maneira de acessar a matriz multi -canal com a API C ++ é criando um ponteiro para uma linha específica usando o método PTR.

Por exemplo;

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

Onde

  • modelo: o tipo de dados (float, int, charct.)
  • eu: Row você está interessado em
  • NC: o número de canais
  • j: a coluna em que você está interessado
  • c: a coluna em que você está interessado (0-3)

Para obter informações sobre outra conversão C-> C ++, consulte este link: Fonte

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top