C ++从数组中快速保存图像的方法

时间:2017-06-12 14:34:49

标签: c++ opencv image-processing bitmap cimg

现在,我正在使用CImg。 由于this问题,我无法使用OpenCV。

我的CImg代码如下所示:

cimg_library::CImg<float> img(512,512); 
cimg_forXYC(img,x,y,c) { img(x,y,c) = (array[x][y]); } //array contains all float values between 0/1
img.save(save.c_str()); //taking a  lot of time

通过使用时钟,我能够确定第一步,for循环需要0-0.01秒。但是,第二步,即保存图像,需要0.06秒,由于我拥有的图像数量太长,这一点太长了。

我正在保存为位图。 在C ++中有没有更快的方法来完成相同的事情(从值数组创建图像并保存)?

2 个答案:

答案 0 :(得分:0)

这是一个小功能,可以将您的图像保存在pgm format中,大多数事情都可以读取并且很简单。它需要你的编译器支持C ++ 11,大多数都支持。它也被硬编码为512x512图像。

#include <fstream>
#include <string>
#include <cmath>
#include <cstdint>

void save_image(const ::std::string &name, float img_vals[][512])
{
   using ::std::string;
   using ::std::ios;
   using ::std::ofstream;
   typedef unsigned char pixval_t;
   auto float_to_pixval = [](float img_val) -> pixval_t {
      int tmpval = static_cast<int>(::std::floor(256 * img_val));
      if (tmpval < 0) {
         return 0u;
      } else if (tmpval > 255) {
         return 255u;
      } else {
         return tmpval & 0xffu;
      }
   };
   auto as_pgm = [](const string &name) -> string {
      if (! ((name.length() >= 4)
             && (name.substr(name.length() - 4, 4) == ".pgm")))
      {
         return name + ".pgm";
      } else {
         return name;
      }
   };

   ofstream out(as_pgm(name), ios::binary | ios::out | ios::trunc);

   out << "P5\n512 512\n255\n";
   for (int x = 0; x < 512; ++x) {
      for (int y = 0; y < 512; ++y) {
         const pixval_t pixval = float_to_pixval(img_vals[x][y]);
         const char outpv = static_cast<const char>(pixval);
         out.write(&outpv, 1);
      }
   }
}

答案 1 :(得分:0)

与@ Omnifarious的回答类似,对于像你这样的浮动数据,有一种非常简单的格式(也基于NetPBM概念)。它被称为PFM,并记录在案here

好处是 CImg ImageMagick 能够读取和编写格式而无需任何其他库,无需编写任何代码!另一个好处是您可以保留浮动的完整色调范围,而不仅仅是256步。在缺点方面,您需要每像素完整的4个字节而不是1个字节。

所以,你的代码将成为:

CImg<float> img(512,512); 
cimg_forXYC(img,x,y,c) { img(x,y,c) = (array[x][y]); }
img.save_pfm("filename.pfm");

我通过创建10,000个图像并使用以下代码将它们保存到磁盘来对此进行基准测试:

#include <iostream>
#include <cstdlib>
#define cimg_display 0        // No need for X11 stuff
#include "CImg.h"

using namespace cimg_library;
using namespace std;

#define W   512
#define H   512
#define N   10000

int main() {
    // Create and initialise float image with radial gradient
   cimg_library::CImg<float> img(W,H); 
   cimg_forXY(img,x,y) {img(x,y) = hypot((float)(W/2-x),(float)(H/2-y)); }

   char filename[128];
   for(int i=0;i<N;i++){
      sprintf(filename,"f-%06d.pfm",i);
      img.save_pfm(filename);
   }
}

它运行21.8秒,即每张图像2.1毫秒(0.002秒)。

正如我之前提到的, ImageMagick 也能够处理PFM格式,因此您可以使用 GNU Parallel ImageMagick mogrify将这些图片转换为JPEG

parallel -X mogrify -format jpg -auto-level ::: *pfm

对于原始10,000张图像,需要22秒,或2.2毫秒/图像。

enter image description here