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); }
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); }
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); }