我正在尝试学习如何使用 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
最有效的方法是什么?与旧接口中使用直接指针类似。

谢谢

有帮助吗?

解决方案

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。选择一种类型来表示元件结果

垫(或与CvMat)具有3个维度:行,列,信道搜索 我们可以通过指定的行和col矩阵中的访问一个元素(或像素)。结果

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。访问该元素

要访问该元素在垫类的最简单和efficiant方法是垫在::。结果 它有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。与旧的接口进行交互

垫提供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;

其他提示

维克必须使用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;
        }
    }
}

可以直接访问底层数据数组:

Mat myMat(size(3, 3), CV_32FC2);

myMat.ptr<float>(y)[2*x]; // first channel
myMat.ptr<float>(y)[2*x+1]; // second channel

这取决于正在使用的垫的数据类型,如果是数字像CV_32FC1 可以使用:

myMat.at<float>(i, j)

如果它是一个UCHAR类型则可以使用访问一个元素

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

,其中k是信道,这就是为0灰度图像和彩色3

使用 c++ api 访问多通道数组的最佳方法是使用 ptr 方法创建指向特定行的指针。

例如;

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

在哪里

  • 类型: :数据类型(float、int、char ect..)
  • : :您感兴趣的行
  • 数控: :通道数
  • j: :您感兴趣的专栏
  • C: :您感兴趣的栏目(0-3)

有关其他 c->c++ 转换的信息,请查看此链接: 来源

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top