C++ 将线性阵列转换为二维矩阵

C++ 将线性阵列转换为二维矩阵,c++,opencv,C++,Opencv,我得到了一个表示图像的浮点指针(数组)。 它的元素计数和索引的宽度*高度。 图像不像矩阵,其原点位于左上角。 相反,它的原点在左下角,就像在卡瑟斯坐标系中一样。 达到最大宽度后,它将从左侧的下一行开始 所以我想高效地将这个数组转换成2D矩阵(可选:opencv) 我如何以良好有效的方式做到这一点? 我怎么把它转换回来 提前感谢。将图像处理API规划为 void my_func (int *src, int *dst, int x_stride, int y_stride, int N); 使

我得到了一个表示图像的浮点指针(数组)。 它的元素计数和索引的宽度*高度。 图像不像矩阵,其原点位于左上角。 相反,它的原点在左下角,就像在卡瑟斯坐标系中一样。 达到最大宽度后,它将从左侧的下一行开始

所以我想高效地将这个数组转换成2D矩阵(可选:opencv)

我如何以良好有效的方式做到这一点? 我怎么把它转换回来


提前感谢。

将图像处理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,以便它将其解释为
(左上)
索引的二维矩阵。下面的示例演示了一种在不重新排列任何阵列的情况下执行此操作的简单方法:

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之前,可以调用该函数/宏以获得所需格式的二维矩阵。此外,在完成任务后,不要忘记为为此目的创建的临时阵列取消分配内存

我要在湖里扔一块石头,看看涟漪。注意:我不知道调用方希望如何处理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;
    }
}

隐式访问类:如果您只需要为您完成虚拟化的行/高度计算,那么以下内容就足够了:

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

我希望这涵盖了OP所寻找的每一个基础。

这纯粹是为了解决位置(x,y)处的单个元素,因为没有更好的术语吗?或者是打算稍后将此数据传递给未命名的函数,这些函数希望数据位于左上角矩阵布局中。它起到了不同的作用(一个是数学,另一个是移动内存)。目的是,我想用opencv处理图像数据。所以我需要“数学”的东西。在做了数学等之后,我想把它转换回你所说的“移动内存”系统。如果OP想在自己的代码中使用矩阵访问转换后的矩阵,你的解决方案非常有效,但他无法将您的包装器类对象传递给可能需要二维浮点数组作为参数的外部API。编辑以添加就地反转例程,
mat\u invert()
。希望这涵盖了OP需要的所有基础。
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