我正在使用带有bsq类型(带序列)的交错的ENVI图像文件(.hdr labbeled)。我正在尝试对大约350MB的图像进行主成分转换。为了做到这一点,我不得不在较小的内存块中单独处理它。如果文件只能在一个内存块中使用,则下面的代码按预期工作。但是,如果它需要多次迭代,则只有最后一个块按预期出现,即,所有先前的块都被写入,好像它们是一遍又一遍地重复相同的像素。
extern void pca_xform(envi_header file){
#define BLOCK_SIZE 3000000
/*Calculates covariance_matrix, eigen_matrix, mean_vector
and allocates pixel_vector and xform_pixel_vector*/
int size = (file.lines)*(file.samples), i;
printf("Transforming\n");
int n = size/BLOCK_SIZE;
int r = size - ((BLOCK_SIZE)*n);
int block;
for(i=0,block=0;i<n+1;++i,++block){
int actual_size = BLOCK_SIZE;
if(i==n){
actual_size = r;
}
int k;
io_bsq_read_pixel(file, i*BLOCK_SIZE, actual_size, pixel_vector);
for(k=0;k<actual_size;++k){
pca_normalize_pixel_vector(mean_vector, pixel_vector[k]);
}
for(k=0;k<actual_size;++k){
pca_xform_pixel_vector(file, eigen_matrix, pixel_vector[k], xform_pixel_vector[k]);
}
io_bsq_write_pixel(file, i*BLOCK_SIZE, actual_size, xform_pixel_vector);
}
return;
}
这是写作功能。
extern void io_bsq_write_pixel(envi_header file, int start, int number, gsl_vector** pixel_vector){
FILE* fp = fopen(file.new_filename, "wb");
if(!fp){
fprintf(stderr, "Failed to open target: %s\n", file.new_filename);
exit(EXIT_FAILURE);
}
int size = (file.samples) * (file.lines);
int i, j;
double d;
for(i=0;i<file.bands;++i){
fseek(fp, sizeof(double)*((size*i)+start), SEEK_SET);
for(j=0;j<number;++j){
d = gsl_vector_get(pixel_vector[j], i);
fwrite(&d, sizeof(double), 1, fp);
}
}
fclose(fp);
return;
}
我得出结论,意外的行为是由于这个函数本身或者在pca_xform函数中对它的一些不恰当的调用。为此,我只使用下面的代码,它按顺序写入像素(双向交错)。
for(i=0;i<size:++i){
gsl_vector_fwrite(fp, xform_pixel_vector[i]);
}
但是,我希望将输出文件保持为带序列。我花了很多时间试图找到解决方案,在这里和那里调整代码,但问题的解决方案仍然无法解决。
答案 0 :(得分:0)
我终于找到了问题的根源。问题是我现在倾向于相信文件中写作程序的位置。然而,它仍然在io_bsq_write_pixel
。每次我调用该函数时,它都会随后调用fwrite(file.new_filename, "w")
。在&#34; w&#34; 模式下打开文件会删除我以前的所有工作。为了解决这个问题,我在调用pca_xform
之前初始化了文件,然后更改了io_bsq_write_pixel
extern void io_bsq_write_pixel(envi_header file, int start, int number, gsl_vector** pixel_vector){
FILE* fp = fopen(file.new_filename, "r+b");
if(!fp){
fprintf(stderr, "Failed to open target: %s\n", file.new_filename);
exit(EXIT_FAILURE);
}
int size = (file.samples) * (file.lines);
int i, j;
double d;
for(i=0;i<file.bands;++i){
fseek(fp, sizeof(double)*((size*i)+start), SEEK_SET);
for(j=0;j<number;++j){
d = gsl_vector_get(pixel_vector[j], i);
fwrite(&d, sizeof(double), 1, fp);
}
}
fclose(fp);
return;
}
这样,使用&#34; r + b&#34; 并首先初始化文件,我保证它会打开文件进行简单更新,而不会删除我之前的工作。