C++ opencv 多通道元素访问

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1824787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:16:54  来源:igfitidea点击:

opencv multi channel element access

c++imageimage-processingopencv

提问by Yair

I'm trying to learn how to use openCV's new c++ interface.

我正在尝试学习如何使用 openCV 的新 C++ 接口。

How do I access elements of a multi channel matrix. for example:

如何访问多通道矩阵的元素。例如:

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

What is the easiest way to do this? Something like cvSet2D of the old interface
What is the most efficiant way? Similar to using direct pointers in the old interface.

什么是最简单的方法来做到这一点?老接口的cvSet2D之类的最有效率的
方法是什么?类似于在旧接口中使用直接指针。

Thank you

谢谢

回答by OwnWaterloo

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 : for OpenCV2.0

更新:对于 OpenCV2.0

1. choose one type to represent the element

1.选择一种类型来表示元素

Mat (or CvMat) has 3 dimensions: row, col, channel.
We can access one element (or pixel) in the matrix by specifying the row and col.

Mat(或 CvMat)有 3 个维度:行、列、通道。
我们可以通过指定行和列来访问矩阵中的一个元素(或像素)。

CV_32FC2means the element is 32bit floating point value with 2 channels.
So elem in above code is one acceptable representation of CV_32FC2.

CV_32FC2表示元素是具有 2 个通道的 32 位浮点值。
所以上面代码中的 elem 是CV_32FC2.

You can use other representations you like. For example :

您可以使用其他您喜欢的表示。例如 :

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

OpenCV2.0 adds some new types to represent the element in the matrix,like :

OpenCV2.0 添加了一些新类型来表示矩阵中的元素,例如:

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

So we can use Vec<float,2>to represent CV_32FC2, or use :

所以我们可以使用Vec<float,2>来表示CV_32FC2,或者使用:

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

See the source code to get more type that can represent your element.
Here we use Vec2f

查看源代码以获取更多可以代表您的元素的类型。
这里我们使用Vec2f

2. access the element

2.访问元素

The easiest and efficiant way to access the element in the Mat class is Mat::at.
It has 4 overloads :

访问 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. interact with old interface

3.与旧界面交互

Mat provides 2 conversion functions:

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;

回答by Ivan

Vic you must use Vec3b instead of Vec3i:

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

回答by crenate

You can access the underlying data array directly:

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

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

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

回答by sami dalati

it depends on the datatype of the Mat you are using, if it is numeric like CV_32FC1 you can use:

这取决于您使用的垫子的数据类型,如果它是像 CV_32FC1 这样的数字,您可以使用:

myMat.at<float>(i, j)

if it is a uchar type then you can access an element using

如果它是 uchar 类型,那么您可以使用访问元素

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

where k is the channel, thats 0 for grayscale images and 3 for colored

其中 k 是通道,灰度图像为 0,彩色图像为 3

回答by aheigins

The best way to access multi channel array with the c++ api is by creating a pointer to a specific row using the ptr method.

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

For example;

例如;

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

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

where

在哪里

  • type: the datatype(float, int, char ect..)
  • i: row you're interested in
  • Nc: the number of channels
  • j: the column you're interested in
  • c: the column you're interested in(0-3)
  • type: 数据类型(float, int, char ect..)
  • i: 你感兴趣的行
  • Nc: 通道数
  • j:您感兴趣的列
  • c:您感兴趣的列(0-3)

For information on other c->c++ conversion check out this link: Source

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