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

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jun 1 15:09:43 PDT 2012


Author: momsen
Date: 2012-06-01 15:09:42 -0700 (Fri, 01 Jun 2012)
New Revision: 51922

Added:
   grass-addons/grass7/imagery/i.segment/write_output.c
Modified:
   grass-addons/grass7/imagery/i.segment/get_input.c
   grass-addons/grass7/imagery/i.segment/iseg.h
   grass-addons/grass7/imagery/i.segment/main.c
Log:
compiles, but still need to debug.  I/O with segmentation library and groups written

Modified: grass-addons/grass7/imagery/i.segment/get_input.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/get_input.c	2012-06-01 18:42:45 UTC (rev 51921)
+++ grass-addons/grass7/imagery/i.segment/get_input.c	2012-06-01 22:09:42 UTC (rev 51922)
@@ -1,54 +1,34 @@
-/****************************************************************************
- *
- * MODULE:       i.segment
- * AUTHOR(S):    Eric Momsen <eric.momsen at gmail com>
- * PURPOSE:      Parse and validate the input
- * COPYRIGHT:    (C) 2012 by Eric Momsen, and the GRASS Development Team
- *
- *               This program is free software under the GNU General Public
- *               License (>=v2). Read the COPYING file that comes with GRASS
- *               for details.
- *
- *****************************************************************************/
+/* PURPOSE:      Parse and validate the input, including opening input rasters and creating segmentation files */
 
-//Should this type of comment block go at the beginning of all sub files?
-
 #include <stdlib.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 get_input(int argc, char *argv[], struct files *files, struct functions *functions)
+int parse_args(int argc, char *argv[], struct files *files, struct functions *functions)
 {
-	//reference: http://grass.osgeo.org/programming7/gislib.html#Command_Line_Parsing
+	/* reference: http://grass.osgeo.org/programming7/gislib.html#Command_Line_Parsing */
 	
-	struct Option *group, *subgroup, *seeds, *output, *method, *threshold; //*input,     /* Establish an Option pointer for each option */
-	struct Flag *diagonal;        /* Establish a Flag pointer for each option */
+	struct Option *group, *subgroup, *seeds, *output, *method, *threshold; 	/* Establish an Option pointer for each option */
+	struct Flag *diagonal;       											/* Establish a Flag pointer for each option */
 
 	group = G_define_standard_option(G_OPT_I_GROUP);
 	
 	subgroup = G_define_standard_option(G_OPT_I_SUBGROUP);
 	
-	//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.");
 	
-	//~ seeds = G_define_standard_option(G_OPT_V_INPUT);
-	//~ seeds->key = "seeds";
-	//~ seeds->type = TYPE_STRING;
-	//~ seeds->required = NO;
-	//~ seeds->description = _("Optional vector map with starting seeds.");
-//~ 	need to add a secondary part of this input (centroids or points) and validate 0 or both optional parameters are used.
-	//~ The vector input seems more user friendly, but raster will be more straightforward to implement.
-	//~ Is there any concern that the raster seeds will cover more than one pixel if the resolution is changed?
-	//~ That might be a reason to switch back to points later.
-//~ 
+	/* Using raster for seeds, maybe consider allowing vector points/centroids later. */
 	seeds = G_define_standard_option(G_OPT_R_INPUT);
 	seeds->key = "seeds";
 	seeds->type = TYPE_STRING;
@@ -56,7 +36,7 @@
 	seeds->description = _("Optional raster map with starting seeds.");
 	
 	output = G_define_standard_option(G_OPT_R_OUTPUT);
-//seems API handles this part...
+//seems API handles this part ?
 	//~ output->key = "output";
 	//~ output->type = TYPE_STRING;
 	//~ output->required = YES;
@@ -76,8 +56,8 @@
 	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, mean_shift";
 	method->description = _("Segmentation method.");
 	
 	threshold = G_define_option();
@@ -90,8 +70,7 @@
     diagonal->key = 'd';
     diagonal->description = _("Use 8 neighbors (3x3 neighborhood) instead of the default 4 neighbors for each pixel.");
 
-	//use checker for any of the data validation steps!?
-	
+
 	//~ G_debug(1, "testing debug!");
 	//~ When put this in, get an error (only when DEBUG is set, if not set, it runs fine)
 	//~ 
@@ -120,22 +99,51 @@
 	if (G_parser(argc, argv))
         exit (EXIT_FAILURE);
 
+/* Validation */
 
-// Open Files (file segmentation) //
+	/* use checker for any of the data validation steps!? */
+	
+	/* ToDo The most important things to check are if the
+input and output raster maps can be opened (non-negative file
+descriptor). */
 
+
+/* Check and save parameters */
+
+	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 
+	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. */
+	
+	files->out_name = output->answer;  /* name of output raster map */
+	
+
+/* Open Files (file segmentation) */
+
+/* references: i.cost and http://grass.osgeo.org/programming7/segmentlib.html */
+
 	struct Ref Ref;             /* subgroup reference list */
-	int *in_fd, out_fd, *seg_in_fd, seg_out_fd;
+	int *in_fd, *seg_in_fd, seg_out_fd;
 	RASTER_MAP_TYPE data_type;
-	int n, row, col, nrows, ncols, srows, scols, seg_in_mem;
+	int n, row, nrows, ncols, srows, scols, seg_in_mem;
 	void *inbuf;
-    int buf[NCOLS]; /* for copying into segmentation file */
+    const char *in_file[7], *out_file;  
+			/*TODO  put const 7 for now, need to dynamically get size based on number of input rasters, commented out "new" statement later on */
     
-    const char *in_file, out_file;
+    /* int buf[NCOLS]; */
+						/* c question... will using void data type be the right way, until I know what the data type is? */
+						/* that was in the developer's manual... but would void *buf also work? */
+	/* void *buf; */	/* for copying from raster into segmentation file */
+	
     
-    // ****** open the input rasters ******* //
+    /* ****** open the input rasters ******* */
     
-    // i.smap/openfiles.c  lines 17-23 checked if subgroup had maps, does API handles the checks?
-    // can no subgroup be entered, just a group?
+    /* i.smap/openfiles.c  lines 17-23 checked if subgroup had maps, does API handles the checks?
+     can no subgroup be entered, just a group? */
     
 	if (!I_get_subgroup_ref(group->answer,subgroup->answer, &Ref))
 		G_fatal_error(_("Unable to read REF file for subgroup <%s> in group <%s>"),
@@ -145,38 +153,46 @@
 		G_fatal_error(_("Subgroup <%s> in group <%s> contains no raster maps"),
 			subgroup->answer, group->answer);
     
-	// open input group maps for reading
+	/* open input group maps for reading */
+	
+	/* TODO ? compiler warning, in_fd was not initialized */
+	
 	for(n = 0; n < Ref.nfiles; n++)
 	{
-		in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);  //    in_fd = Rast_open_old(input->answer, "");
+		in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset);
 	}	
 
 	
+    /* ********** find out file segmentation size ************ */
 
-    // ********** find out file segmentation size ************ //
-
-    //loop again... need to get largest option
+    /*loop again... need to get largest option
 	//for today assume all are the same
-		//data_type = Rast_get_map_type(in_fd[n]);
+		//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;
     
     nrows = Rast_window_rows();
     ncols = Rast_window_cols();
 	
-	//TODO: i.cost and i.watershed take different approaches...
-	//hardcode for now
+	/*TODO: i.cost and i.watershed take different approaches...
+	//hardcode for now */
 	srows = nrows / 8;
 	scols = ncols / 8;
 
-	//TODO: make calculations for this
+	/* TODO: make calculations for this */
 	seg_in_mem = 4;
 
-//    G_debug(1, "  %d rows, %d cols", nrows, ncols);
+/*    G_debug(1, "  %d rows, %d cols", nrows, ncols); ... never tried this, just copied from other module */
 	
     
-    // ******** create temporary segmentation failes **********//
+    /* ******* create temporary segmentation files ********* */
     
     /* Initalize access to database and create temporary files */
+    
+    /* in_file = new char[Ref.nfiles];  Need G_allocate or something here? */
+    
     for(n = 0; n < Ref.nfiles; n++)
 	{
 		in_file[n] = G_tempfile();
@@ -185,12 +201,15 @@
 	out_file = G_tempfile();
     
     /* Format segmented files */
+    
+    /* TODO ? compiler warning, in_fd was not initialized */
+    
     for(n = 0; n < Ref.nfiles; n++)
 	{
 		seg_in_fd[n] = creat(in_file[n], 0666);
-		if (segment_format(seg_in_fd[n], nrows, ncols, srows, scols, sizeof(data_type)) != 1) //TODO: this data_type should be from each map
+		if (segment_format(seg_in_fd[n], nrows, ncols, srows, scols, sizeof(data_type)) != 1) /* TODO: this data_type should be from each map */
 		G_fatal_error("can not create temporary file");
-		close(seg_in_fd[n]);
+		close(seg_in_fd[n]);  /* why close when we just reopen again?  Different access mode between creat and open ? */
     }
 	seg_out_fd = creat(out_file, 0666);
 	if (segment_format(seg_out_fd, nrows, ncols, srows, scols, sizeof(data_type)) != 1)
@@ -201,39 +220,50 @@
 	/* Open and initialize all segment files */
     for(n = 0; n < Ref.nfiles; n++)
 	{
-		seg_in_fd[n] = open(in_file[n], 2);  //TODO: second parameter here is different in many places...
+		seg_in_fd[n] = open(in_file[n], 2);  /* TODO: second parameter here is different in many places... */
 		if (segment_init(&files->bands_seg[n], seg_in_fd[n], seg_in_mem) != 1)
 			G_fatal_error("can not initialize temporary file");
 	}
-		seg_out_fd = open(out_file, 2);
-		if (segment_init(&files->out_seg, seg_out_fd, seg_in_mem) != 1)
-			G_fatal_error("can not initialize temporary file");
-    
+	seg_out_fd = open(out_file, 2);
+	if (segment_init(&files->out_seg, seg_out_fd, seg_in_mem) != 1)
+		G_fatal_error("can not initialize temporary file");
+
     /* convert flat files to segmented files */
-	inbuf = Rast_allocate_buf(data_type);
-	/* allocate memory for buf? */
+	inbuf = Rast_allocate_buf(data_type); /* buffer from the raster file */
 	
+	/* buf = new data_type [ncols] */ /* buffer to read data into, cell by cell.  But can I just write inbuf directly to the segmentation file??? */
+	
 	for (n = 0; n < Ref.nfiles; n++)
 	{
 		for (row = 0; row < nrows; row++)
 		{
 			Rast_get_row(in_fd[n], inbuf, row, data_type);
-			for (col = 0; col < ncols; col++)
-			{
-				/*fill buf */
-				// G_incr_void_ptr
-			}
-			segment_put_row (&files->bands_seg[n], buf, row);
+			//~ for (col = 0; col < ncols; col++)
+			//~ {
+				//~ /*fill buf */
+				//~ // G_incr_void_ptr
+			//~ }
+			
+			segment_put_row (&files->bands_seg[n], inbuf, row);
 		}
 	}
 
-	/* repeat for output */
+	/* Don't need to do anything else for the output segmentation file?  It is initialized to zeros and will be written to later... */
 
-	/* close stuff!!!  in_fd, seg_in_fd, etc, etc */
+	/* Free memory */
 	
+	for(n = 0; n < Ref.nfiles; n++)
+	{
+		 Rast_close(in_fd[n]);
+	}	
+	
+	G_free(inbuf);
+	
+	/* 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  */
+	unlink(in_file);*/		/* remove submatrix files  */
 	
 	return 0;
 }

Modified: grass-addons/grass7/imagery/i.segment/iseg.h
===================================================================
--- grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-01 18:42:45 UTC (rev 51921)
+++ grass-addons/grass7/imagery/i.segment/iseg.h	2012-06-01 22:09:42 UTC (rev 51922)
@@ -11,9 +11,12 @@
  *
  *****************************************************************************/
 
+#include <grass/segment.h>
+#include <grass/raster.h>
+
 struct files
 {
-	/* int *band_fd, out_fd;  /* Do I need these, or is the SEGMENT enough? */
+	/* int *band_fd, out_fd;   Do I need these, or is the SEGMENT enough? */
 	int nbands;
 	SEGMENT *bands_seg, out_seg;
 	
@@ -31,6 +34,9 @@
 	
 	//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 */
 };
 
 
@@ -42,14 +48,18 @@
 {
 
 //based on options, such as diagonal neighbors, etc:
-//	find_neighbor
+//	find_neighbor  - point to euclidean or manhattan or ... neighbor function
 //	calc_simularity
 		
-	//not really a function, but input to the functions
-	double threshold;
+	/* not really a function, but carry these along here to have one less variable to pass? */
+	float threshold;
+
 };
 
 /* get_input.c */
 /* gets input from user, validates, opens files, and sets up functions */
-int get_input(int, char *[], struct files *, struct functions *);
+int parse_args(int, char *[], struct files *, struct functions *);
 
+/* 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-01 18:42:45 UTC (rev 51921)
+++ grass-addons/grass7/imagery/i.segment/main.c	2012-06-01 22:09:42 UTC (rev 51922)
@@ -17,22 +17,11 @@
  * 
  *****************************************************************************/
 
-// #include <grass/config.h>
-
 #include <stdlib.h>
-// #include <unistd.h>
 #include <grass/gis.h>
-//#include <grass/imagery.h>
-#include <grass/glocale.h>   //defines _()  what exactly is that doing...(something about local language translation?) anything else in glocale.h that I should be aware of...
-#include <grass/raster.h>
+#include <grass/glocale.h> /* message translation */
 #include "iseg.h"
 
-//~ (for my reference, order for headers), adding them only as needed...
-//~ 1. Core system headers (stdio.h, ctype.h, ...)
-//~ 2. Headers for non-core system components (X11, libraries).
-//~ 3. Headers for core systems of the package being compiled (grass/gis.h, grass/glocale.h, ...)
-//~ 4. Headers for the specific library/program being compiled (geodesic.h, ...)
-
 int main(int argc, char *argv[])
 {
 	struct files files;		/* input and output file descriptors, data structure, buffers */
@@ -46,13 +35,9 @@
 	G_add_keyword(_("segmentation"));
 	module->description = _("Segments an image.");
 
-	get_input(argc, argv, files, functions);
-	
-//need to update this part still:
-	G_free(inbuf);
-	Rast_close(in_fd);
-    Rast_close(out_fd);
-//
+	parse_args(argc, argv, &files, &functions);
+	/* Write Segmentation Function Next Week !!! */
+    write_output(&files);
     
 	G_done_msg("Number of segments created: ");
 	

Added: grass-addons/grass7/imagery/i.segment/write_output.c
===================================================================
--- grass-addons/grass7/imagery/i.segment/write_output.c	                        (rev 0)
+++ grass-addons/grass7/imagery/i.segment/write_output.c	2012-06-01 22:09:42 UTC (rev 51922)
@@ -0,0 +1,45 @@
+/* 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? */
+
+#include <stdlib.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/segment.h> /* segmentation library */
+#include "iseg.h"
+
+int write_output(struct files *files)
+{
+	int out_fd, row, n;
+	void *outbuf;
+	outbuf = Rast_allocate_buf(files->data_type); 
+
+	/* Todo: return codes are 1 for these, need to check and react to errors? programmer's manual didn't include it... */
+	
+	segment_flush(&files->out_seg); /* force all data to disk */
+	
+	
+	/* open output raster map */
+	out_fd = Rast_open_new(files->out_name, files->data_type); /* I assume even if it already exists, this will overwrite it... */
+	
+	/* transfer data row by row */
+	for (row = 0; row < 100; row++) /* need to acces nrows, syntax?  files->out_seg::nrows  ??? */
+	{
+		segment_get_row (&files->out_seg, outbuf, row); //segment_get_row (SEGMENT *seg, char *buf, int row)
+		Rast_put_row(out_fd, outbuf, files->data_type);
+	}
+	
+	/* close segmentation files and output raster */
+	
+	for(n = 0; n < files->nbands; n++)
+	{
+		segment_release (&files->bands_seg[n]);
+	}
+	segment_release (&files->out_seg);
+	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