2011-03-28 31 views
1

我正在编写一个应用程序,它需要对目标进行一系列曝光并计算其平均值并保存所得图像。这项技术广泛用于天体摄影,以减少最终图像中的噪点。基本上,计算像素的平均值并将输出文件中的值写出。阅读一系列图像逐行或整个图像的性能?

曝光的数量可能相当高,从20至30(有时甚至更多),与今天的大尺寸CCD传感器的分辨率,也可以说是相当高的。所以数据量可能非常大。

我的问题是,当涉及到性能,我应该按行读取的图像行(方法#1)或应读所有阵列的整个图像阵列(方法2#)?使用前一种方法,我将不得不加载每一个对应的行。所以,如果我有10张图像,并且正在阅读第1行 - 我将不得不从每张图像读取第一行,计算它们的平均值并写出行。

对于后者的方法,我的全部,计算读取的所有图像和写出整个图像。

从理论上讲,后者的方法应该是快很多,但更多的内存密集型。然而,在实践中,我发现性能的差异并不大,这是令人困惑的。方法#2最多只比方法1快2至3秒。但是,方法2使用高达1.3 GB的内存来存储24个8百万像素的图像。另一方面,方法#1最多使用70MB。平均而言,这两种方法都需要大约20秒来处理24个8百万像素的图像。

我与调用CFITSIO时抛出一个良好的量的C写这在Objective-C。

这里的方法1:

pixelRows = (double**)malloc(self.numberOfImages * sizeof(double*)); //alloc. pixel array. 
for(i=0;i<self.numberOfImages;i++) 
{ 
    pixelRows[i] = (double*)malloc(width*sizeof(double)); 
} 
apix = (double*)malloc(width*sizeof(double)); 
for(firstpix[1]=1;firstpix[1]<=size[1];firstpix[1]++) 
{ 
    [self gatherRowsFromImages:firstpix[1] withRowWidth:theWidth thePixelMap:pixelRows]; 
    [self averageRows:pixelRows width:width theAveragedRow:apix]; 
    fits_write_pix(outfptr, TDOUBLE, firstpix, width,apix, &status); 
    //NSLog(@"Row %ld written.",firstpix[1]); 
} 

fits_close_file(outfptr,&status); 
NSLog(@"End"); 
if(!status) 
{ 
    NSLog(@"File written successfully."); 
} 
for(i=0;i<self.numberOfImages;i++) 
{ 
    free(pixelRows[i]); 
} 
free(pixelRows); 
free(apix); 

这里的方法2:

imageArray = (double**)malloc(files.count * sizeof(double*)); 
for(i=0;i<files.count;i++) 
{ 
    imageArray[i] = (double*)malloc(size[0] * size[1] * sizeof(double)); 
    fits_read_pix(fptr[i],TDOUBLE,firstpix,size[0] * size[1],NULL,imageArray[i],NULL,&status); 
    //NSLog(@"%d",status); 
} 
int fileIndex; 

NSLog(@"%d",files.count); 
apix = (double*)malloc(size[0] * size[1] * sizeof(double)); 
for(i=0;i<(size[0] * size[1]);i++) 
{ 
    apix[i] = 0.0; 
    for(fileIndex=0;fileIndex<files.count;fileIndex++) 
    { 
     apix[i] = apix[i] + imageArray[fileIndex][i]; 
    } 
    //NSLog(@"%f",apix[i]); 
    apix[i] = apix[i]/files.count; 
} 

fits_create_file(&outfptr,[outPath UTF8String],&status); 
fits_copy_header(fptr[0],outfptr,&status); 
fits_write_pix(outfptr, TDOUBLE, firstpix, size[0] * size[1],apix, &status); 
fits_close_file(outfptr,&status); 

对此有什么建议?我是否期望通过阅读每个图像的整体收益太多?

+0

你好。我正在开发一个项目,我需要能够在objective-c中使用cfitsio,并且在将库集成到Xcode项目中时遇到了一些麻烦。你认为你可以帮助我吗?因为听起来你已经完成了我需要做的事情?顺便说一句,这是我通过UCSB开展的一个开源项目。谢谢!我的电子邮件是[email protected] – Dash 2012-10-10 02:37:48

回答

1

我总是会去的行由行的做法,因为它是可扩展的。它也可能更快,因为内存占用更小,这意味着不需要将任何程序换成磁盘,只需要为内存耗费的工具。

此外,为了优化逐行方法,您还应该考虑每8行(或其他数字)读取图像。例如。 JPEG存储在8x8块中,因此读取少于8行将毫无意义。当然,这取决于您使用的图像格式和库。

还有一些关于cpu使用高速缓存的问题。经常使用的内存位置不必前往“慢”内存,但可以靠近CPU。有几个级别的缓存,并且它们的每个CPU类型的大小都不相同。 (其中最大的一个在编写本文时通常为8或16 MB)

要考虑的另一件事是实际进行平均的代码。对此进行调整也会获得很多好处,特别是对于您正在进行的操作,请参阅SSE和相关主题。同样使用整数计算可能会击败浮点运算。使用位移进行除法也可能比真正的除法更快,但它只会让你除以2^n。

+0

非常感谢您的回复。我相信CFITSIO具有某种迭代器功能,可以自动从文件中读取最佳块数。我认为这应该有所帮助。你能否详细说明SSE是什么?这是否可以在OS X和C/Objective-C上完成? – saad 2011-03-28 00:47:06

+0

但是,如果您有20个文件,您将在前8个图像行上循环20 * 8次,而您只能在每个图像中执行一次。函数调用自身形式的开销。如果您只能平均一个X字节块,则会比平均N行乘以P像素的速度更快。 – mvds 2011-03-28 00:50:35

+0

谷歌是你的朋友。 SSE是指在Intel cpu上发现的一组专用cpu指令。 AMD有自己的一套。它们通常用于对大块内存进行操作。我猜想有些图书馆可以利用它们的魔法。否则,你需要使用内联汇编(你真的不想要)。 – mvds 2011-03-28 00:54:28