访问像素值而不在内存中加载图像以获取大图像

时间:2013-11-26 17:40:46

标签: c++ image cimg

我需要使用CImg库来计算图像的平均值,如下所示:

int i = 0;
float mean = 0;
CImg<float> img("image.cimg");  
float *ptr = img.data(); //retrieves pointer to the first value
while(i<img.width()*img.height()*img.spectrum()){
    mean += *(ptr+i);
    ++i;
}
std::cout << "mean: " << mean/i << std::endl;

我知道img.mean()可以解决问题,但在这里我想以低级别的方式进行。

当图像的大小增加太多时,我的代码中的第3行占用了太多的计算机资源,因为根据documentation它同时将所有图像像素存储在内存缓冲区中

我想到了一个更低级别的解决方案,使用系统调用open()read(),如下所示:

int i = 0;
int k = WIDTH*HEIGHT*SPECTRUM; //assuming this values are known
float mean = 0, aux;
int fd = open("image.cimg", O_RDONLY);
while(i<k){ 
    read(fd, &aux, sizeof(float));
    mean += aux; 
    ++i;
}
close(fd);
std::cout << "mean: " << mean/i << std::endl;

但现在获得的结果没有任何意义。我想知道这个解决方案是否有意义,如果图像以与加载到内存时相同的方式存储在磁盘上,并且如果最终这个解决方案可以节省时间和内存。

1 个答案:

答案 0 :(得分:1)

问题是代码的第二行,因为您已将mean(虽然名称sum更好地命名)为简单float。由于图片中的每个像素也是float,如果您的图片是10,000x10,000,则会遇到问题,因为您会尝试将100M float的总和存储在{ {1}}。

最简单的解决方案是将第2行更改为:

float

作为替代方案,您可以逐步计算平均值,而不会像这样溢出:

double mean=0;

顺便说一下,如果你有非常大的图像,我可以推荐float mean = 0; int i = 1; while(...){ mean+= (x - mean)/i; ++i; } ,它非常快速且非常高效,例如,如果我创建一个10,000x10,000像素的TIF并询问{{1}从命令行对其进行平均:

vips

您可以看到它需要0.4秒,并在7MB内存使用率时达到峰值。

相关问题