wake-up-neo.net

opencv Mehrkanalelementzugriff

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

49
Yair
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

1. Wählen Sie einen Typ, um das Element darzustellen

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

2. greifen Sie auf das Element zu

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;

3. mit der alten Schnittstelle interagieren

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;
61
OwnWaterloo

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;
        }
    }
}
18
Ivan

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
6
crenate

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

1
sami dalati

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

  • type : der Datentyp (float, int, char ect ..)
  • i : Zeile, an der Sie interessiert sind
  • Nc : die Anzahl der Kanäle
  • j : die Spalte, die Sie interessiert
  • c : die Spalte, die Sie interessiert (0-3)

Informationen zu anderen c-> c ++ - Konvertierungen finden Sie unter folgendem Link: Source

0
aheigins