OpenCV Mat data member access
Mat
data is an uchar*
. If you have a, say, float matrix CV_32FC1
, you need to access data as float
.
You can do in different ways, not necessarily using casting:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
cv::Mat matF(3, 3, CV_32F);
randu(matF, Scalar(0), Scalar(10));
int rowIdx = 1;
int colIdx = 1;
// 1
float f1 = matF.at<float>(rowIdx, colIdx);
// 2
float* fData2 = (float*)matF.data;
float f2 = fData2[rowIdx*matF.step1() + colIdx];
// 3
float* fData3 = matF.ptr<float>(0);
float f3 = fData3[rowIdx*matF.step1() + colIdx];
// 4
float* fData4 = matF.ptr<float>(rowIdx);
float f4 = fData4[colIdx];
// 5
Mat1f mm(matF); // Or directly create like: Mat1f mm(3, 3);
float f5 = mm(rowIdx, colIdx);
// f1 == f2 == f3 == f4 == f5
return 0;
}
Notes
- it's better to use
step1()
instead ofcols
when accessing directlydata
through pointers, since the image may not be continuous. Check here for more details. - The snippet is adapted from this my other answer
Convert Mat to Array/Vector in OpenCV
If the memory of the Mat mat
is continuous (all its data is continuous), you can directly get its data to a 1D array:
std::vector<uchar> array(mat.rows*mat.cols*mat.channels());
if (mat.isContinuous())
array = mat.data;
Otherwise, you have to get its data row by row, e.g. to a 2D array:
uchar **array = new uchar*[mat.rows];
for (int i=0; i<mat.rows; ++i)
array[i] = new uchar[mat.cols*mat.channels()];
for (int i=0; i<mat.rows; ++i)
array[i] = mat.ptr<uchar>(i);
UPDATE: It will be easier if you're using std::vector
, where you can do like this:
std::vector<uchar> array;
if (mat.isContinuous()) {
// array.assign(mat.datastart, mat.dataend); // <- has problems for sub-matrix like mat = big_mat.row(i)
array.assign(mat.data, mat.data + mat.total()*mat.channels());
} else {
for (int i = 0; i < mat.rows; ++i) {
array.insert(array.end(), mat.ptr<uchar>(i), mat.ptr<uchar>(i)+mat.cols*mat.channels());
}
}
p.s.: For cv::Mat
s of other types, like CV_32F
, you should do like this:
std::vector<float> array;
if (mat.isContinuous()) {
// array.assign((float*)mat.datastart, (float*)mat.dataend); // <- has problems for sub-matrix like mat = big_mat.row(i)
array.assign((float*)mat.data, (float*)mat.data + mat.total()*mat.channels());
} else {
for (int i = 0; i < mat.rows; ++i) {
array.insert(array.end(), mat.ptr<float>(i), mat.ptr<float>(i)+mat.cols*mat.channels());
}
}
UPDATE2: For OpenCV Mat data continuity, it can be summarized as follows:
- Matrices created by
imread()
,clone()
, or a constructor will always be continuous. - The only time a matrix will not be continuous is when it borrows data (except the data borrowed is continuous in the big matrix, e.g. 1. single row; 2. multiple rows with full original width) from an existing matrix (i.e. created out of an ROI of a big mat).
Please check out this code snippet for demonstration.
Copying OpenCV mat to a known address with memcpy
Ok. I solved this issue ;
Mat img = Mat(height, width, CV_8UC4, address);
cv::imshow("Image from GM", img);
// same image copy to buffer back;
memcpy(&address[0], &img.data[0], width*height*4.);
What is the most efficient matrix representation in C++?
Unless you do some weird stuff (see here for details), data in a Mat
are guaranteed to be continuous. You can think of a Mat
as a lightweight wrapper over a float*
(or other types) that allows easier access to the data. So it's as efficient as a pointer, but with a few nice-to-have abstractions.
If you need to efficiently load/save from/to file, you can save the Mat
in binary format using matread
and matwrite
.
OpenCV : What is the real performance difference between continuous and non-continuous matrices?
Well, it mostly depends on how you'll use your matrices. If you're doing a lot of "jumping" anyways - it won't make much difference, but in 'continuous' use cases, it will matter a few dozens of percents.
The following example (which simply shifts the matrices values) gives me an output:
image.isContinuous() = 1
roi.isContinuous() = 0
image: 0.0162504 s
roi: 0.0219723 s
Sanity check: OK
Which is about 30% difference. Your millage will vary depending on the hardware and actual use cases.
Source (notice how the first loop is much simpler in that case):
#include <opencv2/core/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
int cols = 4096;
int rows = 4096;
int scale = 2;
Mat image(rows, cols, CV_8UC1);
Mat image_big(rows * scale, cols * scale, CV_8UC1);
Mat roi = image_big(Rect(0, 0, cols, rows));
randu(image, 0, 255);
image.copyTo(roi);
cout << "image.isContinuous() = " << image.isContinuous() << "\n" << "roi.isContinuous() = " << roi.isContinuous() << endl;
{
cout << "image: ";
double start = getTickCount();
for (int i = 1; i < image.total(); i++)
{
image.data[i - 1] = image.data[i];
}
cout << (getTickCount() - start)/getTickFrequency() << " s" << endl;
}
{
cout << "roi: ";
double start = getTickCount();
for (int y = 0; y < roi.cols; y++)
{
if (y != 0) {
roi.ptr<char>(y-1)[roi.cols-1] = roi.ptr<char>(y)[0];
}
for (int x = 1; x < roi.rows; x++)
{
roi.ptr<char>(y)[x - 1] = roi.ptr<char>(y)[x];
}
}
cout << (getTickCount() - start)/getTickFrequency() << " s" << endl;
}
cout << "Sanity check: " << (countNonZero(image - roi) ? "FAIL" : "OK") << endl;
}
convert Mat to memory in opencv by using c++
Mat is also two dimensional array covered by class. If you need data in it, you can access it with Mat::at(int x, int y) method. Or copy raw data:
cv::Mat matrix;
float *new_data = new float[matrix.rows*matrix.cols];
float *p = new_data;
for(int i = 0; i < matrix.rows; i++){
memcpy(p, matrix.ptr(i), matrix.cols*sizeof(float));
p += matrix.cols;
}
Related Topics
Switch Passed Type from Template
Header File Inclusion Static Analysis Tools
"Roll-Back" or Undo Any Manipulators Applied to a Stream Without Knowing What the Manipulators Were
Std::Ofstream, Check If File Exists Before Writing
How to Do a #Define Inside of Another #Define
Fatal Error: iOStream.H No Such File or Directory
How to Enable /Std:C++17 in VS2017 with Cmake
Ad Hoc Polymorphism and Heterogeneous Containers with Value Semantics
When to Use Extern "C" in Simple Words
How to Get the Icon, Mime Type, and Application Associated with a File in the Linux Desktop
How to Use Sendinput Function C++
How to Execute a Piece of Code Only Once
A Simple Hello World Npapi Plugin for Google Chrome
What Is Use of the Ref-Qualifier 'Const &&'
Does Auto Deduce the Type at Compile Time or Runtime in C++ 11
How to Create Objects While Adding Them into a Vector