Exemple #1
0
int main(int argc, char *argv[])
{
    int i, j;			/* Loop control variables */
    int bands;			/* Number of image bands */
    double *mu;			/* Mean vector for image bands */
    double **covar;		/* Covariance Matrix */
    double *eigval;
    double **eigmat;
    int *inp_fd;
    int scale, scale_max, scale_min;

    struct GModule *module;
    struct Option *opt_in, *opt_out, *opt_scale;

    /* initialize GIS engine */
    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("imagery"));
    G_add_keyword(_("image transformation"));
    G_add_keyword(_("PCA"));
    module->description = _("Principal components analysis (PCA) "
			    "for image processing.");

    /* Define options */
    opt_in = G_define_standard_option(G_OPT_R_INPUTS);
    opt_in->description = _("Name of two or more input raster maps");

    opt_out = G_define_option();
    opt_out->label = _("Base name for output raster maps");
    opt_out->description =
	_("A numerical suffix will be added for each component map");
    opt_out->key = "output_prefix";
    opt_out->type = TYPE_STRING;
    opt_out->key_desc = "string";
    opt_out->required = YES;

    opt_scale = G_define_option();
    opt_scale->key = "rescale";
    opt_scale->type = TYPE_INTEGER;
    opt_scale->key_desc = "min,max";
    opt_scale->required = NO;
    opt_scale->answer = "0,255";
    opt_scale->label =
	_("Rescaling range for output maps");
    opt_scale->description =
	_("For no rescaling use 0,0");
    opt_scale->guisection = _("Rescale");
    
    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);


    /* determine number of bands passed in */
    for (bands = 0; opt_in->answers[bands] != NULL; bands++) ;

    if (bands < 2)
	G_fatal_error(_("Sorry, at least 2 input bands must be provided"));

    /* default values */
    scale = 1;
    scale_min = 0;
    scale_max = 255;

    /* get scale parameters */
    set_output_scale(opt_scale, &scale, &scale_min, &scale_max);

    /* allocate memory */
    covar = G_alloc_matrix(bands, bands);
    mu = G_alloc_vector(bands);
    inp_fd = G_alloc_ivector(bands);
    eigmat = G_alloc_matrix(bands, bands);
    eigval = G_alloc_vector(bands);

    /* open and check input/output files */
    for (i = 0; i < bands; i++) {
	char tmpbuf[128];

	sprintf(tmpbuf, "%s.%d", opt_out->answer, i + 1);
	G_check_input_output_name(opt_in->answers[i], tmpbuf, GR_FATAL_EXIT);

	inp_fd[i] = Rast_open_old(opt_in->answers[i], "");
    }

    G_verbose_message(_("Calculating covariance matrix..."));
    calc_mu(inp_fd, mu, bands);

    calc_covariance(inp_fd, covar, mu, bands);

    for (i = 0; i < bands; i++) {
	for (j = 0; j < bands; j++) {
	    covar[i][j] =
		covar[i][j] /
		((double)((Rast_window_rows() * Rast_window_cols()) - 1));
	    G_debug(3, "covar[%d][%d] = %f", i, j, covar[i][j]);
	}
    }

    G_math_d_copy(covar[0], eigmat[0], bands*bands);
    G_debug(1, "Calculating eigenvalues and eigenvectors...");
    G_math_eigen(eigmat, eigval, bands);

#ifdef PCA_DEBUG
    /* dump eigen matrix and eigen values */
    dump_eigen(bands, eigmat, eigval);
#endif

    G_debug(1, "Ordering eigenvalues in descending order...");
    G_math_egvorder(eigval, eigmat, bands);

    G_debug(1, "Transposing eigen matrix...");
    G_math_d_A_T(eigmat, bands);

    /* write output images */
    write_pca(eigmat, inp_fd, opt_out->answer, bands, scale, scale_min,
	      scale_max);

    /* write colors and history to output */
    for (i = 0; i < bands; i++) {
	char outname[80];

	sprintf(outname, "%s.%d", opt_out->answer, i + 1);

	/* write colors and history to file */
	write_support(bands, outname, eigmat, eigval);

	/* close output file */
	Rast_unopen(inp_fd[i]);
    }
    
    /* free memory */
    G_free_matrix(covar);
    G_free_vector(mu);
    G_free_ivector(inp_fd);
    G_free_matrix(eigmat);
    G_free_vector(eigval);

    exit(EXIT_SUCCESS);
}
Exemple #2
0
void interface(int argc, char **argv)
{

    /*--------------------------------------------------------------------------*/
    /*                                 INITIALISE                               */

    /*--------------------------------------------------------------------------*/

    struct Option *rast_in,	/* Name of input file from command line. */
     *rast_out,			/* Holds name of output file.           */
     *tol1_val,			/* Tolerance values for feature         */
     *tol2_val,			/* detection (slope and curvature).     */
     *win_size,			/* Size of side of local window.        */
     *parameter,		/* Morphometric parameter to calculate. */
     *expon,			/* Inverse distance exponent for weight. */
     *vert_sc;			/* Vertical scaling factor.             */

    struct Flag *constr;	/* Forces quadratic through the central */

    /* cell of local window if selected.    */
    struct GModule *module;	/* GRASS module description */
    char buf[24];

    G_gisinit(argv[0]);		/* GRASS function which MUST be called  */
    /* first to check for valid database    */
    /* and mapset and prompt user for input. */


    /*--------------------------------------------------------------------------*/
    /*                            SET PARSER OPTIONS                            */

    /*--------------------------------------------------------------------------*/

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("geomorphology"));
    module->label = _("Extracts terrain parameters from a DEM.");
    module->description = _("Uses a multi-scale approach"
			    " by taking fitting quadratic parameters to any size window (via least squares).");

    rast_in = G_define_standard_option(G_OPT_R_INPUT);
    rast_out = G_define_standard_option(G_OPT_R_OUTPUT);
    tol1_val = G_define_option();	/* Request memory for each option.      */
    tol2_val = G_define_option();
    win_size = G_define_option();
    parameter = G_define_option();
    expon = G_define_option();
    vert_sc = G_define_option();

    constr = G_define_flag();

    /* Each option has a 'key' (short descriptn), a 'description` (longer one)  */
    /* a 'type' (eg int, or string), and an indication whether manditory or not */

    rast_out->description =
	_("Name for output raster map containing morphometric parameter");

    tol1_val->key = "s_tol";
    tol1_val->description =
	_("Slope tolerance that defines a 'flat' surface (degrees)");
    tol1_val->type = TYPE_DOUBLE;
    tol1_val->required = NO;
    tol1_val->answer = "1.0";

    tol2_val->key = "c_tol";
    tol2_val->description =
	_("Curvature tolerance that defines 'planar' surface");
    tol2_val->type = TYPE_DOUBLE;
    tol2_val->required = NO;
    tol2_val->answer = "0.0001";

    sprintf(buf, "3-%i", MAX_WSIZE);
    win_size->key = "size";
    win_size->description = _("Size of processing window (odd number only)");
    win_size->type = TYPE_INTEGER;
    win_size->required = NO;
    win_size->options = G_store(buf);
    win_size->answer = "3";

    parameter->key = "param";
    parameter->description =
	_("Morphometric parameter in 'size' window to calculate");
    parameter->type = TYPE_STRING;
    parameter->required = NO;
    parameter->options =
	"elev,slope,aspect,profc,planc,longc,crosc,minic,maxic,feature";
    parameter->answer = "elev";

    expon->key = "exp";
    expon->description = _("Exponent for distance weighting (0.0-4.0)");
    expon->type = TYPE_DOUBLE;
    expon->required = NO;
    expon->answer = "0.0";

    vert_sc->key = "zscale";
    vert_sc->description = _("Vertical scaling factor");
    vert_sc->type = TYPE_DOUBLE;
    vert_sc->required = NO;
    vert_sc->answer = "1.0";

    constr->key = 'c';
    constr->description = _("Constrain model through central window cell");


    if (G_parser(argc, argv))	/* Actually performs the prompting for      */
	exit(EXIT_FAILURE);	/* keyboard input.                      */


    rast_in_name = rast_in->answer;	/* Now  keyboard input has been parsed, */
    rast_out_name = rast_out->answer;	/* can place the contents into strings  */
    wsize = atoi(win_size->answer);
    constrained = constr->answer;
    sscanf(expon->answer, "%lf", &exponent);
    sscanf(vert_sc->answer, "%lf", &zscale);
    sscanf(tol1_val->answer, "%lf", &slope_tol);
    sscanf(tol2_val->answer, "%lf", &curve_tol);

    if ((exponent < 0.0) || (exponent > 4.0))
	exponent = 0.0;

    if (zscale == 0.0)
	zscale = 1;

    if (!strcmp(parameter->answer, "elev"))
	mparam = ELEV;
    else if (!strcmp(parameter->answer, "slope"))
	mparam = SLOPE;
    else if (!strcmp(parameter->answer, "aspect"))
	mparam = ASPECT;
    else if (!strcmp(parameter->answer, "profc"))
	mparam = PROFC;
    else if (!strcmp(parameter->answer, "planc"))
	mparam = PLANC;
    else if (!strcmp(parameter->answer, "crosc"))
	mparam = CROSC;
    else if (!strcmp(parameter->answer, "longc"))
	mparam = LONGC;
    else if (!strcmp(parameter->answer, "maxic"))
	mparam = MAXIC;
    else if (!strcmp(parameter->answer, "minic"))
	mparam = MINIC;
    else if (!strcmp(parameter->answer, "feature"))
	mparam = FEATURE;
    else {
	G_warning(_("Morphometric parameter not recognised. Assuming 'Elevation'"));
	mparam = ELEV;
    }

    /* make sure input and output names are valid */
    G_check_input_output_name(rast_in_name, rast_out_name, G_FATAL_EXIT);

    if ((wsize / 2 != (wsize - 1) / 2) || (wsize > MAX_WSIZE))
	G_fatal_error(_("Inappropriate window size (too big or even)"));
}