0

タイプ 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]);
 }

ただし、出力ファイルをバンド シーケンシャル ファイルとして保持したいと考えています。私は解決策を見つけるために多くの時間を費やし、あちこちでコードを微調整しましたが、問題の解決策はまだわかりません。

4

1 に答える 1

0

私はついに問題の原因を見つけることができました。問題は、ファイル内の書き込み手順の位置を信じる傾向が強かったことです。しかし、それはまだでしたio_bsq_write_pixel。関数を呼び出すたびに、その後 が呼び出されますfwrite(file.new_filename, "w")「w」モードでファイルを開くと、以前の作業がすべて消去されました。これを修正するために、呼び出す前にファイルを初期化してからpca_xformio_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;
}

このように、「r+b」を使用して最初にファイルを初期化すると、以前の作業を消去することなく、簡単な更新のためにファイルを開くことが保証されます。

于 2016-04-06T22:23:46.843 に答える