我正在尝试学习如何使用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之类的东西 什么是最有效的方式?类似于在旧界面中使用直接指针。
谢谢
答案 0 :(得分:63)
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
Mat(或CvMat)有3个维度:row,col,channel 我们可以通过指定行和列来访问矩阵中的一个元素(或像素)。
CV_32FC2
表示该元素是32位浮点值,有2个通道
所以上面代码中的元素是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
访问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;
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;
答案 1 :(得分:19)
Vic你必须使用Vec3b而不是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;
}
}
}
答案 2 :(得分:6)
您可以直接访问基础数据阵列:
Mat myMat(size(3, 3), CV_32FC2);
myMat.ptr<float>(y)[2*x]; // first channel
myMat.ptr<float>(y)[2*x+1]; // second channel
答案 3 :(得分:1)
它取决于您正在使用的Mat的数据类型,如果它是CV_32FC1之类的数字 你可以使用:
myMat.at<float>(i, j)
如果是uchar类型,则可以使用
访问元素(symb.at<Vec3b>(i, j)).val[k]
其中k是通道,其中0表示灰度图像,3表示彩色
答案 4 :(得分:0)
使用c ++ api访问多通道数组的最佳方法是使用ptr方法创建指向特定行的指针。
例如;
type elem = matrix.ptr<type>(i)[N~c~*j+c]
<强>,其中强>
有关其他c-&gt; c ++转换的信息,请查看以下链接:Source