示例#1
0
static int
find_grid_size(meta_parameters *meta_sar, meta_parameters *meta_dem,
               int initial_size, double tolerance)
{
  // pick a square centered on the center of the image
  // we will start with the biggest square and compare the error at the center
  // point between using (1) bilinear interp and (2) the real mapping
  // if the error is larger than the tolerance, shrink square and try again
  int line = meta_sar->general->line_count / 2;
  int samp = meta_sar->general->sample_count / 2;
  int sz = initial_size;
  double lines[4], samps[4];

  while (1) {
    int sz2 = sz/2;
    int line_lo = line - sz2;
    int line_hi = line_lo + sz;
    int samp_lo = samp - sz2;
    int samp_hi = samp_lo + sz;
    get_interp_params(meta_sar, meta_dem, line_lo, line_hi, samp_lo, samp_hi,
                      lines, samps);
    double err = calc_err(meta_sar, meta_dem, line_lo, line_hi, samp_lo, samp_hi,
                          lines, samps);
    if (err < tolerance) {
      asfPrintStatus("Using square size %d (err %f < %f)\n", sz, err, tolerance);
      break;
    }
    asfPrintStatus("Square size %d, no good (err %f > %f)\n", sz, err, tolerance);
    sz = sz2;
    if (sz <= 2) {
      asfPrintStatus("Proceeding with grid size 1.\n");
      sz = 1;
      break;
    }
  }
  return sz;
}
示例#2
0
// Input:
//   meta_parameters *meta_sar--  SAR geometry to subset the DEM
//   const char *demImg       --  DEM data filename
//   const char *demMeta      --  DEM metadata filename
//   int pad                  --  number of lines to add at the top/bottom/left/right
//   double tolerance         --  how accurate the approximation mapping needs to be,
//                                in units of pixels
//   const char *output_name  --  output filename (basename)
//   int test_mode            --  adds checks for the accuracy of the mapping, and
//                                does some unit testing
// Output:
//   no output parameters, the output is the output_name files (.img and .meta)
// Return Value:
//   return TRUE on success, FALSE on fail
//
int make_gr_dem_ext(meta_parameters *meta_sar, const char *demImg, const char *demMeta,
                    int pad, double tolerance, const char *output_name, int test_mode)
{
  if (test_mode)
    test_interp();
  
  asfPrintStatus("Reading DEM...\n");
  meta_parameters *meta_dem = meta_read(demMeta);
  float *demData = NULL;
  FloatImage *fi_dem = NULL;

  int dnl = meta_dem->general->line_count;
  int dns = meta_dem->general->sample_count;

  if (0)
    demData = read_dem(meta_dem, demImg);
  else
    fi_dem = float_image_new_from_metadata(meta_dem, demImg);

  if (demData)
    asfPrintStatus("Old method: reading entire DEM.\n");
  if (fi_dem)
    asfPrintStatus("New method: float image\n");
  if (demData && fi_dem)
    asfPrintError("Impossible.\n");

  char *outImg = appendExt(output_name, ".img");
  char *output_name_tmp, *outImgTmp;

  // do not do DEM smoothing if the DEM pixel size is better or close to the
  // SAR image's pixel size.
  int do_averaging = TRUE;
  if (meta_dem->general->y_pixel_size - 10 < meta_sar->general->y_pixel_size)
    do_averaging = FALSE;
  asfPrintStatus("Averaging: %s (DEM %f, SAR: %f)\n", do_averaging ? "YES" : "NO",
                 meta_dem->general->y_pixel_size,
                 meta_sar->general->y_pixel_size);
  if (do_averaging) {
    output_name_tmp = appendStr(output_name, "_unsmoothed");
    outImgTmp = appendExt(output_name_tmp, ".img");
  }
  else {
    output_name_tmp = STRDUP(output_name);
    outImgTmp = STRDUP(outImg);
  }

  // add the padding if requested
  meta_parameters *meta_out = meta_copy(meta_sar);
  meta_out->general->line_count += pad*2;
  meta_out->general->sample_count += pad*2;
  meta_out->general->start_line -= pad;
  meta_out->general->start_sample -= pad;

  // fixing up the output metadata.  Note that we must keep the SAR section
  // intact since that specifies our geometry which is the whole point of
  // this exercise.
  strcpy(meta_out->general->basename, meta_dem->general->basename);
  strcpy(meta_out->general->sensor, MAGIC_UNSET_STRING);
  strcpy(meta_out->general->processor, MAGIC_UNSET_STRING);
  strcpy(meta_out->general->mode, MAGIC_UNSET_STRING);
  strcpy(meta_out->general->sensor_name, MAGIC_UNSET_STRING);
  meta_out->general->image_data_type = DEM;
  meta_out->general->radiometry = MAGIC_UNSET_INT;
  strcpy(meta_out->general->acquisition_date, meta_dem->general->acquisition_date);
  meta_out->general->orbit = MAGIC_UNSET_INT;
  meta_out->general->orbit_direction = MAGIC_UNSET_CHAR;
  meta_out->general->frame = MAGIC_UNSET_INT;
  meta_out->general->band_count = 1;
  strcpy(meta_out->general->bands, "DEM");

  int nl = meta_out->general->line_count;
  int ns = meta_out->general->sample_count;

  // finding the right grid size
  int size = find_grid_size(meta_sar, meta_dem, 512, .1*tolerance);

  asfPrintStatus("Creating ground range image...\n");

  float *buf = MALLOC(sizeof(float)*ns*size);
  FILE *fpOut = FOPEN(outImgTmp, "wb");

  // these are for tracking the quality of the bilinear interp
  // not used if test_mode is false
  int num_out_of_tol = 0;
  int num_checked = 0;
  int num_bad = 0;
  double max_err = 0;
  double avg_err = 0;

  int ii, jj;
  for (ii=0; ii<nl; ii += size) {
    int line_lo = ii;
    int line_hi = ii + size;

    for (jj=0; jj<ns; jj += size) {
      double lines[4], samps[4];
      
      int samp_lo = jj;
      int samp_hi = jj + size;

      get_interp_params(meta_sar, meta_dem, line_lo, line_hi, samp_lo, samp_hi,
                        lines, samps);

      int iii, jjj;
      for (iii=0; iii<size; ++iii) {
        for (jjj=0; jjj<size && jj+jjj<ns; ++jjj) {
          int index = iii*ns + jj + jjj;
          assert(index < ns*size);

          double line_out, samp_out;
          xy_interp(ii+iii, jj+jjj, line_lo, line_hi, samp_lo, samp_hi, lines, samps,
                    &line_out, &samp_out);

          // random checking of the quality of our interpolations
          if (test_mode && iii%11==0 && jjj%13==0) {
            double real_line, real_samp; 
            sar_to_dem(meta_sar, meta_dem, ii+iii, jj+jjj, &real_line, &real_samp);

            double err = hypot(real_line - line_out, real_samp - samp_out);

            avg_err += err;
            if (err > max_err)
              max_err = err;

            if (err > tolerance) {
              asfPrintStatus("Out of tolerance at %d,%d: (%f,%f) vs (%f,%f) -> %f\n",
                             ii+iii, jj+jjj, line_out, samp_out, real_line, real_samp,
                             err);
              ++num_out_of_tol;
            }
            if (err > .5) {
              asfPrintStatus("Error is larger than 1 pixel!\n");
              ++num_bad;
            }
            ++num_checked;
          }
          if (demData)
            buf[index] = interp_demData(demData, dnl, dns, line_out, samp_out);
          else if (fi_dem)
            buf[index] = interp_dem(fi_dem, line_out, samp_out);
          else
            asfPrintError("Oops.\n");
        }
      }
    }

    put_float_lines(fpOut, meta_out, ii, size, buf);
    asfPrintStatus("Completed %.1f%%  \r", 100.*ii/(double)nl);
  }
  asfPrintStatus("Completed 100%%   \n");

  if (test_mode) {
    asfPrintStatus("Tolerance was %f\n", tolerance);
    asfPrintStatus("%d/%d checked pixels had error exceeding tolerance. (%.1f%%)\n",
                   num_out_of_tol, num_checked, 100.*num_out_of_tol/(double)num_checked);
    asfPrintStatus("%d/%d checked pixels had error larger than half a pixel. (%.1f%%)\n",
                   num_bad, num_checked, 100.*num_bad/(double)num_checked);
    asfPrintStatus("Maximum error: %f pixels\n", max_err);
    avg_err /= (double)num_checked;
    asfPrintStatus("Average error: %f pixels\n", avg_err);
  }

  FCLOSE(fpOut);
  meta_write(meta_out, outImgTmp);

  meta_free(meta_out);
  meta_free(meta_dem);

  FREE(buf);
  FREE(demData);
  if (fi_dem)
    float_image_free(fi_dem);

  // now apply 3x3 filter
  if (do_averaging) {
    asfPrintStatus("Smoothing with 3x3 kernel ...\n");
    smooth(outImgTmp, outImg, 3, EDGE_TRUNCATE);
  }

  FREE(outImg);
  FREE(outImgTmp);
  FREE(output_name_tmp);

  return FALSE;
}
示例#3
0
int geoid_adjust(const char *input_filename, const char *output_filename)
{
  char *input_img = appendExt(input_filename, ".img");
  char *input_meta = appendExt(input_filename, ".meta");

  char *output_img = appendExt(output_filename, ".img");
  char *output_meta = appendExt(output_filename, ".meta");

  if (!fileExists(input_img))
    asfPrintError("File not found: %s\n", input_img);
  if (!fileExists(input_meta))
    asfPrintError("File not found: %s\n", input_meta);

  meta_parameters *meta = meta_read(input_meta);
  int nl = meta->general->line_count;
  int ns = meta->general->sample_count;
  int ii, jj;

  FILE *fpIn = FOPEN(input_img, "rb");
  FILE *fpOut = FOPEN(output_img, "wb");
  float *buf;

  // Two ways we can do this:
  //   1) call meta_get_latLon at every point
  //   2) call meta_get_latLon at certain points and interpolate between
  // We will use the first when we have a lat/lon image, and the second for
  // everything else.
  int latlon_image = meta->projection &&
                     meta->projection->type == LAT_LONG_PSEUDO_PROJECTION;

  double avg = 0.0;
  int num=0;

  asfPrintStatus("Performing geoid correction.\n");
  asfPrintStatus(" Input file: %s\n", input_filename);
  asfPrintStatus(" Output file: %s\n", output_filename);

  if (latlon_image) {
    asfPrintStatus("Lat/Lon image, not using mapping interpolation.\n");
    buf = MALLOC(sizeof(float)*ns);
    for (ii=0; ii<nl; ++ii) {
      get_float_line(fpIn, meta, ii, buf);
      for (jj=0; jj<ns; ++jj) {
        double lat, lon;
        meta_get_latLon(meta, ii, jj, 0, &lat, &lon);
        if (buf[jj] > -900 && buf[jj] != meta->general->no_data)
        {
          float ht = get_geoid_height(lat,lon);
          buf[jj] += ht;
          avg += ht;
          ++num;
        }
      }
      put_float_line(fpOut, meta, ii, buf);
      asfLineMeter(ii,nl);
    }
  }
  else {
    asfPrintStatus("Not a Lat/Lon image, using mapping interpolation.\n");
    double tol = .0001;
    int size = find_grid_size(meta, 512, .1*tol);

    int test_mode = 1;
    buf = MALLOC(sizeof(float)*ns*size);

    // these are for tracking the quality of the bilinear interp
    // not used if test_mode is false
    int num_out_of_tol = 0;
    int num_checked = 0;
    int num_bad = 0;
    double max_err = 0;
    double avg_err = 0;

    for (ii=0; ii<nl; ii += size) {
      int line_lo = ii;
      int line_hi = ii + size;

      if (ii+size >= nl)
        size = nl-ii;

      get_float_lines(fpIn, meta, ii, size, buf);

      for (jj=0; jj<ns; jj += size) {
        double lats[4], lons[4];

        int samp_lo = jj;
        int samp_hi = jj + size;

        get_interp_params(meta, line_lo, line_hi, samp_lo, samp_hi, lats, lons);

        int iii, jjj;
        for (iii=0; iii<size; ++iii) {
          for (jjj=0; jjj<size && jj+jjj<ns; ++jjj) {
            int kkk = iii*ns + jj + jjj;
            assert(kkk < ns*size);

            double lat, lon;
            xy_interp(ii+iii, jj+jjj, line_lo, line_hi, samp_lo, samp_hi, lats, lons,
                      &lat, &lon);

            // random checking of the quality of our interpolations
            if (test_mode && iii%11==0 && jjj%13==0) {
              double real_lat, real_lon;
              img_to_latlon(meta, ii+iii, jj+jjj, &real_lat, &real_lon);
              double err = hypot(real_lat - lat, real_lon - lon);

              avg_err += err;
              if (err > max_err)
                max_err = err;

              if (err > .1*tol) {
                asfPrintStatus("Out of tolerance at %d,%d: (%f,%f) vs (%f,%f) -> %f\n",
                               ii+iii, jj+jjj, lat, lon, real_lat, real_lon,
                               err);
                ++num_out_of_tol;
              }
              if (err > tol) {
                asfPrintStatus("Error is larger than %f!\n", .01*tol);
                ++num_bad;
              }
              ++num_checked;
            }

            if (buf[kkk] > -900 && buf[kkk] != meta->general->no_data)
            {
              float ht = get_geoid_height(lat,lon);
              buf[kkk] += ht;
              avg += ht;
              ++num;
            }
          }  
        }
      }
      put_float_lines(fpOut, meta, ii, size, buf);
      asfPrintStatus("Completed %.1f%%  \r", 100.*ii/(double)nl);
    }
    asfPrintStatus("Completed 100%%   \n");
  }

  avg /= (double)(num);
  asfPrintStatus("Average correction: %f\n", avg);

  meta_write(meta, output_meta);
  meta_free(meta);

  FCLOSE(fpIn);
  FCLOSE(fpOut);

  FREE(buf);
  FREE(input_img);
  FREE(input_meta);
  FREE(output_img);
  FREE(output_meta);

  // success
  return 0;
}