Beispiel #1
0
int fftMatch_gridded(char *inFile1, char *inFile2, char *gridFile,
                     float *avgLocX, float *avgLocY, float *certainty,
                     int size, double tol, int overlap)
{
  meta_parameters *meta1 = meta_read(inFile1);
  meta_parameters *meta2 = meta_read(inFile2);

  int nl = mini(meta1->general->line_count, meta2->general->line_count);
  int ns = mini(meta1->general->sample_count, meta2->general->sample_count);

  if (size<0) size = 512;
  if (overlap<0) overlap = 256;
  if (tol<0) tol = .28;

  asfPrintStatus("Tile size is %dx%d pixels\n", size, size);
  asfPrintStatus("Tile overlap is %d pixels\n", overlap);
  asfPrintStatus("Match tolerance is %.2f\n", tol);

  long long lsz = (long long)size;

  int num_x = (ns - size) / (size - overlap);
  int num_y = (nl - size) / (size - overlap);
  int len = num_x*num_y;

  asfPrintStatus("Number of tiles is %dx%d\n", num_x, num_y);

  offset_point_t *matches = MALLOC(sizeof(offset_point_t)*len); 

  int ii, jj, kk=0, nvalid=0;
  for (ii=0; ii<num_y; ++ii) {
    int tile_y = ii*(size - overlap);
    if (tile_y + size > nl) {
      if (ii != num_y - 1)
        asfPrintError("Bad tile_y: %d %d %d %d %d\n", ii, num_y, tile_y, size, nl);
      tile_y = nl - size;
    }
    for (jj=0; jj<num_x; ++jj) {
      int tile_x = jj*(size - overlap);
      if (tile_x + size > ns) {
        if (jj != num_x - 1)
          asfPrintError("Bad tile_x: %d %d %d %d %d\n", jj, num_x, tile_x, size, ns);
        tile_x = ns - size;
      }
      //asfPrintStatus("Matching tile starting at (L,S) (%d,%d)\n", tile_y, tile_x);
      char trim_append[64];
      sprintf(trim_append, "_chip_%05d_%05d", tile_y, tile_x);
      char *trim_chip1 = appendToBasename(inFile1, trim_append);
      char *trim_chip2 = appendToBasename(inFile2, trim_append);
      trim(inFile1, trim_chip1, (long long)tile_x, (long long)tile_y, lsz, lsz);
      trim(inFile2, trim_chip2, (long long)tile_x, (long long)tile_y, lsz, lsz);
      //char smooth_append[64];
      //sprintf(smooth_append, "_smooth_chip_%05d_%05d", tile_x, tile_y);
      //char *smooth_chip1 = appendToBasename(inFile1, smooth_append);
      //smooth(trim_chip1, smooth_chip1, 3, EDGE_TRUNCATE);
      float dx, dy, cert;
      int ok = fftMatchBF(trim_chip1, trim_chip2, &dx, &dy, &cert, tol);
      matches[kk].x_pos = tile_x;
      matches[kk].y_pos = tile_y;
      matches[kk].cert = cert;
      matches[kk].x_offset = dx;
      matches[kk].y_offset = dy;
      matches[kk].valid = ok && cert>tol;
      asfPrintStatus("%s: %5d %5d dx=%7.3f, dy=%7.3f, cert=%5.3f\n",
                     matches[kk].valid?"GOOD":"BAD ", tile_y, tile_x, dx, dy, cert);
      if (matches[kk].valid) ++nvalid;
      ++kk;
      //printf("%4.1f ", dx);
      removeImgAndMeta(trim_chip1);
      FREE(trim_chip1);
      removeImgAndMeta(trim_chip2);
      FREE(trim_chip2);
      //unlink(smooth_chip1);
      //FREE(smooth_chip1);
    }
    //printf("\n");
  }

  //print_matches(matches, num_x, num_y, stdout);

  asfPrintStatus("Removing grid offset outliers.\n");
  asfPrintStatus("Starting with %d offsets.\n", nvalid);

  int removed, iter=0;
  do {
    removed = remove_outliers(matches, len);
    if (removed > 0)
      asfPrintStatus("Iteration %d: Removed %d outliers\n", ++iter, removed);
  }
  while (removed > 0);
  asfPrintStatus("Finished removing outliers.\n");

  if (gridFile) {
    FILE *offset_fp = FOPEN(gridFile,"w");
    print_matches(matches, num_x, num_y, offset_fp);
    FCLOSE(offset_fp);
  }

  char *name = appendExt(inFile1, ".offsets.txt");
  FILE *fp = FOPEN(name, "w");

  int valid_points = 0;
  for (ii=0; ii<len; ++ii) {
    if (matches[ii].valid) {
      ++valid_points;
      if (fp) {
        fprintf(fp, "%5d %5d %14.5f %14.5f %14.5f\n",
                matches[ii].x_pos, matches[ii].y_pos,
                matches[ii].x_pos + matches[ii].x_offset,
                matches[ii].y_pos + matches[ii].y_offset,
                matches[ii].cert);
      }
    }
  }

  if (valid_points < 1) {
     asfPrintStatus("Too few points for a good match.\n");
  
     *avgLocX = 0;
     *avgLocY = 0;
     *certainty = 0;
  }
  else {
    *avgLocX = 0;
    *avgLocY = 0;
    *certainty = 0;
    int n = 0;
    for (ii=0; ii<len; ++ii) {
      if (matches[ii].valid) {
        *avgLocX += matches[ii].x_offset;
        *avgLocY += matches[ii].y_offset;
        *certainty += matches[ii].cert;
        ++n;
      }
    }

    *avgLocX /= (float)n;
    *avgLocY /= (float)n;
    //*certainty = (float)n / (float)len;
    *certainty /= (float)n;
  }

  asfPrintStatus("Found %d offsets.\n", valid_points);
  asfPrintStatus("Average tile offset: dx=%f, dy=%f, cert=%f\n",
                 *avgLocX, *avgLocY, *certainty);

  meta_free(meta1);
  meta_free(meta2);

  FCLOSE(fp);
  asfPrintStatus("Generated grid match file: %s\n", name);

  FREE(matches);
  FREE(name);

  return (0);
}
Beispiel #2
0
void deskew(const char *infile, const char *outfile)
{
    meta_parameters *meta = meta_read(infile);

    int nl = meta->general->line_count;
    int np = meta->general->sample_count;
    int nb = meta->general->band_count;
    char **band_name = extract_band_names(meta->general->bands, nb);
    int band, line, samp, deskewed = meta->sar->deskewed != 0;

    if (!meta->sar)
        asfPrintError("Cannot deskew data without a sar block!\n");

    char *tmp_outfile;
    int do_rename = FALSE;
    if (strcmp(infile, outfile) == 0 && nb>1) {
        // user wants to deskew in-place
        // we can't actually do that on multi-band data, too much to keep in memory
        // use a temporary file, then clobber input file
        tmp_outfile = appendToBasename(outfile, "_tmp");
        do_rename = TRUE;
    } else {
        // normal case: either
        // 1) single-band in-place deskew
        // 2) not in-place deskew (single or multi)
        tmp_outfile = STRDUP(outfile);
    }

    // calculate the amount of shift necessary
    double fac = calc_shift(meta, 0, 0);
    // Not sure if we need this or not...
    //fac *= meta->general->x_pixel_size / meta->general->y_pixel_size;

    // the "lower" array stores the required shifts, indexed by column
    // (the amount of shift is row-independent)
    int *lower = MALLOC(np * sizeof(int));
    for (samp=0; samp<np; ++samp)
        lower[samp] = (int) floor(fac*(double)samp);

    if (meta->sar->deskewed) {
        asfPrintStatus("Data is already deskewed.\n");
    } else {
        asfPrintStatus("Far-range shift amount: ");
        if (lower[np-1] > 0)
            asfPrintStatus("%d pixels down.\n", lower[np-1]);
        else
            asfPrintStatus("%d pixels up.\n", -lower[np-1]);
    }

    float *ibuf = MALLOC(np * sizeof(float));
    float *obuf = CALLOC(np*nl, sizeof(float));

    FILE *fpi = fopenImage(infile, "rb");

    for (band=0; band<nb; ++band) {
        if (nb>1)
            asfPrintStatus("Deskewing band: %s\n", band_name[band]);

        // apply deskewing to this band
        for (line=0; line<nl; ++line) {
            get_float_line(fpi, meta, line + nl*band, ibuf);

            for (samp=0; samp<np; ++samp) {
                int out_line = deskewed ? line : line + lower[samp];
                if (out_line >= 0 && out_line < nl)
                    obuf[out_line*np+samp] = ibuf[samp];
            }

            asfLineMeter(line,nl);
        }

        // write out this band
        FILE *fpo = fopenImage(tmp_outfile, band>0 ? "ab" : "wb");
        put_float_lines(fpo, meta, band*nl, nl, obuf);
        FCLOSE(fpo);
    }

    FCLOSE(fpi);
    FREE(obuf);
    FREE(ibuf);
    FREE(lower);

    // if we output to a temporary file, clobber the input
    if (do_rename) {
        char *tmp_outfile_img = appendExt(tmp_outfile, ".img");
        char *outfile_img = appendExt(outfile, ".img");
        //printf("Renaming: %s -> %s\n", tmp_outfile_img, outfile_img);
        rename(tmp_outfile_img, outfile_img);
        FREE(tmp_outfile_img);
        FREE(outfile_img);
    }
    FREE(tmp_outfile);

    // only need to update the deskewed flag in the metadata
    meta->sar->deskewed = 1;
    meta_write(meta, outfile);
    meta_free(meta);
}
Beispiel #3
0
void c2p_ext(const char *inDataName, const char *inMetaName,
             const char *outfile, int multilook, int banded)
{
    meta_parameters *in_meta = meta_read(inMetaName);
    int data_type = in_meta->general->data_type;
    // the old code did this, but why??
    in_meta->general->data_type = meta_polar2complex(data_type);

    // some sanity checks
    switch (data_type) {
      case COMPLEX_BYTE:
      case COMPLEX_INTEGER16:
      case COMPLEX_INTEGER32:
      case COMPLEX_REAL32:
      case COMPLEX_REAL64:
          break;
      default:
          asfPrintError("c2p: %s is not a complex image.\n", inDataName);
    }

    if (in_meta->general->band_count != 1)
        asfPrintError("c2p: %s is not a single-band image.\n", inDataName);

    if (!in_meta->sar)
        asfPrintError("c2p: %s is missing a SAR block.\n", inDataName);

    asfPrintStatus("Converting complex image to amplitude/phase...\n");

    int nl = in_meta->general->line_count;
    int ns = in_meta->general->sample_count;
    // process 1 line at a time when not multilooking, otherwise grab nlooks
    int nlooks = multilook ? in_meta->sar->look_count : 1;

    if (nlooks == 1 && multilook) {
        asfPrintStatus("Not multilooking, look_count is 1.\n");
        multilook = FALSE;
    }

    if (multilook)
        asfPrintStatus("Multilooking with %d looks.\n", nlooks);

    meta_parameters *out_meta = meta_read(inMetaName);
    out_meta->general->data_type = meta_complex2polar(data_type);

    // set up input/output files
    FILE *fin = fopenImage(inDataName, "rb");

    // we either have 1 or 2 output files, per the "banded" flag.
    char *outfile_img = appendExt(outfile, ".img");
    char *amp_name=NULL, *phase_name=NULL;
    FILE *fout_banded=NULL, *fout_amp=NULL, *fout_phase=NULL;
    if (banded) {
        asfPrintStatus("Output is 2-band image: %s\n", outfile_img);
        fout_banded = fopenImage(outfile_img, "wb");
    } else {
        amp_name = appendToBasename(outfile_img, "_amp");
        phase_name = appendToBasename(outfile_img, "_phase");
        asfPrintStatus("Output amplitude file: %s\n", amp_name);
        asfPrintStatus("Output phase file: %s\n", phase_name);
        fout_amp = fopenImage(amp_name, "wb");
        fout_phase = fopenImage(phase_name, "wb");
    }
    if (banded)
        assert(fout_banded && !fout_amp && !fout_phase);
    else
        assert(!fout_banded && fout_amp && fout_phase);

    // get the metadata band_count correct, needed in the put_* calls
    if (banded) {
        out_meta->general->band_count = 2;
        strcpy(out_meta->general->bands, "AMP,PHASE");
    }

    // input buffer
    complexFloat *cpx = MALLOC(sizeof(complexFloat)*ns*nlooks);

    // output buffers
    float *amp = MALLOC(sizeof(float)*ns*nlooks);
    float *phase = MALLOC(sizeof(float)*ns*nlooks);

    int line_in;    // line in the input image
    int line_out=0; // line in the output image
    int samp;       // sample #, loop index
    int l;          // line loop index, iterates over the lines in the block

    out_meta->general->line_count = (int)ceil((double)nl/(double)nlooks);

    for (line_in=0; line_in<nl; line_in+=nlooks)
    {
        // lc = "line count" -- how many lines to read. normally we will read
        // nlooks lines, but near eof we might have to read fewer
        int lc = nlooks; 
        if (line_in + lc > nl)
            lc = nl - line_in;

        // read "nlooks" (or possibly fewer, if near eof) lines of data
        int blockSize = get_complexFloat_lines(fin,in_meta,line_in,lc,cpx);
        if (blockSize != lc*ns)
            asfPrintError("bad blockSize: bs=%d nlooks=%d ns=%d\n", 
			  blockSize, nlooks, ns);

        // first, compute the power/phase
        for (l=0; l<lc; ++l) {
            for (samp=0; samp<ns; ++samp) {
                int k = l*ns + samp; // index into the block
                float re = cpx[k].real;
                float im = cpx[k].imag;
                if (re != 0.0 || im != 0.0) {
                    amp[k] = re*re + im*im;
                    phase[k] = atan2(im, re);
                } else {
                    amp[k] = phase[k] = 0.0;
                }
            }
        }

        // now multilook, if requested
        if (multilook) {
            // put the multilooked data in the first "row" of amp,phase
            for (samp=0; samp<ns; ++samp) {
                float value = 0.0;
                for (l=0; l<lc; ++l)
                    value += amp[l*ns + samp];
                amp[samp] = sqrt(value/(float)lc);

                value = 0.0;
                for (l=0; l<lc; ++l)
                    value += phase[l*ns + samp];
                phase[samp] = value/(float)lc;
            }
        }
        else {
            for (samp=0; samp<ns*lc; ++samp)
                amp[samp] = sqrt(amp[samp]);
        }

        // write out a line (multilooked) or a bunch of lines (not multi)
        if (multilook) {
            if (banded) {
                put_band_float_line(fout_banded, out_meta, 0, line_out, amp);
                put_band_float_line(fout_banded, out_meta, 1, line_out, phase);
            } else {
                put_float_line(fout_amp, out_meta, line_out, amp);
                put_float_line(fout_phase, out_meta, line_out, phase);
            }
            ++line_out;
        } else {
            for (l=0; l<lc; ++l) {
                if (banded) {
                    put_band_float_line(fout_banded, out_meta, 0, line_in+l, amp);
                    put_band_float_line(fout_banded, out_meta, 1, line_in+l, phase);
                } else {
                    put_float_line(fout_amp, out_meta, line_in+l, amp);
                    put_float_line(fout_phase, out_meta, line_in+l, phase);
                }
                ++line_out;
            }
        }

        asfPercentMeter((float)line_in/(float)(nl));
    }
    asfPercentMeter(1.0);

    fclose(fin);
    if (fout_banded) fclose(fout_banded);
    if (fout_amp) fclose(fout_amp);
    if (fout_phase) fclose(fout_phase);

    if (multilook) {
        if (out_meta->general->line_count != line_out)
            asfPrintError("Line counts don't match: %d != %d\n",
                out_meta->general->line_count, line_out);
        out_meta->general->y_pixel_size *= nlooks;
        out_meta->sar->azimuth_time_per_pixel *= nlooks;
        out_meta->sar->multilook = TRUE;
    } else
        assert(line_out == nl);

    // write out the metadata, different whether multi-banded or not
    if (banded) {
        assert(!amp_name && !phase_name);
        meta_write(out_meta, outfile);
    } else {
        assert(amp_name && phase_name);
        
        out_meta->general->image_data_type = AMPLITUDE_IMAGE;
        meta_write(out_meta, amp_name);
        
        out_meta->general->image_data_type = PHASE_IMAGE;
        meta_write(out_meta, phase_name);
    }

    if (multilook)
        asfPrintStatus("Original line count: %d, after multilooking: %d "
            "(%d looks)\n", nl, line_out, nlooks);

    meta_free(in_meta);
    meta_free(out_meta);

    FREE(amp);
    FREE(phase);
    FREE(cpx);

    FREE(outfile_img);

    FREE(amp_name);
    FREE(phase_name);
}