我是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 ++中是否有一些我不知道的内容?
答案 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。