Opencv Multi Channel Element Access

opencv multi channel element access

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

1. choose one type to represent the element

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.

CV_32FC2 means the element is 32bit floating point value with 2 channels.

So elem in above code is one acceptable representation of 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 :

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 :

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

2. access the element

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

It has 4 overloads :

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

Mat provides 2 conversion functions:

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

Accessing elements in a multi-channel OpenCV Mat

The first element of a cv::Mat is always at (0, 0), so just correct cv::Vec3f elem = rgb_m.at<cv::Vec3f>(1, 1); by cv::Vec3f elem = rgb_m.at<cv::Vec3f>(0, 0); and cv::Vec3f elem2 = lab_m.at<cv::Vec3f>(1, 1); by cv::Vec3f elem2 = lab_m.at<cv::Vec3f>(0, 0);

opencv matrix multi channel access and fill

As mentioned earlier, pixels next to the high-intensity pixel take non-zero values after JPG-compression because JPEG is a lossy algorithm. In fact, JPEG-compression discards information precisely in image regions with strong gradient.

As for your second question: your pixels are blue because of an Opencv quirk: color channels are not stored in R, G, B order, but in B, G, R order:

For color images, the channel ordering is normally Blue, Green, Red

Source: http://docs.opencv.org/modules/core/doc/drawing_functions.html?highlight=green

(this is one of those things that make life miserable for the Opencv programmer)

how to access nth channel of a Mat in opencv?

Let's say n = 10 and we want to access 4th channel of pixel (i, j). Here's a simple example:

typedef cv::Vec<uchar, 10> Vec10b;

// ....

// Create the mat
cv::Mat_<Vec10b> some_mat;

// Access 4th channel
uchar value = some_mat.at<Vec10b>(i,j)(4);

// or
uchar value = some_mat.at<Vec10b>(i,j)[4];

Hope this helps you. Notice that you can omit the typedef line, I just think it's easier this way.

OpenCV (c++) multi channel element access

Shouldn't you be using Vec3b instead of Vec3i ?

CV_8UC3 means your image is 8 bit, 3 channels, unsigned char. While Vec3iis for 3 channels integers and Vec3bis for 3 channels unsigned char.

So I think you should be using Vec3b

Accessing Whole Channel in a multi channel array in opencv

Just use split and merge

Mat RGB // source mat
Mat BGR_3[3];
split(RGB,RGB_3);
BGR_3[0]//do some operation Blue channel
BGR_3[1]//do some operation Green Channel
BGR_3[2]//do some operation Red channel

//later merge
Mat dst
merge(BGR_3,3,dst);

Access multiple channels in OpenCV Mat

I think you are searching for the following:

 cv::Mat M(10, 3, CV_32SC3);
cv::Mat_<cv::Vec3d> helpimg = M;
helpimg .row(0).begin()[0][0] = 2.5;

I can compile it but i didn't test it. Tell if it works. You could use it also to get the cols values:

 helpimg .col(0).begin()[0][0] = 4.5;

Initialize a Multi-Channel OpenCV Mat

I was trying to use OpenCV's Vec_ and Mat_ template classes, because of this Mat_ constructor. Unfortunately, I couldn't find a working solution. All attempts lead to the same error, you already came across with. So, my guess would be, the underlying OpenCV implementation just does not support such actions, even on custom derived types.

Certainly, you have your own idea to work-around this. Nevertheless, I wanted to provide the shortest (and hopefully most efficient) solution, I could think of:

const int levels = 20;
const cv::Size size = cv::Size(123, 234);

const cv::Mat proto = cv::Mat(size, CV_16SC1, 1000);

std::vector<cv::Mat> channels;
for (int i = 0; i < levels; i++)
channels.push_back(proto);

cv::Mat A;
cv::merge(channels, A);

Mat access element OpenCV2.3

http://aishack.in/tutorials/opencvs-c-interface/

Mat a= Mat(4,3, CV_32FC1);

float elem_a= a.at(i,j); //access element aij, with i from 0 to
rows-1 and j from 0 to cols-1



Related Topics



Leave a reply



Submit