タイプ bsq (バンド シーケンシャル) のインターリーブを含む ENVI イメージ ファイル (.hdr ラベル付き) を使用しています。約350MBの画像の主成分変換をしようとしています。そのためには、小さなメモリ ブロックで個別に処理する必要がありました。以下のコードは、ファイルがメモリの 1 ブロックだけで処理できる場合、期待どおりに機能します。ただし、複数回の繰り返しが必要な場合は、最後のブロックのみが期待どおりに出力されます。つまり、前のすべてのブロックは、同じピクセルが何度も繰り返されているかのように書き込まれます。
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 関数での不適切な呼び出しが原因であるという結論に達しました。これを行うには、単純に、ピクセルを順番に書き込む (bip インターリーブ) 挿入された次のコードを使用しました。
for(i=0;i<size:++i){
gsl_vector_fwrite(fp, xform_pixel_vector[i]);
}
ただし、出力ファイルをバンド シーケンシャル ファイルとして保持したいと考えています。私は解決策を見つけるために多くの時間を費やし、あちこちでコードを微調整しましたが、問題の解決策はまだわかりません。