[GRASS-SVN] r51993 - grass-addons/grass7/imagery/i.segment

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Jun 6 09:48:57 PDT 2012


Author: momsen
Date: 2012-06-06 09:48:57 -0700 (Wed, 06 Jun 2012)
New Revision: 51993

Modified:
   grass-addons/grass7/imagery/i.segment/create_isegs.c
   grass-addons/grass7/imagery/i.segment/iseg.h
   grass-addons/grass7/imagery/i.segment/main.c
   grass-addons/grass7/imagery/i.segment/parse_args.c
   grass-addons/grass7/imagery/i.segment/write_output.c
Log:
cleaned up code, finished easy TODO - I/O works.

Modified: grass-addons/grass7/imagery/i.segment/create_isegs.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-06-06 16:48:51 UTC (rev 51992)
+++ grass-addons/grass7/imagery/i.segment/create_isegs.c	2012-06-06 16:48:57 UTC (rev 51993)
@@ -3,17 +3,14 @@
 /* Currently only region growing is implemented */
 
 #include <stdlib.h>
-#include <string.h>
 #include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/imagery.h>
+#include <grass/raster.h>
 #include <grass/segment.h>	/* segmentation library */
 #include "iseg.h"
 
 int create_isegs(struct files *files, struct functions *functions)
 {
-    int row, col, nrows, ncols, *segval;
-    double *bandsval;
+    int row, col, nrows, ncols;
 
     /* **************write fake data to test I/O portion of module */
 
@@ -22,19 +19,16 @@
     ncols = Rast_window_cols();
 
     /* initialize data structure */
-    segval = (int *)G_malloc(2 * sizeof(int));
-    /* TODO why didn't this work?  error: request fof member 'nbands' in something not a structure or union */
-    /* bandsval = (double *) G_malloc(files.nbands * sizeof(double)); */
-    bandsval = (double *)G_malloc(1 * sizeof(double));
+    files->out_val = (int *)G_malloc(2 * sizeof(int));
 
-    G_verbose_message("writing fake data");
+    G_verbose_message("writing fake data to segmentation file");
     for (row = 0; row < nrows; row++) {
 	G_percent(row, nrows, 1);	/*this didn't get displayed in the output??? Does it get erased when done? */
 	for (col = 0; col < ncols; col++) {
-	    //segval[0] = bandsval[0]; /*segment number */  /* just copying the map for testing. */
-	    segval[0] = 42;
-	    segval[1] = 1;	/*processing flag */
-	    segment_put(&files->out_seg, (void *)segval, row, col);
+	    //files->out_val[0] = files->out_val[0]; /*segment number */  /* just copying the map for testing. */
+	    files->out_val[0] = col+2*row;
+	    files->out_val[1] = 1;	/*processing flag */
+	    segment_put(&files->out_seg, (void *)files->out_val, row, col);
 	}
     }
 

Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-06 16:48:51 UTC (rev 51992)
+++ grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-06 16:48:57 UTC (rev 51993)
@@ -13,54 +13,67 @@
  *****************************************************************************/
 
 #include <grass/segment.h>
-#include <grass/raster.h>
 
 struct files
 {
-    /* int *band_fd, out_fd;   Do I need these, or is the SEGMENT enough? */
+    /* user parameters */
+    char *image_group;
+    
     int nbands;
-    SEGMENT bands_seg, out_seg;
+    SEGMENT bands_seg, out_seg; /* bands is for input, normal application is landsat bands, but other input can be included in the group. */
+    double *bands_val;		/* array, to hold all input values at one pixel */
+	int *out_val;			/* array, to hold the segment ID and processing flag(s) */
+    
+    /*
+    * Todo: Memory managment:
+    * If we want to implement the option to load directly to memory
+    * instead of declaring "SEGMENT" could we declare as void
+    * then assign either a SEGMENT or a matrix during the get_input procedure?
+    */
 
-    // naming using "bands" to follow i.smap but it doesn't need to be just landsat bands
+    /* TODO: some parts of the data structure from i.smap
+     * confirm if there is any reason to be using them here
+     * struct Categories output_labels;
+     * char *isdata;
+     */
 
-    // If we want to implement the option to load directly to memory
-    // instead of declaring "SEGMENT" could we declare as void
-    // then assign either a SEGMENT or a matrix during the get_input procedure?
+    /* Todo: Additional data to be stored in this structure:
+     * vector constraints
+     * seeds (Put directly into output map?)
+     * Need to consider if they should be put in RAM or SEGMENT?
+     */
 
-    // i.smap has this:  struct Categories output_labels;
-    // I don't think I'll be using categories...
-
-    // i.smap has:  char *isdata;
-    // not sure yet if I'll need that
-
-    //will need to add something here for the vector contsraints and for seeds
-    // store those directly in RAM instead of SEGMENT library?
-
     char *out_name;		/* name of output raster map */
-    RASTER_MAP_TYPE data_type;	/* assuming input and output are the same right now */
+    /* RASTER_MAP_TYPE data_type;	Removed: input is always DCELL, output is CELL. 
+     *  TODO: if input might be smaller then DCELL, we could detect size and allocate accordingly. */
 };
 
 
-// I think if I use function pointers, I can set up one time in the input
-// what similarity function, etc, will be used later in the processing
-// and make it easier to add additional variations later.
+/* I think if I use function pointers, I can set up one time in the input
+* what similarity function, etc, will be used later in the processing
+* and make it easier to add additional variations later.
+*/
 
 struct functions
 {
 
-    //based on options, such as diagonal neighbors, etc:
-    //      find_neighbor  - point to euclidean or manhattan or ... neighbor function
-    //      calc_simularity
+    /*based on options, such as diagonal neighbors, etc, some function pointers:
+    *      find_neighbor  - point to euclidean or manhattan or ... neighbor function
+    *      calc_simularity
+*/
 
-    /* not really a function, but carry these along here to have one less variable to pass? */
-    float threshold;
+    
+    float threshold; /* similarity threshold */
 
 };
 
 /* parse_args.c */
-/* gets input from user, validates, opens files, and sets up functions */
+/* gets input from user, validates, and sets up functions */
 int parse_args(int, char *[], struct files *, struct functions *);
 
+/* open_files.c */
+int open_files(struct files *);
+
 /* write_output.c */
 /* also currently closes files */
 int write_output(struct files *);

Modified: grass-addons/grass7/imagery/i.segment/main.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/main.c	2012-06-06 16:48:51 UTC (rev 51992)
+++ grass-addons/grass7/imagery/i.segment/main.c	2012-06-06 16:48:57 UTC (rev 51993)
@@ -34,16 +34,16 @@
     module = G_define_module();
     G_add_keyword(_("imagery"));
     G_add_keyword(_("segmentation"));
-    module->description = _("Segments an image.");
+    module->description = _("Outputs a single segmention map (raster) based on input values in an image group.");
 
     parse_args(argc, argv, &files, &functions);
-    /* Write Segmentation Function Next Week !!! */
-
+	G_debug(1, "Main: starting open_files()");
+	open_files(&files);
+	
     G_debug(1, "Main: starting create_isegs()");
     create_isegs(&files, &functions);
 
     G_debug(1, "starting write_output...");
-    G_verbose_message("Main: starting write_output...");
     write_output(&files);
 
     G_done_msg("Number of segments created: ");

Modified: grass-addons/grass7/imagery/i.segment/parse_args.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/parse_args.c	2012-06-06 16:48:51 UTC (rev 51992)
+++ grass-addons/grass7/imagery/i.segment/parse_args.c	2012-06-06 16:48:57 UTC (rev 51993)
@@ -1,13 +1,8 @@
-/* PURPOSE:      Parse and validate the input, including opening input rasters and creating segmentation files */
+/* PURPOSE:      Parse and validate the input */
 
 #include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>		/* needed for creat and open for the segmentation files.
-				   used those functions per the programmer's manual, correct usage? */
 #include <grass/gis.h>
 #include <grass/glocale.h>
-#include <grass/imagery.h>
-#include <grass/segment.h>	/* segmentation library */
 #include "iseg.h"
 
 int parse_args(int argc, char *argv[], struct files *files,
@@ -18,31 +13,11 @@
     struct Option *group, *seeds, *output, *method, *threshold;	/* Establish an Option pointer for each option */
     struct Flag *diagonal;	/* Establish a Flag pointer for each option */
 
-    /* for the opening files portion */
-    struct Ref Ref;		/* group reference list */
-    int *in_fd;
-    RASTER_MAP_TYPE data_type;
-    int n, row, col, nrows, ncols, srows, scols, inlen, outlen, nseg;
-    DCELL **inbuf;		/* buffer array, to store lines from each of the imagery group rasters */
-    double *inval;		/* array, to collect data from one column of inbuf to be put into segmentation file */
-    char *in_file, *out_file;	/* original functions required const char, new segment_open() does not */
-
-    /*debugging */
-    SEGMENT testseg;
-
     group = G_define_standard_option(G_OPT_I_GROUP);
 
-    /* deleted subgroup line, but still appears in input form */
+    /* TODO: OK to require the user to create a group?  Otherwise later add an either/or option to give just a single raster map... */
 
-    /* OK to require the user to create a group?  Otherwise later add an either/or option to give just a single raster map... */
-
-    //~ input = G_define_standard_option(G_OPT_R_INPUT);   /* Request a pointer to memory for each option */
-    //~ input->key = "input"; /* TODO: update to allow groups.  Maybe this needs a group/subgroup variables, or we can check if the input is group/subgroup/raster */
-    //~ input->type = TYPE_STRING;
-    //~ input->required = YES;
-    //~ input->description = _("Raster map to be segmented.");
-
-    /* Using raster for seeds, maybe consider allowing vector points/centroids later. */
+    /* Using raster for seeds, Low priority TODO: allow vector points/centroids seed input. */
     seeds = G_define_standard_option(G_OPT_R_INPUT);
     seeds->key = "seeds";
     seeds->type = TYPE_STRING;
@@ -51,22 +26,12 @@
 
     output = G_define_standard_option(G_OPT_R_OUTPUT);
 
-    //TODO: when put in a new raster map, error message:
-    //~ Command 'd.rast map=testing at samples' failed
-    //~ Details: Raster map <testing at samples> not found
-
-    //Also, that error seems to be accumulated, putting in a new output map names results in:
-    //~ Command 'd.rast map=testing at samples' failed
-    //~ Details: Raster map <testing at samples> not found
-    //~ Command 'd.rast map=test2 at samples' failed
-    //~ Details: Raster map <test2 at samples> not found
-
     method = G_define_option();
     method->key = "method";
     method->type = TYPE_STRING;
     method->required = NO;
-    method->answer = _("region_growing");
-    method->options = "region_growing, mean_shift";
+    method->answer = "region_growing";
+    method->options = "region_growing, io_debug";
     method->description = _("Segmentation method.");
 
     threshold = G_define_option();
@@ -84,6 +49,7 @@
     if (G_parser(argc, argv))
 	exit(EXIT_FAILURE);
 
+
     G_debug(1, "For the option <%s> you chose: <%s>",
 	    group->description, group->answer);
 
@@ -111,148 +77,21 @@
 
 
     /* Check and save parameters */
-
+	
+	files->image_group = group->answer;
+	
     sscanf(threshold->answer, "%f", &functions->threshold);
 
-    /* I'm assuming it is already validated as a number.  Is this OK, or is there a better way to cast the input? */
-    /* r.cost line 313 
+    /* TODO: I'm assuming it is already validated as a number.  Is this OK, or is there a better way to cast the input? */
+    /* reference r.cost line 313 
        if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
        G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost); */
 
-    /* TODO: The following routines create a new raster map in the current mapset and open it for writing. G_legal_filename() should be called first to make sure that raster map name is a valid name. */
+	if (G_legal_filename(output->answer)==1)
+		files->out_name = output->answer;	/* name of output raster map */
+	else
+		G_fatal_error("Invalid output raster name.");
 
-    files->out_name = output->answer;	/* name of output raster map */
 
-
-    /* Open Files (file segmentation) */
-    G_verbose_message("Checking image group...");
-    /* references: i.cost and http://grass.osgeo.org/programming7/segmentlib.html */
-
-
-    /* ****** open the input rasters ******* */
-
-    /* TODO, this is from i.smap/openfiles.c  lines 17-23 checked if subgroup had maps, does API handles the checks? */
-
-    if (!I_get_group_ref(group->answer, &Ref))
-	G_fatal_error(_("Unable to read REF file for group <%s>"),
-		      group->answer);
-
-    if (Ref.nfiles <= 0)
-	G_fatal_error(_("Group <%s> contains no raster maps"), group->answer);
-
-    /* Read Imagery Group */
-
-    in_fd = G_malloc(Ref.nfiles * sizeof(int));
-    inbuf = (DCELL **) G_malloc(Ref.nfiles * sizeof(DCELL *));
-    inval = (double *)G_malloc(Ref.nfiles * sizeof(double));
-
-
-    G_verbose_message("Opening input rasters...");
-    for (n = 0; n < Ref.nfiles; n++) {
-	inbuf[n] = Rast_allocate_d_buf();
-	in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
-    }
-
-
-    /* ********** find out file segmentation size ************ */
-    G_verbose_message("Calculate temp file sizes...");
-
-    /*loop again... need to get largest option
-       //for today assume all are the same
-       //data_type = Rast_get_map_type(in_fd[n]); */
-    files->nbands = Ref.nfiles;
-
-    data_type = Rast_get_map_type(in_fd[0]);
-    files->data_type = data_type;
-
-
-    /* size of each element to be stored */
-
-    inlen = sizeof(double) * Ref.nfiles;
-    outlen = sizeof(int) * 2;	/* change in write_output.c if this value changes TODO: better to save this in the files data structure? */
-
-    nrows = Rast_window_rows();
-    ncols = Rast_window_cols();
-
-    /*TODO: i.cost and i.watershed take different approaches...hardcode for now */
-    /* when fine tuning, should be a power of 2 and not larger than 256 for speed reasons */
-    srows = 64;
-    scols = 64;
-
-    /* TODO: make calculations for this */
-    nseg = 8;
-
-
-    /* ******* create temporary segmentation files ********* */
-    G_verbose_message("Getting temporary file names...");
-    /* Initalize access to database and create temporary files */
-
-
-    in_file = G_tempfile();
-    out_file = G_tempfile();
-
-    G_debug(1, "Image size:  %d rows, %d cols", nrows, ncols);
-    G_debug(1, "Segmented to tiles with size:  %d rows, %d cols", srows,
-	    scols);
-    G_debug(1, "File names, in: %s, out: %s", in_file, out_file);
-    G_debug(1, "Data element size, in: %d , out: %d ", inlen, outlen);
-    G_debug(1, "number of segments to have in memory: %d", nseg);
-
-    /* size: reading all input bands as DCELL  TODO: could consider checking input to see if it is all FCELL or CELL, could reduce memory requirements. */
-
-    if (segment_open
-	(&files->bands_seg, in_file, nrows, ncols, srows, scols, inlen,
-	 nseg) != 1)
-	G_fatal_error("Unable to create input temporary files");
-
-    /* programmer's manual had G_tempfile() directly in call.  Do I need to know the temp file name to delete it? */
-
-    G_debug(1, "finished segment_open(...bands_seg...)");
-
-    /* TODO: signed integer gives a 2 billion segment limit, depending on how the initialization is done, this means 2 billion max input pixels. */
-    if (segment_open
-	(&files->out_seg, out_file, nrows, ncols, srows, scols, outlen,
-	 nseg) != 1)
-	G_fatal_error("Unable to create output temporary files");
-
-    /*
-       int segment_open(SEGMENT *SEG, char *fname, off_t nrows, off_t ncols, int srows, int scols, int len, int nseg), open a new segment structure.
-
-       A new file with full path name fname will be created and formatted. The original nonsegmented data matrix consists of nrows and ncols. The segments consist of srows by scols. The data items have length len bytes. The number of segments to be retained in memory is given by nseg. This routine calls segment_format() and segment_init(), see below. If segment_open() is used, the routines segment_format() and segment_init() must not be used.
-     */
-
-    /* load input bands to segment structure */
-    G_verbose_message("Reading input rasters into temporary data files...");
-
-    for (row = 0; row < nrows; row++) {
-	for (n = 0; n < Ref.nfiles; n++) {
-	    Rast_get_d_row(in_fd[n], inbuf[n], row);
-	}
-	for (col = 0; col < ncols; col++) {
-	    for (n = 0; n < Ref.nfiles; n++) {
-		inval[n] = inbuf[n][col];
-	    }
-	    segment_put(&files->bands_seg, (void *)inval, row, col);
-	}
-    }
-
-    /* Don't need to do anything else for the output segmentation file?  It is initialized to zeros and will be written to later... */
-
-    /* Free memory */
-
-    for (n = 0; n < Ref.nfiles; n++) {
-	Rast_close(in_fd[n]);
-    }
-
-    G_free(inbuf);
-    G_free(in_fd);
-
-
-    /* Need to clean up anything else?  Need to close segmentation files?  Or they should be open still since they will be used later?  Close after all processing is done? */
-
-    /*
-       from r.cost
-       unlink(in_file); *//* remove submatrix files  */
-
     return 0;
 }

Modified: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c	2012-06-06 16:48:51 UTC (rev 51992)
+++ grass-addons/grass7/imagery/i.segment/write_output.c	2012-06-06 16:48:57 UTC (rev 51993)
@@ -1,10 +1,9 @@
 /* transfer the segmented regions from the segmented data file to a raster file */
-/* put closing segment files here for now, OK to combine or better to put somewhere else? */
+/* put closing segment files here for now, OK to combine or better to put in a seperate function? */
 
 #include <stdlib.h>
 #include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/imagery.h>
+#include <grass/raster.h>
 #include <grass/segment.h>	/* segmentation library */
 #include "iseg.h"
 
@@ -12,10 +11,8 @@
 {
     int out_fd, row, col, nrows, ncols;
     CELL *outbuf;
-    int *outval;
 
     outbuf = Rast_allocate_c_buf();	/*hold one row of data to put into raster */
-    outval = (int *)G_malloc(2 * sizeof(int));	/* hold one "cell" from the segmentation file */
 
     /*picked this up in the file reading as well, just do it again? */
     nrows = Rast_window_rows();
@@ -27,24 +24,19 @@
 
     G_debug(1, "preparing output raster");
     /* open output raster map */
-    out_fd = Rast_open_new(files->out_name, CELL_TYPE);	/* I assume even if it already exists, this will overwrite it... */
+    out_fd = Rast_open_new(files->out_name, CELL_TYPE);
 
     G_debug(1, "start data transfer from segmentation file to raster");
     /* transfer data from segmentation file to raster */
-    /* output segmentation file, each element includes the segment ID then the processing flag.  So just need the first part of it. */
-    /* Hmm, does this mean I can't use a buffer, since the length isn't simply integer or float?! */
+    /* output segmentation file: each element includes the segment ID then processing flag(s).  So just need the first part of it. */
 
     for (row = 0; row < nrows; row++) {
-	G_percent(row, nrows, 1);
+	G_percent(row, nrows, 1); /*TODO: Why isn't this getting printed? */
 	for (col = 0; col < ncols; col++) {
-	    //~ G_debug(1, "got here");
-	    /* didn't work?                 segment_get(&files->out_seg, &outval, row, col); */
-	    segment_get(&files->out_seg, (void *)outval, row, col);	/* segment_get (&seg, &value, row, col); */
-	    //~ G_debug(1, "segment_get() worked");
-	    //~ G_debug(1, "outval[0] = %i", outval[0]); /*This didn't work - something is wrong with outval reference */
-	    outbuf[col] = outval[0];	/*just want segment assignment, not the other processing flag(s) */
+	    segment_get(&files->out_seg, (void *)files->out_val, row, col);
+	    G_debug(5, "outval[0] = %i", files->out_val[0]);
+	    outbuf[col] = files->out_val[0];	/*just want segment assignment, not the other processing flag(s) */
 	}
-	//~ G_debug(1, "just before Rast_put_row()");
 	Rast_put_row(out_fd, outbuf, CELL_TYPE);
     }
 
@@ -55,8 +47,6 @@
     segment_close(&files->out_seg);
     Rast_close(out_fd);
 
-    /* TODO Note: The Segment Library does not know the name of the segment file. It does not attempt to remove the file. If the file is only temporary, the programmer should remove the file after closing it. */
-
     /* anything else left to clean up? */
 
     return 0;



More information about the grass-commit mailing list