将线性数组转换为2D矩阵 [英] Convert linear Array to 2D Matrix

查看:94
本文介绍了将线性数组转换为2D矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个浮点指针(数组),它代表一张图像. 它的元素数量和索引的宽度*高度. 图像与矩阵不同,它的原点位于左上方. 相反,它的原点位于左下角,例如在笛卡尔坐标系中. 达到最大宽度后,它将在左侧开始下一行.

I got an float pointer (array), which represents an image. It's elements count and index has width*height. The image is not like a matrix, which has it's origin at the upper left. Instead it has the origin in the lower left, like in the carthesian coordinate system. After reaching the max-width, it starts it's next row at the left side.

所以我想有效地将​​此数组转换为2D矩阵(可选:opencv).

So I want to efficiently convert this array to a 2D matrix (optional: opencv).

我该如何以一种有效的方式做到这一点? 以及如何将其转换回去?

How do I do that in a good and effective manner? And how do I convert it back?

谢谢.

推荐答案

我将在岩石上扔一块石头,看着涟漪.注意:我不知道调用者希望使用xformed数据做什么,这主要是由于我对OpenCV尚不了解.但是,转型的核心问题似乎很直截了当.如果我离基地很远,请发表评论,然后我放弃答案.我提出了两种方法,一种用于就地进行数据倒置,另一种用于使用C ++类进行简单的访问器包装.

I'll throw a rock in the lake and watch the ripples. Note: I have no idea what the caller expects to do with the xformed data, mostly due to my fledgling knowledge of OpenCV. However the core question of transformation seemed pretty straight forward. If I'm way off-base kindly leave a comment and I'll drop the answer. I propose two approaches, one for data inversion in-place, and one for simple accessor wrapping using a C++ class.

就地反转:如果调用方需要反转行以适应传递给API的用法,则可以就地完成.使用反转数据完成操作后,只需确保再次执行此操作即可.纯粹面向字节的示例是:

In-place Inversion: If the caller needs to invert the rows to accommodate usage for passing to an API, it can be done in place. Just be sure to do it again once you're done using the inverted data. An example purely byte-oriented is:

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


隐式访问类:如果您所需要做的只是为您完成了虚拟化的行/高度数学计算,那么就可以做到这一点:


Implicit Access Class: If all you need is virtualized row/height math done for you, the following will suffice to do just that:

#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寻找的所有基础.

I hope that covers every base the OP is looking for.

这篇关于将线性数组转换为2D矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆