web-dev-qa-db-ja.com

opencvマルチチャンネル要素アクセス

私はopenCVの新しいc ++インターフェイスの使用方法を学ぼうとしています。

マルチチャネルマトリックスの要素にアクセスするにはどうすればよいですか。例えば:

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

これを行う最も簡単な方法は何ですか?古いインターフェースのcvSet2Dのようなもの
最も効率的な方法は何ですか?古いインターフェースで直接ポインターを使用するのと同様です。

ありがとうございました

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

更新:OpenCV2.0用

1.要素を表す1つのタイプを選択します

Mat(またはCvMat)には、row、col、channelの3つのディメンションがあります。
行と列を指定することで、マトリックス内の1つの要素(またはピクセル)にアクセスできます。

CV_32FC2は、要素が2チャネルの32ビット浮動小数点値であることを意味します。
したがって、上記のコードのelemは、CV_32FC2

好きな表現を使用できます。例えば ​​:

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

OpenCV2.0は、マトリックス内の要素を表す新しいタイプをいくつか追加します。

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

したがって、Vec<float,2> 表現します CV_32FC2、または使用:

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

ソースコードを参照して、要素を表すことができるより多くの型を取得してください。
ここではVec2f

2.要素にアクセスする

Matクラスの要素にアクセスする最も簡単で効率的な方法は、Mat :: atです。
4つのオーバーロードがあります。

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.古いインターフェイスと対話する

Matは2つの変換関数を提供します。

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

Vic Vec3iの代わりにVec3bを使用する必要があります。

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

基になるデータ配列に直接アクセスできます。

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

使用しているマットのデータ型に依存します。CV_32FC1のような数値の場合、使用できます:

myMat.at<float>(i, j)

uchar型の場合は、次を使用して要素にアクセスできます。

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

ここで、kはチャネルであり、グレースケールイメージの場合は0、カラーの場合は3

1
sami dalati

C++ APIを使用してマルチチャネル配列にアクセスする最良の方法は、ptrメソッドを使用して特定の行へのポインターを作成することです。

例えば;

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

where

  • type:datatype(float、int、char ect ..)
  • i:興味のある行
  • Nc:チャネル数
  • j:興味のある列
  • c:興味のある列(0-3)

他のc-> c ++変換については、次のリンクを参照してください。 ソース

0
aheigins