我是OpenCV的新手。最近,我遇到了麻烦,发现OpenCV函数将从Mat转换为Array。我用OpenCV API中提供的.ptr和.at方法进行了研究,但我无法获得正确的数据。我想直接从Mat转换为Array(如果可用,如果不是Vector)。我需要OpenCV功能,因为代码必须在Vivado HLS中进行高级综合。请帮忙。在OpenCV中将矩阵转换为阵列/向量
23
A
回答
55
如果Mat mat
的内存是连续的(其所有的数据是连续的),你可以直接得到它的数据为一维数组:
std::vector<uchar> array(mat.rows*mat.cols);
if (mat.isContinuous())
array = mat.data;
否则,您必须按行来获取其数据行,例如以二维数组:
uchar **array = new uchar*[mat.rows];
for (int i=0; i<mat.rows; ++i)
array[i] = new uchar[mat.cols];
for (int i=0; i<mat.rows; ++i)
array[i] = mat.ptr<uchar>(i);
UPDATE:
std::vector<uchar> array;
if (mat.isContinuous()) {
array.assign(mat.datastart, mat.dataend);
} else {
for (int i = 0; i < mat.rows; ++i) {
array.insert(array.end(), mat.ptr<uchar>(i), mat.ptr<uchar>(i)+mat.cols);
}
}
PS:如果你使用std::vector
,在这里你可以这样做会更容易为cv::Mat
S的其他类型,如CV_32F
,你应该这样做:
std::vector<float> array;
if (mat.isContinuous()) {
array.assign((float*)mat.datastart, (float*)mat.dataend);
} else {
for (int i = 0; i < mat.rows; ++i) {
array.insert(array.end(), mat.ptr<float>(i), mat.ptr<float>(i)+mat.cols);
}
}
3
0
byte * matToBytes(Mat image)
{
int size = image.total() * image.elemSize();
byte * bytes = new byte[size]; //delete[] later
std::memcpy(bytes,image.data,size * sizeof(byte));
}
+0
虽然这段代码可能会回答这个问题,但提供关于此代码为何和/或如何回答此问题的其他上下文会提高其长期价值。 – ryanyuyu 2016-03-16 21:33:39
4
0
无的提供的例子在这里的工作一般情况下,这是N维矩阵。任何使用“行”的东西只是假设列和行,4维矩阵可能会有更多。
下面是一些示例代码复制的非连续的N维矩阵划分成连续的存储器流 - 然后将其转换回简历::垫
#include <iostream>
#include <cstdint>
#include <cstring>
#include <opencv2/opencv.hpp>
int main(int argc, char**argv)
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <Image_Path>\n";
return -1;
}
cv::Mat origSource = cv::imread(argv[1],1);
if (!origSource.data) {
std::cerr << "Can't read image";
return -1;
}
// this will select a subsection of the original source image - WITHOUT copying the data
// (the header will point to a region of interest, adjusting data pointers and row step sizes)
cv::Mat sourceMat = origSource(cv::Range(origSource.size[0]/4,(3*origSource.size[0])/4),cv::Range(origSource.size[1]/4,(3*origSource.size[1])/4));
// correctly copy the contents of an N dimensional cv::Mat
// works just as fast as copying a 2D mat, but has much more difficult to read code :)
// see http://stackoverflow.com/questions/18882242/how-do-i-get-the-size-of-a-multi-dimensional-cvmat-mat-or-matnd
// copy this code in your own cvMat_To_Char_Array() function which really OpenCV should provide somehow...
// keep in mind that even Mat::clone() aligns each row at a 4 byte boundary, so uneven sized images always have stepgaps
size_t totalsize = sourceMat.step[sourceMat.dims-1];
const size_t rowsize = sourceMat.step[sourceMat.dims-1] * sourceMat.size[sourceMat.dims-1];
size_t coordinates[sourceMat.dims-1] = {0};
std::cout << "Image dimensions: ";
for (int t=0;t<sourceMat.dims;t++)
{
// calculate total size of multi dimensional matrix by multiplying dimensions
totalsize*=sourceMat.size[t];
std::cout << (t>0?" X ":"") << sourceMat.size[t];
}
// Allocate destination image buffer
uint8_t * imagebuffer = new uint8_t[totalsize];
size_t srcptr=0,dptr=0;
std::cout << std::endl;
std::cout << "One pixel in image has " << sourceMat.step[sourceMat.dims-1] << " bytes" <<std::endl;
std::cout << "Copying data in blocks of " << rowsize << " bytes" << std::endl ;
std::cout << "Total size is " << totalsize << " bytes" << std::endl;
while (dptr<totalsize) {
// we copy entire rows at once, so lowest iterator is always [dims-2]
// this is legal since OpenCV does not use 1 dimensional matrices internally (a 1D matrix is a 2d matrix with only 1 row)
std::memcpy(&imagebuffer[dptr],&(((uint8_t*)sourceMat.data)[srcptr]),rowsize);
// destination matrix has no gaps so rows follow each other directly
dptr += rowsize;
// src matrix can have gaps so we need to calculate the address of the start of the next row the hard way
// see *brief* text in opencv2/core/mat.hpp for address calculation
coordinates[sourceMat.dims-2]++;
srcptr = 0;
for (int t=sourceMat.dims-2;t>=0;t--) {
if (coordinates[t]>=sourceMat.size[t]) {
if (t==0) break;
coordinates[t]=0;
coordinates[t-1]++;
}
srcptr += sourceMat.step[t]*coordinates[t];
}
}
// this constructor assumes that imagebuffer is gap-less (if not, a complete array of step sizes must be given, too)
cv::Mat destination=cv::Mat(sourceMat.dims, sourceMat.size, sourceMat.type(), (void*)imagebuffer);
// and just to proof that sourceImage points to the same memory as origSource, we strike it through
cv::line(sourceMat,cv::Point(0,0),cv::Point(sourceMat.size[1],sourceMat.size[0]),CV_RGB(255,0,0),3);
cv::imshow("original image",origSource);
cv::imshow("partial image",sourceMat);
cv::imshow("copied image",destination);
while (cv::waitKey(60)!='q');
}
0
cv::Mat m;
m.create(10, 10, CV_32FC3);
float *array = (float *)malloc(3*sizeof(float)*10*10);
cv::MatConstIterator_<cv::Vec3f> it = m.begin<cv::Vec3f>();
for (unsigned i = 0; it != m.end<cv::Vec3f>(); it++) {
for (unsigned j = 0; j < 3; j++) {
*(array + i) = (*it)[j];
i++;
}
}
Now you have a float array. In case of 8 bit, simply change float to uchar and Vec3f to Vec3b and CV_32FC3 to CV_8UC3
相关问题
- 1. 将矩阵列表转换为向量
- 2. 将openCV矩阵转换为矢量
- 3. 如何在MATLAB中将阵列向量转换为矩阵
- 4. 将索引向量转换为矩阵
- 5. 将行向量转换为矩阵
- 6. 将列转换为矩阵
- 7. Opencv:将RGB矩阵转换为1d阵列
- 8. 将矩阵转换为1维阵列
- 9. 将阵列数组转换为矩阵
- 10. 向量转换与矩阵
- 11. 将矩阵转换为R中的向量列表
- 12. 如何将列矩阵转换为行矩阵在MATLAB
- 13. 将char的矩阵转换为日期的列向量
- 14. 如何将列向量转换为矩阵的对角线?
- 15. 转换为单列矩阵
- 16. 将矢量转换为矩阵
- 17. 将矢量转换为逻辑矩阵
- 18. 将matlab矩阵转换为矢量
- 19. 将RleViews转换为矩阵
- 20. 将矩阵市场转换为CRS转换(稀疏矩阵)
- 21. 转换向量单元阵列到二维矩阵 - MATLAB
- 22. 如何在MATLAB中将灰度矩阵转换为RGB矩阵?
- 23. 在特征中将动态矩阵转换为固定矩阵
- 24. 将列表转换为numpy矩阵
- 25. 将列表转换为稀疏矩阵
- 26. 将嵌套列表转换为矩阵
- 27. 如何将列表转换为矩阵?
- 28. 将矩阵转换为R中的向量数
- 29. 图像转换矩阵OpenCV中
- 30. 将转换矩阵应用于opencv中的点列表(Python)
更好如果使用一个std: :向量。用裸指针你也可以释放内存。 – madduci 2015-01-19 12:20:32
@blackibiza好点。更新了使用'std :: vector'的答案。 :-) – herohuyongtao 2015-01-19 13:00:45
我猜''mat.cols'应该乘以'mat.channels'复制数据'array.insert'。使用float作为模板参数时,也可以省略从'uchar *'到'float *'的转换:'mat.ptr' –
2017-03-07 09:36:59