高效的图像到矩阵转换

时间:2017-10-26 08:18:56

标签: c++ image matrix

我是c ++的初学者(主要使用Python),我还不知道如何正确地做事。我希望随着时间的推移将一些彩色图像作为信号处理,为了做到这一点,我希望它们是双矩阵。

灰度图像将是1d向量,从左上角到右下角,彩色图像将是2d向量,第二维度是3种颜色。也就是说,我想将图像展平为一个长向量,其中包含带有rgb信息的3个向量。

我使用dlib打开图片,如下所示:

#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
#include <dlib/image_transforms.h>

using namespace dlib;

array2d<rgb_pixel> img;
load_image(img, image_name);

这给了我一个包含像素结构的dlib array2d。现在,我想将其更改为展平图像。我想,由于图像尺寸可能会改变,我会使用

std::vector<std::vector<double>> 

作为我的矩阵。

转换它的天真方式如下:

#include <vector>
#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
#include <dlib/image_transforms.h>


std::vector<std::vector<double>> image_to_frame(array2d<rgb_pixel> const &image)
{
    const int total_num_of_px = image.nc() * image.nr();
    std::vector<std::vector<double>> frame = std::vector<std::vector<double>>(total_num_of_px);
    for (int i = 0; i < image.nr(); i++) 
    {
        for (int j = 0; j < image.nc(); j++)
        {
            frame[(i+1)*j] = std::vector<double>(3);
            frame[(i + 1)*j][0] = (double)image[i][j].red;
            frame[(i + 1)*j][1] = (double)image[i][j].green;
            frame[(i + 1)*j][2] = (double)image[i][j].blue;
        }
    }
    return frame;
}

但1280x720图像需要8秒钟。在我看来有点长。有一个更好的方法吗?将array2d转换为向量矩阵的更有效方法?

或者是否存在比矢量矩阵更有效的数据结构?或者我应该不使用dlib并以另一种方式打开图像以便更容易转换?

在Python中,我可以直接打开图像作为numpy数组,然后进行重塑,这非常快。在c ++中是否有一些我不知道的内容?

1 个答案:

答案 0 :(得分:1)

从API看起来dlib中的图像与OpenCV中的图像完全一样(dlib :: toMat通过重用相同的内存来转换它)。这意味着您可以获取指向array2d的第一个元素的指针,然后将其重新解释为指向结构{uchar r,uchar g,uchar b}(或任何您想要的)的指针,其长度将为nc * nr。在这里,您可以使用memcpy复制整个缓冲区。

但我真的不明白你为什么需要它,因为行是连续存储的,所以你不应该指望任何缓存未命中。

更新:同样,cmon,你的程序浪费的一半时间将uchars转换为双打。你不应该使用double来保存RGB。默认情况下有无符号字符。

UPDATE2:

struct rgb
{
    uchar r, g, b;
};

rgb* data = reinterpret_cast<rgb*>(&frame[0][0]);
std::vector<rgb> vect;
std::copy(data, data + nc * nr * sizeof(rgb), std::back_inserter(vect));

之后,您将图像的矢量平铺,直接存储在一块存储器中。如果您不需要副本,则只需使用data指针即可。

此外,如果您想要类似索引的访问权限,则可以使用uchar[3]代替rgb struct。