私は、bsq(バンドシーケンシャル)タイプのインターリーブを持つENVI画像ファイル(.hdr labbeled)で作業しています。私は約350MBの画像の主成分変換をしようとしています。これを行うために、私は別々に小さなメモリブロックでそれを処理しなければなりませんでした。次のコードは、ファイルを1ブロックのメモリで処理できる場合、期待どおりに機能します。しかし、2つ以上の反復が必要な場合は、最後のブロックだけが期待通りに出てくる、すなわち、前のブロックはすべて同じピクセルの繰り返しであるかのように書き込まれる。ピクセルブロックをバンドシーケンシャルモードで書き込むことができません
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インターリーブ)以下のコードinstedを使いました。
for(i=0;i<size:++i){
gsl_vector_fwrite(fp, xform_pixel_vector[i]);
}
出力ファイルをバンド順番に保つことをお勧めします。私は解決策を見つけようと多くの時間を費やしてきましたが、こことそこでコードを調整しましたが、問題の解決策はまだ私を逃しています。
私は 'fseek()'が不審であることがわかりました。あなたが順番に書いているなら、どうしてあなたは何を求めているのですか? – EOF
@EOF私は 'fseek()'を使って、そのバンドの書き込みを開始する正しい位置を見つけることができます。出力として2バンドの10MBイメージがあるとします。これにより、バンド1の最初の2,5MB(たとえばブロック1)を書き込んだり、2番のバンドに行き、もう一方の2,5MBを書き込んだりできます。そこで、5MBの2番目のブロックを書き込むために空白を正しい位置に残しました。 – lfmc
私はこれがコンパイルを妨げ、問題の原因ではないことを知っています....最後のコードスニペットでは ')'が必要です。 – ryyker