Esempio n. 1
0
float cal2amp(meta_parameters *meta, float incid, int sample, char *bandExt, 
	      float calValue)
{
  double scaledPower, ampValue, invIncAngle;
  radiometry_t radiometry = meta->general->radiometry;

  if (radiometry >= r_SIGMA_DB && radiometry <= r_BETA_DB)
    scaledPower = pow(10, calValue/10.0);
  else if (radiometry >= r_SIGMA && radiometry <= r_BETA)
    scaledPower = calValue;
  else
    asfPrintError("Conversion requires radiometric values in input image.\n"
		  "Radiometry: %s", radiometry2str(radiometry));

  // Calculate according to the calibration data type
  if (meta->calibration->type == asf_cal) { // ASF style data (PP and SSP)

    if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB)
      invIncAngle = 1.0;
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB)
      invIncAngle = 1/cos(incid);
    else if (radiometry == r_BETA || radiometry == r_BETA_DB)
      invIncAngle = 1/sin(incid);

    asf_cal_params *p = meta->calibration->asf;
    double index = (double)sample*256./(double)(p->sample_count);
    int base = (int) index;
    double frac = index - base;
    double *noise = p->noise;
    double noiseValue = noise[base] + frac*(noise[base+1] - noise[base]);

    // Convert (amplitude) data number to scaled, noise-removed power
    //scaledPower = (p->a1*(inDn*inDn-p->a0*noiseValue) + p->a2)*invIncAngle;
    ampValue = sqrt((scaledPower/invIncAngle - p->a2)/p->a1 + p->a0*noiseValue);
  }
  else if (meta->calibration->type == asf_scansar_cal) { // ASF style ScanSar

    asf_scansar_cal_params *p = meta->calibration->asf_scansar;

    if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB)
      invIncAngle = 1.0;
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB)
      invIncAngle = 1/cos(incid);
    else if (radiometry == r_BETA || radiometry == r_BETA_DB)
      invIncAngle = 1/sin(incid);

    double look = 25.0; // FIXME: hack to get things compiled
    double index = (look-16.3)*10.0;
    double noiseValue;
    double *noise = p->noise;

    if (index <= 0)
      noiseValue = noise[0];
    else if (index >= 255)
      noiseValue = noise[255];
    else {
      // Use linear interpolation on noise array
      int base = (int)index;
      double frac = index - base;
      noiseValue = noise[base] + frac*(noise[base+1] - noise[base]);
    }

    // Convert (amplitude) data number to scaled, noise-removed power
    //scaledPower = (p->a1*(inDn*inDn-p->a0*noiseValue) + p->a2)*invIncAngle;
    ampValue = sqrt((scaledPower/invIncAngle - p->a2)/p->a1 + p->a0*noiseValue);
  }
  else if (meta->calibration->type == esa_cal) { // ESA style ERS and JERS data

    esa_cal_params *p = meta->calibration->esa;

    if (radiometry == r_BETA || radiometry == r_BETA_DB) {
      //scaledPower = inDn*inDn/p->k;
      ampValue = sqrt(scaledPower*p->k);
    }
    else if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB) 
      //scaledPower = inDn*inDn/p->k*sin(p->ref_incid*D2R)/sin(incidence_angle);
      ampValue = sqrt(scaledPower * p->k*sin(p->ref_incid*D2R)*sin(incid));
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB) {
      invIncAngle = 1/cos(incid);
      //scaledPower = 
      //inDn*inDn/p->k*sin(p->ref_incid*D2R)/sin(incidence_angle)/invIncAngle;
      ampValue = 
	sqrt(scaledPower*invIncAngle*sin(incid)*p->k/sin(p->ref_incid*D2R));
    }

  }
  else if (meta->calibration->type == rsat_cal) { // CDPF style Radarsat data

    if (radiometry == r_BETA || radiometry == r_BETA_DB)
      invIncAngle = 1.0;
    if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB)
      invIncAngle = 1/tan(incid);
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB)
      invIncAngle = tan(incid);

    rsat_cal_params *p = meta->calibration->rsat;
    double a2;
    if (meta->calibration->rsat->focus)
      a2 = p->lut[0];
    else if (sample < (p->samp_inc*(p->n-1))) {
      int i_low = sample/p->samp_inc;
      int i_up = i_low + 1;
      a2 = p->lut[i_low] +
    ((p->lut[i_up] - p->lut[i_low])*((sample/p->samp_inc) - i_low));
    }
    else
      a2 = p->lut[p->n-1] +
    ((p->lut[p->n-1] - p->lut[p->n-2])*((sample/p->samp_inc) - p->n-1));
    if (p->slc)
      //scaledPower = (inDn*inDn)/(a2*a2)*invIncAngle;
      ampValue = sqrt(scaledPower *a2*a2/invIncAngle);
    else
      //scaledPower = (inDn*inDn + p->a3)/a2*invIncAngle;
      ampValue = sqrt((scaledPower *a2/invIncAngle) - p->a3);
  }
  else if (meta->calibration->type == alos_cal) { // ALOS data

    if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB)
      invIncAngle = 1.0;
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB)
      invIncAngle = 1/cos(incid);
    else if (radiometry == r_BETA || radiometry == r_BETA_DB)
      invIncAngle = 1/sin(incid);

    alos_cal_params *p = meta->calibration->alos;
    double cf;
    if (strstr(bandExt, "HH"))
      cf = p->cf_hh;
    else if (strstr(bandExt, "HV"))
      cf = p->cf_hv;
    else if (strstr(bandExt, "VH"))
      cf = p->cf_vh;
    else if (strstr(bandExt, "VV"))
      cf = p->cf_vv;
    
    //scaledPower = pow(10, cf/10.0)*inDn*inDn*invIncAngle;
    ampValue = sqrt(scaledPower / invIncAngle / pow(10, cf/10.0));
  }
  else if (meta->calibration->type == tsx_cal) { // TerraSAR-X

    if (radiometry == r_BETA || radiometry == r_BETA_DB)
      invIncAngle = 1.0;
    if (radiometry == r_SIGMA || radiometry == r_SIGMA_DB)
      invIncAngle = 1/tan(incid);
    else if (radiometry == r_GAMMA || radiometry == r_GAMMA_DB)
      invIncAngle = tan(incid);

    double cf = meta->calibration->tsx->k;
    //scaledPower = cf*inDn*inDn*invIncAngle;
    ampValue = sqrt(scaledPower / (cf*invIncAngle));
  }
  else
    // should never get here
    asfPrintError("Unknown calibration data type!\n");

  return ampValue;
}
Esempio n. 2
0
int asf_calibrate(const char *inFile, const char *outFile, 
		  radiometry_t outRadiometry, int wh_scaleFlag)
{
  meta_parameters *metaIn = meta_read(inFile);
  meta_parameters *metaOut = meta_read(inFile);

  if (!metaIn->calibration) {
    asfPrintError("This data cannot be calibrated, missing calibration block.\n");
  }

  // Check for valid output radiometry
  if (outRadiometry == r_AMP || outRadiometry == r_POWER)
    asfPrintError("Invalid radiometry (%s) passed into calibration function!\n",
		  radiometry2str(outRadiometry));

  // Check whether output radiometry fits with Woods Hole scaling flag
  if (wh_scaleFlag && outRadiometry >= r_SIGMA && outRadiometry <= r_GAMMA)
    outRadiometry += 3;

  // This can only work if the image is in some SAR geometry
  if (metaIn->projection && metaIn->projection->type != SCANSAR_PROJECTION)
    asfPrintError("Can't apply calibration factors to map projected images\n"
                  "(Amplitude or Power only)\n");

  radiometry_t inRadiometry = metaIn->general->radiometry;
  asfPrintStatus("Calibrating %s image to %s image\n\n", 
		 radiometry2str(inRadiometry), radiometry2str(outRadiometry));
  // FIXME: This function should be able to remap between different
  //        radiometry projections.
  if (metaIn->general->radiometry != r_AMP)
    asfPrintError("Currently only AMPLITUDE as radiometry is supported!\n");

  metaOut->general->radiometry = outRadiometry;
  int dbFlag = FALSE;
  if (outRadiometry >= r_SIGMA && outRadiometry <= r_GAMMA)
    metaOut->general->no_data = 0.0001;
  if (outRadiometry >= r_SIGMA_DB && outRadiometry <= r_GAMMA_DB) {
    metaOut->general->no_data = -40.0;
    dbFlag = TRUE;
  }
  if (metaIn->general->image_data_type != POLARIMETRIC_IMAGE) {
    if (outRadiometry == r_SIGMA || outRadiometry == r_SIGMA_DB)
      metaOut->general->image_data_type = SIGMA_IMAGE;
    else if (outRadiometry == r_BETA || outRadiometry == r_BETA_DB)
      metaOut->general->image_data_type = BETA_IMAGE;
    else if (outRadiometry == r_GAMMA || outRadiometry == r_GAMMA_DB)
      metaOut->general->image_data_type = GAMMA_IMAGE;
  }
  if (wh_scaleFlag)
    metaOut->general->data_type = ASF_BYTE;

  char *input = appendExt(inFile, ".img");
  char *output = appendExt(outFile, ".img");
  FILE *fpIn = FOPEN(input, "rb");
  FILE *fpOut = FOPEN(output, "wb");

  int dualpol = strncmp_case(metaIn->general->mode, "FBD", 3) == 0 ? 1 : 0;
  int band_count = metaIn->general->band_count;
  int sample_count = metaIn->general->sample_count;
  int line_count = metaIn->general->line_count;
  char **bands = 
    extract_band_names(metaIn->general->bands, band_count);

  float *bufIn = (float *) MALLOC(sizeof(float)*sample_count);
  float *bufOut = (float *) MALLOC(sizeof(float)*sample_count);
  float *bufIn2 = NULL, *bufOut2 = NULL, *bufOut3 = NULL;
  if (dualpol && wh_scaleFlag) {
    bufIn2 = (float *) MALLOC(sizeof(float)*sample_count);
    bufOut2 = (float *) MALLOC(sizeof(float)*sample_count);
    bufOut3 = (float *) MALLOC(sizeof(float)*sample_count);
    metaOut->general->band_count = 3;
    sprintf(metaOut->general->bands, "%s,%s,%s-%s", 
	    bands[0], bands[1], bands[0], bands[1]);
  }

  int ii, jj, kk;
  float cal_dn, cal_dn2;
  double incid;
  if (dualpol && wh_scaleFlag) {
    metaOut->general->image_data_type = RGB_STACK;
    for (ii=0; ii<line_count; ii++) {
      get_band_float_line(fpIn, metaIn, 0, ii, bufIn);
      get_band_float_line(fpIn, metaIn, 1, ii, bufIn2);
      for (jj=0; jj<sample_count; jj++) {
	// Taking the remapping of other radiometries out for the moment
	//if (inRadiometry >= r_SIGMA && inRadiometry <= r_BETA_DB)
	//bufIn[jj] = cal2amp(metaIn, incid, jj, bands[kk], bufIn[jj]);
	incid = meta_incid(metaIn, ii, jj);
	cal_dn = 
	  get_cal_dn(metaOut, incid, jj, bufIn[jj], bands[0], dbFlag);
	cal_dn2 = 
	  get_cal_dn(metaOut, incid, jj, bufIn2[jj], bands[1], dbFlag);
	if (FLOAT_EQUIVALENT(cal_dn, metaIn->general->no_data) ||
	    cal_dn == cal_dn2) {
	  bufOut[jj] = 0;
	  bufOut2[jj] = 0;
	  bufOut3[jj] = 0;
	}
	else {
	  bufOut[jj] = (cal_dn + 31) / 0.15 + 1.5;
	  bufOut2[jj] = (cal_dn2 + 31) / 0.15 + 1.5;
	  bufOut3[jj] = bufOut[jj] - bufOut2[jj];
	}
      }
      put_band_float_line(fpOut, metaOut, 0, ii, bufOut);
      put_band_float_line(fpOut, metaOut, 1, ii, bufOut2);
      put_band_float_line(fpOut, metaOut, 2, ii, bufOut3);
      asfLineMeter(ii, line_count);
    }
  }
  else {
    for (kk=0; kk<band_count; kk++) {
      for (ii=0; ii<line_count; ii++) {
	get_band_float_line(fpIn, metaIn, kk, ii, bufIn);
	for (jj=0; jj<sample_count; jj++) {
	  // Taking the remapping of other radiometries out for the moment
	  //if (inRadiometry >= r_SIGMA && inRadiometry <= r_BETA_DB)
	  //bufIn[jj] = cal2amp(metaIn, incid, jj, bands[kk], bufIn[jj]);
	  if (strstr(bands[kk], "PHASE") == NULL) {
	    incid = meta_incid(metaIn, ii, jj);
	    cal_dn =
	      get_cal_dn(metaOut, incid, jj, bufIn[jj], bands[kk], dbFlag);
	    if (wh_scaleFlag) {
	      if (FLOAT_EQUIVALENT(cal_dn, metaIn->general->no_data))
		bufOut[jj] = 0;
	      else
		bufOut[jj] = (cal_dn + 31) / 0.15 + 1.5;
	    }
	    else
	      bufOut[jj] = cal_dn;
	  }
	  else // PHASE band, do nothing
	    bufOut[jj] = bufIn[jj];
	}
	put_band_float_line(fpOut, metaOut, kk, ii, bufOut);
	asfLineMeter(ii, line_count);
      }
      if (kk==0)
	sprintf(metaOut->general->bands, "%s-%s", 
		radiometry2str(outRadiometry), bands[kk]);
      else {
	char tmp[255];
	sprintf(tmp, ",%s-%s", radiometry2str(outRadiometry), bands[kk]);
	strcat(metaOut->general->bands, tmp);
      }
    }
  }
  meta_write(metaOut, outFile);
  meta_free(metaIn);
  meta_free(metaOut);
  FREE(bufIn);
  FREE(bufOut);
  if (dualpol) {
    FREE(bufIn2);
    FREE(bufOut2);
    FREE(bufOut3);
  }
  for (kk=0; kk<band_count; ++kk)
    FREE(bands[kk]);
  FREE(bands);
  FCLOSE(fpIn);
  FCLOSE(fpOut);
  FREE(input);
  FREE(output);

  return FALSE;
}