Ich versuche zu lernen, wie man die neue C++ - Schnittstelle von openCV verwendet.
Wie kann ich auf Elemente einer Mehrkanalmatrix zugreifen? zum Beispiel:
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);
}
}
Was ist der einfachste Weg, dies zu tun? So etwas wie cvSet2D der alten Schnittstelle
Was ist der effektivste Weg? Ähnlich wie bei der Verwendung von direkten Zeigern in der alten Benutzeroberfläche.
Vielen Dank
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;
Update: für OpenCV2.0
Mat (oder CvMat) hat 3 Dimensionen: Zeile, Spalte, Kanal.
Wir können auf ein Element (oder ein Pixel) in der Matrix zugreifen, indem Sie die Zeile und Spalte angeben.
CV_32FC2
bedeutet, dass das Element ein 32-Bit-Gleitkommawert mit 2 Kanälen ist.
.__ elem im obigen Code ist also eine akzeptable Darstellung von CV_32FC2
.
Sie können andere Darstellungen verwenden, die Sie mögen. Zum Beispiel :
typedef struct elem_ { float val[2]; } elem;
typedef struct elem_ { float x;float y; } elem;
OpenCV2.0 fügt einige neue Typen hinzu, um das Element in der Matrix darzustellen, beispielsweise:
template<typename _Tp, int cn> class CV_EXPORTS Vec // cxcore.hpp (208)
So können wir Vec<float,2>
verwenden, um CV_32FC2
darzustellen, oder verwenden:
typedef Vec<float, 2> Vec2f; // cxcore.hpp (254)
Sehen Sie sich den Quellcode an, um mehr Typen zu erhalten, die Ihr Element darstellen können.
Hier verwenden wir Vec2f
Die einfachste und effizienteste Möglichkeit, auf das Element in der Mat-Klasse zuzugreifen, ist Mat :: at.
Es hat 4 Überladungen:
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;
Mat bietet 2 Konvertierungsfunktionen:
// 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;
Vic Sie müssen Vec3b anstelle von Vec3i verwenden:
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;
}
}
}
Sie können direkt auf das zugrunde liegende Datenarray zugreifen:
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 hängt vom Datentyp der verwendeten Mat ab, ob es numerisch ist wie CV_32FC1you. Sie können Folgendes verwenden:
myMat.at<float>(i, j)
wenn es sich um einen Uchar-Typ handelt, können Sie mit auf ein Element zugreifen
(symb.at<Vec3b>(i, j)).val[k]
dabei ist k der Kanal, also 0 für Graustufenbilder und 3 für farbige
Der beste Weg, mit der c ++ - API auf ein Mehrkanal-Array zuzugreifen, besteht darin, mit der ptr-Methode einen Zeiger auf eine bestimmte Zeile zu erstellen.
Zum Beispiel;
type elem = matrix.ptr<type>(i)[N~c~*j+c]
wobei
Informationen zu anderen c-> c ++ - Konvertierungen finden Sie unter folgendem Link: Source