将线性阵列转换为二维矩阵
Convert linear Array to 2D Matrix
我得到了一个浮点指针(数组),它表示一个图像。它的元素计数和索引具有宽度*高度。图像不像一个矩阵,它的原点在左上角。相反,它的原点在左下角,就像在圆括号坐标系中一样。达到最大宽度后,它从左侧的下一行开始。
所以我想有效地将这个数组转换为2D矩阵(可选:opencv)。
我该如何以良好和有效的方式做到这一点?我该如何将其转换回?
提前谢谢。
我会在湖中扔一块石头,看着涟漪。注意:我不知道调用者希望对xformed数据做什么,这主要是因为我对OpenCV的知识还不成熟。然而,转型的核心问题似乎很直接。如果我偏离了底线,请留下评论,我会放弃答案。我提出了两种方法,一种用于数据反转,另一种用于使用C++类的简单访问器包装。
内嵌反转:如果调用方需要反转行以适应传递给API的使用,则可以就地完成。只要确保在使用反转数据后再次执行即可。一个纯粹面向字节的例子是:
// in-place inversion of the linear matrix to re-origin.
void mat_invert(float *data, size_t height, size_t width)
{
// must be at least 2 rows high for this to mean anything.
if (height < 2)
return;
// setup a pair of pointers to walk the rows in byte-form
unsigned char* top = (unsigned char*)data;
unsigned char *bottom = (unsigned char *)(data + (height-1)*width);
size_t row_width = sizeof(data[0]) * width;
while (top < bottom)
{
for (size_t i=0; i<row_width; i++)
{
*top ^= *bottom;
*bottom ^= *top;
*top++ ^= *bottom++;
}
bottom -= 2*row_width;
}
}
示例用法:
int main(int argc, char *argv[])
{
const size_t w = 10;
const size_t h = 5;
float ar[h*w];
memset(ar, 0, sizeof(ar));
ar[0] = 0.1;
ar[1*w + 1] = 1.1;
ar[2*w + 2] = 2.1;
ar[3*w + 3] = 3.1;
ar[4*w + 4] = 4.1;
// dump original
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// invert original
mat_invert(ar, h, w);
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// invert again
mat_invert(ar, h, w);
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
return EXIT_SUCCESS;
}
结果:
0.1 0 0 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0.1 0 0 0 0 0 0 0 0 0
0.1 0 0 0 0 0 0 0 0 0
0 1.1 0 0 0 0 0 0 0 0
0 0 2.1 0 0 0 0 0 0 0
0 0 0 3.1 0 0 0 0 0 0
0 0 0 0 4.1 0 0 0 0 0
隐式访问类:如果您所需要的只是为您完成虚拟行/高度计算,那么以下内容就足够了:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
class matrix_xform
{
private:
size_t width, height;
float *data;
public:
matrix_xform(float *data, size_t height, size_t width)
: data(data), width(width), height(height)
{
}
float * operator[](size_t x)
{
if (x > (height-1))
throw std::out_of_range("matrix_xform[x]");
return data + (width * (height - 1 - x));
}
const float * operator[](size_t x) const
{
if (x > (height-1))
throw std::out_of_range("matrix_xform[x]");
return data + (width * (height - 1 - x));
}
};
示例用法:
int main(int argc, char *argv[])
{
const size_t w = 10;
const size_t h = 5;
float ar[h*w];
memset(ar, 0, sizeof(ar));
matrix_xform mat(ar, h, w);
mat[0][0] = 1.0;
mat[1][1] = 1.0;
mat[2][2] = 1.0;
mat[3][3] = 1.0;
mat[4][4] = 1.0;
// dump original
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << ar[i*w+j] << ' ';
cout << endl;
}
cout << endl;
// dump using accessor
for (size_t i=0; i<h; i++)
{
for (size_t j=0; j<w; j++)
cout << mat[i][j] << ' ';
cout << endl;
}
return EXIT_SUCCESS;
}
结果:
0 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
我希望它能覆盖OP正在寻找的每一个基地。
将图像处理API规划为
void my_func (int *src, int *dst, int x_stride, int y_stride, int N);
使其易于在连续内存中迭代,同时在左<->之间切换扫描方向对,但也在向上<->之间向下
如果API被设计用于不同的输入&输出跨步,还可以更改每个图像元素的字节数(例如,将颜色模式从RGBA更改为RGB,或从24位RGB更改为16位R5G6B5,从int更改为float等),也可以更改图像宽度(和高度…)。
重点是,无论图像的每一行的位置如何,数学都应该是相同的。
其中一个功能可以是:
copy_row(int *src, int* dst, int N, int x_stride);
copy_2D_mem(int *src_base, int* dst_base, int N, int M, int y_stride, int x_stride);
再说一遍,许多现有的opencv算法很可能不关心图像的方向。写自己的文章,也可以采用同样的方法。
根据我的理解,您需要将数组传递给OpenCV API,以便它将其解释为(top,left)
索引的二维矩阵。一个简单的方法可以在不重新排列任何阵列的情况下做到这一点,如以下示例所示:
float a[8] = {1,2,3,4,5,6,7,8}; //your array containing the image
int img_width = 2;
int img_height = 4;
float** b = new float*[img_height];
for(int i=img_height ; i>0; i--)
b[img_height-i] = a+ (i-1)*img_width;
//call your API
do_something(b,img_height,img_width);
//your OpenCV API that expects a 2-d matrix
void do_something(float** x , int r, int c){};
如果需要,可以将其转换为一个方便的函数/宏,在调用OpenCV API之前,可以调用该函数/宏以获得所需格式的二维矩阵。此外,完成后,不要忘记为为此目的创建的临时数组取消分配内存。
- 将二维矢量传递给类
- 将值从二维数组输出到文本文件
- 我在二维向量中是否正确分配了内存
- 带结构的二维矢量:如何存储元素
- 在二维数组中查找最小值和最大值?
- 移动二维数组中的字符
- C++ 传递二维字符数组
- 如何正确填充在堆上分配的二维数组?
- 传递二维数组时出现问题
- 具有随机数的二维数组不会更改
- 如何在C++中获取二维数组中最少的一列数?
- 如何使用用户输入变量制作二维数组?
- C++ 中的二维整数数组,每行中的元素数量不均匀
- C++ 中动态二维数组的访问冲突
- 在二维向量或数组中可以存储的最大元素数是多少?
- 如何将整数字符串转换为整数的二维向量?
- 通过访问二维数组实现双线性插值的概念类似于一维数组
- 使用c/awk/shell对二维数据进行双线性插值
- 将线性阵列转换为二维矩阵
- 检查二维向量的正线性组合