accesso agli elementi multicanale aperto
-
22-07-2019 - |
Domanda
Sto cercando di imparare come usare la nuova interfaccia c ++ di openCV.
Come posso accedere agli elementi di una matrice multicanale. ad esempio:
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 è il modo più semplice per farlo? Qualcosa come cvSet2D della vecchia interfaccia
Qual è il modo più efficace? Simile all'utilizzo di puntatori diretti nella vecchia interfaccia.
Grazie
Soluzione
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;
Aggiornamento: per OpenCV2.0
1. scegli un tipo per rappresentare l'elemento
Mat (o CvMat) ha 3 dimensioni: riga, colonna, canale.
Possiamo accedere a un elemento (o pixel) nella matrice specificando riga e colonna.
CV_32FC2
indica che l'elemento ha un valore in virgola mobile a 32 bit con 2 canali.
Quindi elem nel codice sopra è una rappresentazione accettabile di Vec<float,2>
.
Puoi usare altre rappresentazioni che ti piacciono. Ad esempio:
typedef struct elem_ { float val[2]; } elem;
typedef struct elem_ { float x;float y; } elem;
OpenCV2.0 aggiunge alcuni nuovi tipi per rappresentare l'elemento nella matrice, come:
template<typename _Tp, int cn> class CV_EXPORTS Vec // cxcore.hpp (208)
Quindi possiamo usare Vec2f
per rappresentare <=>, oppure usare:
typedef Vec<float, 2> Vec2f; // cxcore.hpp (254)
Vedi il codice sorgente per ottenere più tipi in grado di rappresentare il tuo elemento.
Qui usiamo <=>
2. accedi all'elemento
Il modo più semplice ed efficace per accedere all'elemento nella classe Mat è Mat :: at.
Ha 4 sovraccarichi:
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. interagire con la vecchia interfaccia
Mat offre 2 funzioni di conversione:
// 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;
Altri suggerimenti
Vic devi usare Vec3b invece di 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;
}
}
}
Puoi accedere direttamente all'array di dati sottostante:
Mat myMat(size(3, 3), CV_32FC2);
myMat.ptr<float>(y)[2*x]; // first channel
myMat.ptr<float>(y)[2*x+1]; // second channel
dipende dal tipo di dati del Mat che si sta utilizzando, se è numerico come CV_32FC1 puoi usare:
myMat.at<float>(i, j)
se è un tipo uchar, puoi accedere a un elemento usando
(symb.at<Vec3b>(i, j)).val[k]
dove k è il canale, ovvero 0 per le immagini in scala di grigi e 3 per le immagini colorate
Il modo migliore per accedere all'array multicanale con l'API c ++ è creare un puntatore a una riga specifica usando il metodo ptr.
Ad esempio;
type elem = matrix.ptr<type>(i)[N~c~*j+c]
dove
- tipo : il tipo di dati (float, int, char ect ..)
- i : riga che ti interessa
- Nc : il numero di canali
- j : la colonna che ti interessa
- c : la colonna che ti interessa (0-3)
Per informazioni su altre conversioni c - > c ++ consulta questo link: Fonte