浏览代码

move i.segment to grass-addons

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@54998 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz 12 年之前
父节点
当前提交
0e0af9447b

+ 0 - 10
imagery/i.segment/Makefile

@@ -1,10 +0,0 @@
-MODULE_TOPDIR = ../..
-
-PGM = i.segment
-
-LIBES = $(IMAGERYLIB) $(RASTERLIB) $(SEGMENTLIB) $(GISLIB) $(LINKMLIB) $(BTREE2LIB)
-DEPENDENCIES = $(IMAGERYDEP) $(RASTERDEP) $(SEGMENTDEP) $(GISDEP) $(LINKMDEP)
-
-include $(MODULE_TOPDIR)/include/Make/Module.make
-
-default: cmd

文件差异内容过多而无法显示
+ 0 - 1244
imagery/i.segment/create_isegs.c


+ 0 - 94
imagery/i.segment/estimate_threshold.c

@@ -1,94 +0,0 @@
-/* Purpose: open input files and suggest a reasonable threshold */
-
-#include <stdlib.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/imagery.h>
-#include "iseg.h"
-
-int estimate_threshold(char *image_group)
-{
-    double min, max, est_t;
-
-    /* check if the input image group is valid. */
-    check_group(image_group);
-
-    /* read the raster files to find the minimum and maximum values */
-    read_range(&min, &max, image_group);
-
-    /* perform the calculations to estimate the threshold */
-    est_t = calc_t(min, max);
-
-    /* set the output message and finish */
-    G_done_msg(_("Suggested threshold (if using -w flag and radioweight=1) is: <%g>"),
-	       est_t);
-    return TRUE;
-}
-
-/* function to validate that the user input is readable and contains files */
-int check_group(char *image_group)
-{
-    struct Ref Ref;		/* group reference list */
-
-    /* check that the input image group can be found */
-    if (!I_get_group_ref(image_group, &Ref))
-	G_fatal_error(_("Unable to read REF file for group <%s>"),
-		      image_group);
-
-    /* check that the input image group contains rasters */
-    if (Ref.nfiles <= 0)
-	G_fatal_error(_("Group <%s> contains no raster maps"), image_group);
-
-    return TRUE;
-}
-
-/* function to find the min and max values in all rasters of an image group */
-int read_range(double *min, double *max, char *image_group)
-{
-    int n;
-    struct FPRange fp_range;	/* range for a raster */
-    struct Ref Ref;		/* group reference list */
-    double candidate_min, candidate_max;	/* for min/max in each raster */
-
-    /* read the image group */
-    I_get_group_ref(image_group, &Ref);
-
-    /* initialize min/max with the first raster min/max */
-    if (Rast_read_fp_range(Ref.file[0].name, Ref.file[0].mapset, &fp_range) != 1)	/* returns -1 on error, 2 on empty range, quiting either way. */
-	G_fatal_error(_("No min/max found in raster map <%s>"),
-		      Ref.file[0].name);
-    else
-	Rast_get_fp_range_min_max(&fp_range, min, max);
-
-    /* check the min/max for any remaining rasters */
-    for (n = 1; n < Ref.nfiles; n++) {
-	if (Rast_read_fp_range(Ref.file[n].name, Ref.file[n].mapset, &fp_range) != 1) {	/* returns -1 on error, 2 on empty range, quiting either way. */
-	    G_fatal_error(_("No min/max found in raster map <%s>"),
-			  Ref.file[n].name);
-
-	    Rast_get_fp_range_min_max(&fp_range, &candidate_min,
-				      &candidate_max);
-
-	    if (candidate_min < *min)
-		*min = candidate_min;
-	    if (candidate_max > *max)
-		*max = candidate_max;
-	}
-    }
-
-    return TRUE;
-}
-
-/* function to calculate a suggested threshold based on the min and max values of the rasters */
-double calc_t(double min, double max)
-{
-    double t, fraction;
-
-    /* Empirical testing indicated 1 to 5% of the differences was a good starting point. */
-    fraction = 0.03;
-
-    /* TODO: allow the community to test this estimate, the formula can be updated based on their advice. */
-    t = fraction * (max - min);
-
-    return t;
-}

+ 0 - 49
imagery/i.segment/flag.c

@@ -1,49 +0,0 @@
-#include <grass/gis.h>
-#include "flag.h"
-
-int flag_clear_all(FLAG * flags)
-{
-    register int r, c;
-
-    for (r = 0; r < flags->nrows; r++) {
-	for (c = 0; c < flags->leng; c++) {
-	    flags->array[r][c] = 0;
-	}
-    }
-
-    return 0;
-}
-
-FLAG *flag_create(int nrows, int ncols)
-{
-    unsigned char *temp;
-    FLAG *new_flag;
-    register int i;
-
-    new_flag = (FLAG *) G_malloc(sizeof(FLAG));
-    new_flag->nrows = nrows;
-    new_flag->ncols = ncols;
-    new_flag->leng = (ncols + 7) / 8;
-    new_flag->array =
-	(unsigned char **)G_malloc(nrows * sizeof(unsigned char *));
-
-    temp =
-	(unsigned char *)G_malloc(nrows * new_flag->leng *
-				  sizeof(unsigned char));
-
-    for (i = 0; i < nrows; i++) {
-	new_flag->array[i] = temp;
-	temp += new_flag->leng;
-    }
-
-    return (new_flag);
-}
-
-int flag_destroy(FLAG * flags)
-{
-    G_free(flags->array[0]);
-    G_free(flags->array);
-    G_free(flags);
-
-    return 0;
-}

+ 0 - 65
imagery/i.segment/flag.h

@@ -1,65 +0,0 @@
-#ifndef __FLAG_H__
-#define __FLAG_H__
-
-
-/* flag.[ch] is a set of routines which will set up an array of bits
- ** that allow the programmer to "flag" cells in a raster map.
- **
- ** FLAG *
- ** flag_create(nrows,ncols)
- ** int nrows, ncols;
- **     opens the structure flag.  
- **     The flag structure will be a two dimensional array of bits the
- **     size of nrows by ncols.  Will initalize flags to zero (unset).
- **
- ** flag_destroy(flags)
- ** FLAG *flags;
- **     closes flags and gives the memory back to the system.
- **
- ** flag_clear_all(flags)
- ** FLAG *flags;
- **     sets all values in flags to zero.
- **
- * following 3 were changed to macros, same usage
- * 
- ** flag_unset(flags, row, col)
- ** FLAG *flags;
- ** int row, col;
- **     sets the value of (row, col) in flags to zero.
- **
- ** flag_set(flags, row, col)
- ** FLAG *flags;
- ** int row, col;
- **     will set the value of (row, col) in flags to one.
- **
- ** int
- ** flag_get(flags, row, col)
- ** FLAG *flags;
- ** int row, col;
- **     returns the value in flags that is at (row, col).
- **
- ** idea by Michael Shapiro
- ** code by Chuck Ehlschlaeger
- ** April 03, 1989
- */
-#define FLAG struct _flagsss_
-FLAG {
-    int nrows, ncols, leng;
-    unsigned char **array;
-};
-
-#define FLAG_UNSET(flags,row,col) \
-	(flags)->array[(row)][(col)>>3] &= ~(1<<((col) & 7))
-
-#define FLAG_SET(flags,row,col) \
-	(flags)->array[(row)][(col)>>3] |= (1<<((col) & 7))
-
-#define FLAG_GET(flags,row,col) \
-	(flags)->array[(row)][(col)>>3] & (1<<((col) & 7))
-
-/* flag.c */
-int flag_clear_all(FLAG *);
-FLAG *flag_create(int, int);
-int flag_destroy(FLAG *);
-
-#endif /* __FLAG_H__ */

+ 0 - 226
imagery/i.segment/i.segment.html

@@ -1,226 +0,0 @@
-<h2>DESCRIPTION</h2>
-Image segmentation is the process of grouping similar pixels into 
-unique segments. Boundary and region based algorithms are described 
-in the literature, currently a region growing and merging algorithm 
-is implemented.  Each grouping (usually refered to as objects or 
-segments) found during the segmentation process is given a unique ID 
-and is a collection of contiguous pixels meeting some criteria.  
-(Note the contrast with image classification, where continuity and 
-spatial characteristics are not important, but rather only the 
-spectral similarity.)  The results can be useful on their own, or 
-used as a preprocessing step for image classification.  The 
-segmentation preprocessing step can reduce noise and speed up the 
-classification.
-
-<H2>NOTES</h2>
-
-<h3>Region Growing and Merging</h3>
-This segmentation algorithm sequentially examines all current 
-segments in the map.  The similarity between the current segment and 
-each of its neighbors is calculated according to the given distance 
-formula. Segments will be merged if they meet a number of criteria, 
-including: 1.  The pair is mutually most similar to each other (the 
-similarity distance will be smaller then all other neighbors), and 
-2. The similarity must be lower then the input threshold.  All 
-segments are checked once per pass.  The process is repeated until 
-no merges are made during a complete pass.
-
-<h3>Similarity and Threshold</h3>
-The similarity between segments and unmerged pixels is used to 
-determine which are merged.  The Euclidean version uses the 
-radiometric distance between the two segments and also the shape 
-characteristics. The Manhatten calculations currently only uses only 
-the radiometric distance between the two segments, but eventually 
-shape characteristics will be included as well.  NOTE: 
-Closer/smaller distances mean a lower value for the similarity 
-indicates a closer match, with a similarity score of zero for 
-identical pixels.
-<p>
-During normal processing, merges are only allowed when the 
-similarity between two segments is lower then the calculated 
-threshold value. During the final pass, however, if a minimum 
-segment size of 2 or larger is given with the <em>minsize</em> 
-parameter, segments with a smaller pixel count will be merged with 
-their most similar neighbor even if the similarity is greater then 
-the threshold.
-<p>
-Unless the <em>-w</em> flag for weighted data is used, the threshold 
-should be set by the user between 0 and 1.0. A threshold of 0 would 
-allow only identical valued pixels to be merged, while a threshold 
-of 1 would allow everything to be merged.
-<p>
-The threshold will be multiplied by the number of rasters included 
-in the image group.  This will allow the same threshold to achieve 
-similar segmentation results when the number of rasters in the image 
-group varies.
-<p>
-The -t flag will estimate the threshold, it is calculated at 3% of 
-the range of data in the imagery group.  Initial empirical tests 
-indicate threshold values of 1% to 5% are reasonable places to start.
-
-<h4>Calculation Formulas</h4>
-Both Euclidean and Manhattan distances use the normal definition, 
-considering each raster in the image group as a dimension.
-
-Furthermore, the Euclidean calculation also takes into account the 
-shape characteristics of the segments.  The normal distances are 
-multiplied by the input radiometric weight.  Next an additional 
-contribution is added: (1-radioweight) * {smoothness * smoothness 
-weight + compactness * (1-smoothness weight)}, where compactness = 
-the Perimeter Length / sqrt( Area ) and smoothness = Perimeter 
-Length / the Bounding Box.  The perimeter length is estimated as the 
-number of pixel sides the segment has.
-
-<h3>Seeds</h3>
-The seeds map can be used to provide either seed pixels (random or 
-selected points from which to start the segmentation process) or 
-seed segments (results of previous segmentations or 
-classifications).  The different approaches are automatically 
-detected by the program: any pixels that have identical seed values 
-and are contiguous will be lumped into a single segment ID.
-<p>
-It is expected that the <em>minsize</em> will be set to 1 if a seed 
-map is used, but the program will allow other values to be used.  If 
-both options are used, the final iteration that ignores the 
-threshold also will ignore the seed map and force merges for all 
-pixels (not just segments that have grown/merged from the seeds).
-
-<h3>Maximum number of starting segments</h3>
-For the region growing algorithm without starting seeds, each pixel 
-is sequentially numbered.  The current limit with CELL storage is 2 
-billion starting segment ID's.  If the initial map has a larger 
-number of non-null pixels, there are two workarounds:
-<p>
-1.  Use starting seed pixels.  (Maximum 2 billion pixels can be 
-labeled with positive integers.)
-<p>
-2.  Use starting seed segments.  (By initial classification or other 
-methods.)
-
-<h3>Boundary Constraints</h3>
-Boundary constraints limit the adjacency of pixels and segments.  
-Each unique value present in the <em>bounds</em> raster are 
-considered as a MASK.  Thus no segments in the final segmentated map 
-will cross a boundary, even if their spectral data is very similar.
-
-<h3>Minimum Segment Size</h3>
-To reduce the salt and pepper affect, a <em>minsize</em> greater 
-than 1 will add one additional pass to the processing.  During the 
-final pass, the threshold is ignored for any segments smaller then 
-the set size, thus forcing very small segments to merge with their 
-most similar neighbor.
-
-<h2>EXAMPLES</h2>
-This example uses the ortho photograph included in the NC Sample 
-Dataset.  Set up an imagery group:<br>
-<div class="code"><pre>
-i.group group=ortho_group input=ortho_2001_t792_1m@PERMANENT
-</pre></div>
-
-<p>Because the segmentation process is computationally expensive, 
-start with a small processing area to confirm if the segmentation 
-results meet your requirements.  Some manual adjustment of the 
-threshold may be required. <br>
-
-<div class="code"><pre>
-g.region rast=ortho_2001_t792_1m@PERMANENT n=220400 s=220200 e=639000 w=638800
-</pre></div>
-
-Try out a first threshold and check the results.<br>
-<div class="code"><pre>
-i.segment -w -l group=ortho_group output=ortho_segs threshold=4 \
-          method=region_growing 
-</pre></div>
-<p></p>
-From a visual inspection, it seems this results in oversegmentation.  
-Increasing the threshold: <br>
-<div class="code"><pre>
-i.segment -w -l --overwrite group=ortho_group output=ortho_segs \
-          threshold=10 method=region_growing
-</pre></div>
-<p></p>
-This looks better.  There is some noise in the image, lets next force 
-all segments smaller then 5 pixels to be merged into their most similar 
-neighbor (even if they are less similar then required by our 
-threshold):<br>
-<div class="code"><pre>
-i.segment -w -l --overwrite group=ortho_group output=ortho_segs \
-          threshold=10 method=region_growing minsize=5
-</pre></div>
-<p></p>
-Each of these segmentation steps took less then 1 minute on a decent 
-machine.  Now that we are satisfied with the settings, we'll process 
-the entire image:
-<div class="code"><pre>
-g.region rast=ortho_2001_t792_1m@PERMANENT<br>
-i.segment -w -l --overwrite group=ortho_group output=ortho_segs \
-          threshold=10 method=region_growing minsize=5 endt=5000
-</pre></div>
-<p>
-Processing the entire ortho image (over 9 million pixels) took about 
-a day.
-
-<h2>TODO</h2>
-<h3>Functionality</h3>
-<ul>
-<li>Further testing of the shape characteristics (smoothness, 
-compactness), if it looks good it should be added to the Manhatten 
-option.
-<b>in progress</b></li>
-<li>Malahanobis distance for the similarity calculation.</li>
-</ul>
-<h3>Use of Segmentation Results</h3>
-<ul>
-<li>Improve the optional output from this module, or better yet, add a 
-module for <em>i.segment.metrics</em>.</li>
-<li>Providing updates to i.maxlik to ensure the segmentation output can 
-be used as input for the existing classification functionality.</li>
-<li>Integration/workflow for <em>r.fuzzy</em>.</li>
-</ul>
-<h3>Speed</h3>
-<ul>
-<li>See create_isegs.c</li>
-</ul>
-<h3>Memory</h3>
-<ul>
-<li>User input for how much RAM can be used.</li>
-<li>Check input map type(s), currently storing in DCELL sized SEG file, 
-could reduce this dynamically depending on input map time. (Could only 
-reduce to FCELL, since will be storing mean we can't use CELL. Might 
-not be worth the added code complexity.)</li>
-</ul>
-<h2>BUGS</h2>
-If the seeds map is used to give starting seed segments, the segments 
-are renumbered starting from 1.  There is a chance a segment could be 
-renumbered to a seed value that has not yet been processed.  If they 
-happen to be adjacent, they would be merged.  (Possible fixes: a.  use 
-a processing flag to make sure the pixels hasn't been previously used, 
-or b. use negative segment ID's as a placeholder and negate all values 
-after the seed map has been processed.)
-<H2>REFERENCES</h2>
-This project was first developed during GSoC 2012.  Project 
-documentation, Image Segmentation references, and other information 
-is at the <a href=
-"http://grass.osgeo.org/wiki/GRASS_GSoC_2012_Image_Segmentation">
-project wiki</a>.
-<p>
-Information about <a href=
-"http://grass.osgeo.org/wiki/Image_classification">classification in 
-GRASS GIS</a> is also available on the wiki.
-
-<h2>SEE ALSO</h2>
-<em>
-<a href="i.group.html">i.group</a>, 
-<a href="i.maxlik.html">i.maxlik</a>, 
-<a href="r.fuzzy">r.fuzzy</a>, 
-<a href="i.smap.html">i.smap</a>, 
-<a href="r.seg.html">r.seg</a> (Addon)
-</em>
-
-<h2>AUTHORS</h2>
-Eric Momsen - North Dakota State University
-<p>
-GSoC mentor: Markus Metz
-
-<p>
-<i>Last changed: $Date$

+ 0 - 149
imagery/i.segment/iseg.h

@@ -1,149 +0,0 @@
-
-/****************************************************************************
- *
- * MODULE:       i.segment
- * AUTHOR(S):    Eric Momsen <eric.momsen at gmail com>
- * PURPOSE:      structure definition and function listing
- * 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.
- *
- *****************************************************************************/
-
-#include <grass/segment.h>
-#include <grass/linkm.h>
-#include "flag.h"
-
-/* PROFILE will add some rough time checks for finding neighbors, merging, and pass times. */
-/* #define PROFILE */
-
-/* SIGNPOST will add some fprintf statments to indicate what segments are being merged.
- * other diagnostics could be included here for during further development and speed improvements.
- */
-/* #define SIGNPOST */
-
-/* pixel stack */
-struct pixels
-{
-    struct pixels *next;
-    int row;
-    int col;
-    int count_shared;		/* todo perimeter: will hold the count how 
-				 * many pixels are shared on the Border Between 
-				 * Ri and Rk.  Not used for all pixels... see if 
-				 * this is an OK way to do this... */
-};
-
-/* input and output files, as well as some other processing info */
-struct files
-{
-    /* user parameters */
-    char *image_group;
-    int weighted;		/* 0 if false/not selected, so we should scale input.  1 if the scaling should be skipped */
-
-    /* region info */
-    int nrows, ncols;
-
-    /* files */
-    char *out_name;		/* name of output raster map */
-    const char *seeds_map, *seeds_mapset, *bounds_map, *bounds_mapset;	/* optional segment seeds and polygon constraints/boundaries */
-    char *out_band;		/* for segment average values */
-
-    /* file processing */
-    /* bands_seg is initialized with the input raster valuess, then is updated with current mean values for the segment. */
-    /* for now, also storing: Area, Perimeter, maxcol, mincol, maxrow, minrow */
-    int nbands;			/* number of rasters in the image group */
-    SEGMENT bands_seg, bounds_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 */
-    double *second_val;		/* to hold values at second point for similarity comparison */
-    int bounds_val, current_bound;
-    int minrow, maxrow, mincol, maxcol;
-
-    /* results */
-    SEGMENT iseg_seg;		/* segment ID assignment */
-    int nsegs;			/* number of segments */
-
-    /* processing flags */
-    /* candidate flag for if a cell/segment has already been merged in that pass. */
-    /* seeds flag for if a cell/segment is a seed (can be Ri to start a merge).
-     *   All cells are valid seeds if a starting seeds map is not supplied. */
-    FLAG *candidate_flag, *null_flag, *orig_null_flag, *seeds_flag;
-
-    /* memory management, linked lists */
-    struct link_head *token;	/* for linkm.h linked list memory management. */
-
-};
-
-struct functions
-{
-    int method;			/* Segmentation method */
-    int num_pn;			/* number of pixel neighbors  int, 4 or 8. */
-    float threshold;		/* similarity threshold */
-    int min_segment_size;	/* smallest number of pixels/cells allowed in a final segment */
-    float radio_weight, smooth_weight;	/* radiometric (bands) vs. shape and smoothness vs. compactness */
-    /* Some function pointers to set in parse_args() */
-    int (*find_pixel_neighbors) (int, int, int[8][2], struct files *);	/*parameters: row, col, pixel_neighbors */
-    double (*calculate_similarity) (struct pixels *, struct pixels *, struct files *, struct functions *);	/*parameters: two pixels (each with row,col) to compare */
-
-    /* max number of iterations/passes */
-    int end_t;
-
-    int path;			/* flag if we are using Rk as next Ri for non-mutually best neighbor. */
-    int limited;		/* flag if we are limiting merges to one per pass */
-    int estimate_threshold;	/* flag if we just want to estimate a suggested threshold value and exit. */
-    int final_merge_only;	/* flag if we want to just run the final merge portion of the algorithm. */
-
-    /* todo: is there a fast way (and valid from an algorithm 
-       standpoint) to merge all neighbors that are within some small % 
-       of the treshold? * There is some code using "very_close" that is 
-       excluded with IFDEF * The goal is to speed processing, since in 
-       the end many of these very similar neighbors will be merged. * 
-       But the problem is that the find_segment_neighbors() function 
-       only returns a single pixel, not the entire segment membership. 
-       * The commented out code actually slowed down processing times 
-       in the first tries. */
-#ifdef VCLOSE
-    double very_close;		/* segments with very_close similarity 
-				 * will be merged without changing or checking the candidate flag. 
-				 * The algorithm will continue looking for the "most similar" 
-				 * neighbor that isn't "very close". */
-#endif
-};
-
-/* main.c */
-int estimate_threshold(char *);
-int check_group(char *);
-int read_range(double *, double *, char *);
-double calc_t(double, double);
-
-/* parse_args.c */
-/* 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 *, struct functions *);
-
-/* create_isegs.c */
-int create_isegs(struct files *, struct functions *);
-int region_growing(struct files *, struct functions *);
-int find_segment_neighbors(struct pixels **, struct pixels **, int *,
-			   struct files *, struct functions *);
-int set_candidate_flag(struct pixels *, int, struct files *);
-int merge_values(struct pixels *, struct pixels *, int, int, struct files *);
-int merge_pixels(struct pixels *, int, struct files *);
-int find_four_pixel_neighbors(int, int, int[][2], struct files *);
-int find_eight_pixel_neighbors(int, int, int[8][2], struct files *);
-double calculate_euclidean_similarity(struct pixels *, struct pixels *,
-				      struct files *, struct functions *);
-double calculate_manhattan_similarity(struct pixels *, struct pixels *,
-				      struct files *, struct functions *);
-int my_dispose_list(struct link_head *, struct pixels **);
-int compare_ids(const void *, const void *);
-int compare_pixels(const void *, const void *);
-int set_all_candidate_flags(struct files *);
-
-/* write_output.c */
-int write_output(struct files *);
-int close_files(struct files *);

+ 0 - 70
imagery/i.segment/main.c

@@ -1,70 +0,0 @@
-
-/****************************************************************************
- *
- * MODULE:       i.segment
- * AUTHOR(S):    Eric Momsen <eric.momsen at gmail com>
- * PURPOSE:      Segments an image group.
- * 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.
- * 
- *
- *               NOTE: the names "segment" and "SEG" are already used by the Segmentation
- *               Library for the data files/tiling, so "iseg" (image segmentation)
- *               will be used to refer to the image segmentation.
- * 
- * 				 First developed for GSoC 2012 with mentor: Markus Metz
- * 
- *****************************************************************************/
-
-#include <stdlib.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/imagery.h>
-#include "iseg.h"
-
-int main(int argc, char *argv[])
-{
-    struct files files;		/* input and output file descriptors, data structure, buffers */
-    struct functions functions;	/* function pointers and parameters for the calculations */
-    struct GModule *module;
-
-    G_gisinit(argv[0]);
-
-    module = G_define_module();
-    G_add_keyword(_("imagery"));
-    G_add_keyword(_("segmentation"));
-    module->description =
-	_("Outputs a single segmented map (raster) based on input values in an image group.");
-
-    if (parse_args(argc, argv, &files, &functions) != TRUE)
-	G_fatal_error(_("Error in parse_args()"));
-
-    /* check if we are doing normal processing or if the estimate threshold and exit flag has been selected */
-
-    if (functions.estimate_threshold == FALSE) {
-
-	G_debug(1, "Main: starting open_files()");
-	if (open_files(&files, &functions) != TRUE)
-	    G_fatal_error(_("Error in open_files()"));
-
-	G_debug(1, "Main: starting create_isegs()");
-	if (create_isegs(&files, &functions) != TRUE)
-	    G_fatal_error(_("Error in create_isegs()"));
-
-	G_debug(1, "Main: starting write_output()");
-	if (write_output(&files) != TRUE)
-	    G_fatal_error(_("Error in write_output()"));
-
-	G_debug(1, "Main: starting close_files()");
-	close_files(&files);
-
-	G_done_msg(_("Number of segments created: <%d>"), files.nsegs);
-    }
-    else {
-	estimate_threshold(files.image_group);
-    }
-    exit(EXIT_SUCCESS);
-}

+ 0 - 368
imagery/i.segment/open_files.c

@@ -1,368 +0,0 @@
-/* PURPOSE:      opening input rasters and creating segmentation files */
-
-#include <limits.h>		/* for INT_MAX */
-#include <stdlib.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/imagery.h>
-#include <grass/segment.h>	/* segmentation library */
-#include "iseg.h"
-
-int open_files(struct files *files, struct functions *functions)
-{
-    struct Ref Ref;		/* group reference list */
-    int *in_fd, seeds_fd, bounds_fd, null_check, out_fd, mean_fd;
-    int n, s, row, col, srows, scols, inlen, nseg, borderPixels;
-    DCELL **inbuf;		/* buffer array, to store lines from each of the imagery group rasters */
-    CELL *boundsbuf, *seedsbuf;
-    void *ptr;			/* for iterating seedsbuf */
-    size_t ptrsize;
-    struct FPRange *fp_range;	/* for getting min/max values on each input raster */
-    DCELL *min, *max;
-    struct Range range;		/* for seeds range */
-    int seeds_min, seeds_max;
-
-
-    /* for merging seed values */
-    struct pixels *R_head, *Rn_head, *newpixel, *current;
-    int R_count;
-
-    G_verbose_message(_("Opening files and initializing"));
-
-    /* confirm output maps can be opened (don't want to do all this work for nothing!) */
-    out_fd = Rast_open_new(files->out_name, CELL_TYPE);
-    if (out_fd < 0)
-	G_fatal_error(_("Could not open output raster for writing segment ID's"));
-    else
-	Rast_unopen(out_fd);
-
-    if (files->out_band != NULL) {
-	mean_fd = Rast_open_new(files->out_band, DCELL_TYPE);
-	if (mean_fd < 0)
-	    G_fatal_error(_("Could not open output raster for writing mean segment values"));
-	else
-	    Rast_unopen(mean_fd);
-    }
-
-    /*allocate memory for flags */
-    files->null_flag = flag_create(files->nrows, files->ncols);
-    flag_clear_all(files->null_flag);
-    files->candidate_flag = flag_create(files->nrows, files->ncols);
-
-    if (files->bounds_map != NULL)
-	files->orig_null_flag = flag_create(files->nrows, files->ncols);
-
-    files->seeds_flag = flag_create(files->nrows, files->ncols);
-    flag_clear_all(files->seeds_flag);
-
-    /* references for segmentation library: i.cost r.watershed/seg and http://grass.osgeo.org/programming7/segmentlib.html */
-
-    /* ****** open the input rasters ******* */
-
-    /* Note: I confirmed, the API does not check this: */
-    if (!I_get_group_ref(files->image_group, &Ref))
-	G_fatal_error(_("Unable to read REF file for group <%s>"),
-		      files->image_group);
-
-    if (Ref.nfiles <= 0)
-	G_fatal_error(_("Group <%s> contains no raster maps"),
-		      files->image_group);
-
-    /* Read Imagery Group */
-
-    in_fd = G_malloc(Ref.nfiles * sizeof(int));
-    inbuf = (DCELL **) G_malloc(Ref.nfiles * sizeof(DCELL *));
-    fp_range = G_malloc(Ref.nfiles * sizeof(struct FPRange));
-    min = G_malloc(Ref.nfiles * sizeof(DCELL));
-    max = G_malloc(Ref.nfiles * sizeof(DCELL));
-
-    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);
-	if (in_fd[n] < 0)
-	    G_fatal_error(_("Error opening %s@%s"), Ref.file[n].name,
-			  Ref.file[n].mapset);
-    }
-
-    /* open seeds raster and confirm all positive integers were given */
-    if (files->seeds_map != NULL) {
-	seeds_fd = Rast_open_old(files->seeds_map, "");
-	seedsbuf = Rast_allocate_c_buf();
-	ptrsize = sizeof(CELL);
-
-	if (Rast_read_range(files->seeds_map, files->seeds_mapset, &range) != 1) {	/* returns -1 on error, 2 on empty range, quiting either way. */
-	    G_fatal_error(_("No min/max found in seeds raster map <%s>"),
-			  files->seeds_map);
-	}
-	Rast_get_range_min_max(&range, &seeds_min, &seeds_max);
-	if (seeds_min < 0)
-	    G_fatal_error(_("Seeds raster should have postive integers for starting seeds, and zero or NULL for all other pixels."));
-    }
-
-    /* Get min/max values of each input raster for scaling */
-
-    if (files->weighted == FALSE) {	/*default, we will scale */
-	for (n = 0; n < Ref.nfiles; n++) {
-	    if (Rast_read_fp_range(Ref.file[n].name, Ref.file[n].mapset, &fp_range[n]) != 1)	/* returns -1 on error, 2 on empty range, quiting either way. */
-		G_fatal_error(_("No min/max found in raster map <%s>"),
-			      Ref.file[n].name);
-	    Rast_get_fp_range_min_max(&(fp_range[n]), &min[n], &max[n]);
-	}
-    }
-
-    /* ********** find out file segmentation size ************ */
-
-    files->nbands = Ref.nfiles;
-
-    /* size of each element to be stored */
-
-    /* save for bands, plus area, perimeter, bounding box. */
-
-    inlen = sizeof(double) * (Ref.nfiles + 6);
-
-    /* when fine tuning, should be a power of 2 and not larger than 256 for speed reasons */
-    srows = 64;
-    scols = 64;
-
-    /* RAM enhancement: have user input limit and make calculations for this, reference i.cost and i.watershed 
-     * One segment tile is tile_mb = (nbands * sizeof(double) + sizeof(CELL) * srows * scols / (1024*1024) 
-     * (check if sizeof(CELL) was from when iseg would be included, or the extra overhead?)
-     * If user inputs total RAM available, need to subtract the size of the flags, and the size of the linked lists.
-     * I'm not sure how to estimate the size of the linked lists, it is allowed to grow when needed.  Assume one segment
-     * could be 50% of the map?  Or more?  So ll_mb = sizeof(pixels) * nrows * ncols * 0.5 / (1024*1024)
-     * then split the remaining RAM between bands_seg and iseg_seg. */
-
-    nseg = 16;
-
-
-    /* ******* create temporary segmentation files ********* */
-    /* Initalize access to database and create temporary files */
-
-    G_debug(1, "Image size:  %d rows, %d cols", files->nrows, files->ncols);
-    G_debug(1, "Segmented to tiles with size:  %d rows, %d cols", srows,
-	    scols);
-    G_debug(1, "Data element size, in: %d", inlen);
-    G_debug(1, "number of segments to have in memory: %d", nseg);
-
-    if (segment_open
-	(&files->bands_seg, G_tempfile(), files->nrows, files->ncols, srows,
-	 scols, inlen, nseg) != TRUE)
-	G_fatal_error("Unable to create input temporary files");
-
-    /* ******* remaining memory allocation ********* */
-
-    /* save the area and perimeter as well */
-    /* perimeter todo: currently saving this with the input DCELL values.  
-     * Better to have a second segment structure to save as integers ??? */
-    /* along with P and A, also saving the bounding box - min/max row/col */
-
-    /* Why was this being reset here??? commented out... 
-       inlen = inlen + sizeof(double) * 6; */
-
-    files->bands_val = (double *)G_malloc(inlen);
-    files->second_val = (double *)G_malloc(inlen);
-
-    if (segment_open
-	(&files->iseg_seg, G_tempfile(), files->nrows, files->ncols, srows,
-	 scols, sizeof(int), nseg) != TRUE)
-	G_fatal_error(_("Unable to allocate memory for initial segment ID's"));
-
-    /* bounds/constraints (start with processing constraints to get any possible NULL values) */
-    if (files->bounds_map != NULL) {
-	if (segment_open
-	    (&files->bounds_seg, G_tempfile(), files->nrows, files->ncols,
-	     srows, scols, sizeof(int), nseg) != TRUE)
-	    G_fatal_error(_("Unable to create bounds temporary files"));
-
-	boundsbuf = Rast_allocate_c_buf();
-	bounds_fd = Rast_open_old(files->bounds_map, files->bounds_mapset);
-
-	for (row = 0; row < files->nrows; row++) {
-	    Rast_get_c_row(bounds_fd, boundsbuf, row);
-	    for (col = 0; col < files->ncols; col++) {
-		files->bounds_val = boundsbuf[col];
-		segment_put(&files->bounds_seg, &files->bounds_val, row, col);
-		if (Rast_is_c_null_value(&boundsbuf[col]) == TRUE) {
-		    FLAG_SET(files->null_flag, row, col);
-		}
-	    }
-	}
-	Rast_close(bounds_fd);
-	G_free(boundsbuf);
-    }				/* end bounds/constraints opening */
-
-
-    /* ********  load input bands to segment structure and fill initial seg ID's ******** */
-    s = 0;			/* initial segment ID will be 1 */
-
-    for (row = 0; row < files->nrows; row++) {
-
-	/* read in rows of data (each input band from the imagery group and the optional seeds map) */
-	for (n = 0; n < Ref.nfiles; n++) {
-	    Rast_get_d_row(in_fd[n], inbuf[n], row);
-	}
-	if (files->seeds_map != NULL) {
-	    Rast_get_c_row(seeds_fd, seedsbuf, row);
-	    ptr = seedsbuf;
-	}
-
-	for (col = 0; col < files->ncols; col++) {
-	    if (FLAG_GET(files->null_flag, row, col))
-		continue;
-	    null_check = 1;	/*Assume there is data */
-	    for (n = 0; n < Ref.nfiles; n++) {
-		if (Rast_is_d_null_value(&inbuf[n][col]))
-		    null_check = -1;
-		if (files->weighted == TRUE)
-		    files->bands_val[n] = inbuf[n][col];	/*unscaled */
-		else
-		    files->bands_val[n] = (inbuf[n][col] - min[n]) / (max[n] - min[n]);	/* scaled */
-	    }
-
-	    /* besides the user input rasters, also save the shape parameters */
-
-	    files->bands_val[Ref.nfiles] = 1;	/* area (just using the number of pixels) */
-	    files->bands_val[Ref.nfiles + 1] = 4;	/* Perimeter Length *//* todo perimeter, not exact for edges...close enough for now? */
-	    files->bands_val[Ref.nfiles + 2] = col;	/*max col */
-	    files->bands_val[Ref.nfiles + 3] = col;	/*min col */
-	    files->bands_val[Ref.nfiles + 4] = row;	/*max row */
-	    files->bands_val[Ref.nfiles + 5] = row;	/*min row */
-
-	    segment_put(&files->bands_seg, (void *)files->bands_val, row, col);	/* store input bands */
-	    if (null_check != -1) {	/*good pixel */
-		FLAG_UNSET(files->null_flag, row, col);	/*flag */
-		if (files->seeds_map != NULL) {
-		    if (Rast_is_c_null_value(ptr) == TRUE) {
-			/* when using iseg_seg the segmentation file is already initialized to zero.  Just initialize seeds_flag: */
-			FLAG_UNSET(files->seeds_flag, row, col);
-		    }
-		    else {
-			FLAG_SET(files->seeds_flag, row, col);	/* RAM enhancement, but it might cost speed.  Could look for seg ID > 0 instead of using seed_flag. */
-			/* seed value is starting segment ID. */
-			segment_put(&files->iseg_seg, ptr, row, col);
-		    }
-		    ptr = G_incr_void_ptr(ptr, ptrsize);
-		}
-		else {		/* no seeds provided */
-		    s++;	/* sequentially number all pixels with their own segment ID */
-		    if (s < INT_MAX) {	/* Check that the starting seeds aren't too large. */
-			segment_put(&files->iseg_seg, &s, row, col);	/*starting segment number */
-			FLAG_SET(files->seeds_flag, row, col);	/*all pixels are seeds */
-		    }
-		    else
-			G_fatal_error(_("Exceeded integer storage limit, too many initial pixels."));
-		}
-	    }
-	    else {		/*don't use this pixel */
-		FLAG_SET(files->null_flag, row, col);	/*flag */
-	    }
-	}
-    }
-
-    /* keep original copy of null flag if we have boundary constraints */
-    if (files->bounds_map != NULL) {
-	for (row = 0; row < files->nrows; row++) {
-	    for (col = 0; col < files->ncols; col++) {
-		if (FLAG_GET(files->null_flag, row, col))
-		    FLAG_SET(files->orig_null_flag, row, col);
-		else
-		    FLAG_UNSET(files->orig_null_flag, row, col);
-	    }
-	}
-    }				/* end: if (files->bounds_map != NULL) */
-
-    /* linked list memory management linkm */
-    link_set_chunk_size(1000);	/* TODO RAM: fine tune this number */
-
-    files->token = link_init(sizeof(struct pixels));
-
-    /* if we have seeds that are segments (not pixels) we need to update the bands_seg */
-    /* also renumber the segment ID's in case they were classified 
-     * (duplicating numbers) instead of output from i.segment. */
-    if (files->seeds_map != NULL) {
-
-	/*initialization */
-	files->minrow = files->mincol = 0;
-	files->maxrow = files->nrows;
-	files->maxcol = files->ncols;
-	R_count = 1;
-	R_head = NULL;
-	Rn_head = NULL;
-	newpixel = NULL;
-	current = NULL;
-	set_all_candidate_flags(files);
-	for (row = 0; row < files->nrows; row++) {
-	    G_percent(row, files->nrows, 1);	/* I think this is the longest part of open_files()
-						 * - not entirely accurate for the actual %,
-						 *  but will give the user something to see. */
-	    for (col = 0; col < files->ncols; col++) {
-		if (!(FLAG_GET(files->candidate_flag, row, col)) ||
-		    FLAG_GET(files->null_flag, row, col))
-		    continue;
-		/*start R_head */
-		newpixel = (struct pixels *)link_new(files->token);
-		newpixel->next = NULL;
-		newpixel->row = row;
-		newpixel->col = col;
-		R_head = newpixel;
-
-		/* get pixel list, possible initialization speed enhancement: 
-		 * could use a custom (shorter) function, some results from 
-		 * find_segment_neighbors are not used here */
-		/* bug todo: There is a small chance that a renumbered segment 
-		 * matches and borders an original segment.  This would be a 
-		 * good reason to write a custom function - use the candidate 
-		 * flag to see if the pixel was already processed. */
-		borderPixels =
-		    find_segment_neighbors(&R_head, &Rn_head, &R_count, files,
-					   functions);
-
-		/* update the segment ID */
-
-		s++;
-		if (s == INT_MAX)	/* Check that the starting seeds aren't too large. */
-		    G_fatal_error(_("Exceeded integer storage limit, too many initial pixels."));
-
-		for (current = R_head; current != NULL;
-		     current = current->next) {
-		    segment_put(&files->iseg_seg, &s, current->row,
-				current->col);
-		    FLAG_UNSET(files->candidate_flag, current->row,
-			       current->col);
-		}
-
-		/*merge pixels (updates the bands_seg) */
-		merge_pixels(R_head, borderPixels, files);
-
-		/*todo calculate perimeter (?and area?) here? */
-
-		/*clean up */
-		my_dispose_list(files->token, &R_head);
-		my_dispose_list(files->token, &Rn_head);
-		R_count = 1;
-	    }
-	}
-    }
-
-    files->nsegs = s;
-
-    /* Free memory */
-
-    for (n = 0; n < Ref.nfiles; n++) {
-	G_free(inbuf[n]);
-	Rast_close(in_fd[n]);
-    }
-
-    if (files->seeds_map != NULL) {
-	Rast_close(seeds_fd);
-	G_free(seedsbuf);
-    }
-
-    G_free(inbuf);
-    G_free(in_fd);
-    G_free(fp_range);
-    G_free(min);
-    G_free(max);
-
-    return TRUE;
-}

+ 0 - 293
imagery/i.segment/parse_args.c

@@ -1,293 +0,0 @@
-/* PURPOSE:      Parse and validate the input */
-
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/raster.h>
-#include "iseg.h"
-
-int parse_args(int argc, char *argv[], struct files *files,
-	       struct functions *functions)
-{
-    struct Option *group, *seeds, *bounds, *output, *method, *similarity, *threshold, *min_segment_size, *endt;	/* Establish an Option pointer for each option */
-    struct Option *radio_weight, *smooth_weight;
-    struct Flag *estimate_threshold, *diagonal, *weighted, *limited, *final;	/* Establish a Flag pointer for each option */
-    struct Option *outband;	/* optional saving of segment data, until a seperate module is written */
-
-#ifdef VCLOSE
-    struct Option *very_close;
-#endif
-
-    /* required parameters */
-    /* enhancement: consider giving the option to process just one
-     * raster directly, without creating an image group. */
-    group = G_define_standard_option(G_OPT_I_GROUP);
-
-    output = G_define_standard_option(G_OPT_R_OUTPUT);
-
-    threshold = G_define_option();
-    threshold->key = "threshold";
-    threshold->type = TYPE_DOUBLE;
-    threshold->required = YES;
-    threshold->description = _("Similarity threshold.");
-
-    method = G_define_option();
-    method->key = "method";
-    method->type = TYPE_STRING;
-    method->required = YES;
-    method->answer = "region_growing";
-    method->options = "region_growing";
-    method->description = _("Segmentation method.");
-
-    similarity = G_define_option();
-    similarity->key = "similarity";
-    similarity->type = TYPE_STRING;
-    similarity->required = YES;
-    similarity->answer = "euclidean";
-    similarity->options = "euclidean, manhattan";
-    similarity->description = _("Similarity calculation method.");
-
-    min_segment_size = G_define_option();
-    min_segment_size->key = "minsize";
-    min_segment_size->type = TYPE_INTEGER;
-    min_segment_size->required = YES;
-    min_segment_size->answer = "1";	/* default: no merges, a minimum of 1 pixel is allowed in a segment. */
-    min_segment_size->options = "1-100000";
-    min_segment_size->label = _("Minimum number of cells in a segment.");
-    min_segment_size->description =
-	_("The final iteration will ignore the threshold for any segments with fewer pixels.");
-
-#ifdef VCLOSE
-    very_close = G_define_option();
-    very_close->key = "very_close";
-    very_close->type = TYPE_DOUBLE;
-    very_close->required = YES;
-    very_close->answer = "0";
-    very_close->options = "0-1";
-    very_close->label = _("Fraction of the threshold.");
-    very_close->description =
-	_("Neighbors similarity lower then this fraction of the threshold will be merged without regard to any other processing rules.");
-#endif
-
-    /* for the weights of bands values vs. shape parameters, and weight of smoothness vs. compactness */
-
-    radio_weight = G_define_option();
-    radio_weight->key = "radioweight";
-    radio_weight->type = TYPE_DOUBLE;
-    radio_weight->required = YES;
-    radio_weight->answer = "0.9";
-    radio_weight->options = "0-1";
-    radio_weight->label =
-	_("Importance of radiometric (input raseters) values relative to shape");
-
-    smooth_weight = G_define_option();
-    smooth_weight->key = "smoothweight";
-    smooth_weight->type = TYPE_DOUBLE;
-    smooth_weight->required = YES;
-    smooth_weight->answer = "0.5";
-    smooth_weight->options = "0-1";
-    smooth_weight->label =
-	_("Importance of smoothness relative to compactness");
-
-    /* optional parameters */
-
-    estimate_threshold = G_define_flag();
-    estimate_threshold->key = 't';
-    estimate_threshold->description =
-	_("Estimate a threshold based on input image group and exit.");
-
-    diagonal = G_define_flag();
-    diagonal->key = 'd';
-    diagonal->description =
-	_("Use 8 neighbors (3x3 neighborhood) instead of the default 4 neighbors for each pixel.");
-
-    weighted = G_define_flag();
-    weighted->key = 'w';
-    weighted->description =
-	_("Weighted input, don't perform the default scaling of input maps.");
-
-    final = G_define_flag();
-    final->key = 'f';
-    final->description =
-	_("Final forced merge only (skip the growing portion of the algorithm.");
-
-    /* Raster for initial segment seeds */
-    /* future enhancement: allow vector points/centroids for seed input. */
-    seeds = G_define_standard_option(G_OPT_R_INPUT);
-    seeds->key = "seeds";
-    seeds->required = NO;
-    seeds->label = _("Optional raster map with starting seeds.");
-    seeds->description =
-	_("Pixel values with positive integers are used as starting seeds.");
-
-    /* Polygon constraints. */
-    bounds = G_define_standard_option(G_OPT_R_INPUT);
-    bounds->key = "bounds";
-    bounds->required = NO;
-    bounds->label = _("Optional bounding/constraining raster map");
-    bounds->description =
-	_("Pixels with the same integer value will be segmented independent of the others.");
-
-    /* other parameters */
-    endt = G_define_option();
-    endt->key = "endt";
-    endt->type = TYPE_INTEGER;
-    endt->required = NO;
-    endt->answer = "1000";
-    endt->description =
-	_("Maximum number of passes (time steps) to complete.");
-
-    /* Leaving path flag out of user options, will hardcode TRUE for 
-       this option.  This does change the resulting segments, but I 
-       don't see any reason why one version is more valid.  It 
-       reduced the processing time by 50% when segmenting the ortho 
-       image. Code in the segmenation algorithm remains, in case more 
-       validation of this option should be done. */
-    /*
-       path = G_define_flag();
-       path->key = 'p';
-       path->description =
-       _("temporary option, pathflag, select to use Rk as next Ri if not mutually best neighbors.");
-     */
-    limited = G_define_flag();
-    limited->key = 'l';
-    limited->description =
-	_("segments are limited to be included in only one merge per pass");
-
-    outband = G_define_standard_option(G_OPT_R_OUTPUT);
-    outband->key = "final_mean";
-    outband->required = NO;
-    outband->description =
-	_("Save the final mean values for the first band in the imagery group.");
-    /* enhancement: save mean values for all bands.  Multiple rasters or switch to polygons? */
-
-
-    if (G_parser(argc, argv))
-	exit(EXIT_FAILURE);
-
-    /* Validation */
-
-    /* Check and save parameters */
-
-    files->image_group = group->answer;
-
-    functions->estimate_threshold = estimate_threshold->answer;
-
-    /* if we are just estimating a threshold, skip remaining input validation */
-    if (functions->estimate_threshold == TRUE)
-	return TRUE;
-
-    if (G_legal_filename(output->answer) == TRUE)
-	files->out_name = output->answer;	/* name of output (segment ID) raster map */
-    else
-	G_fatal_error(_("Invalid output raster name."));
-
-    functions->threshold = atof(threshold->answer);	/* Note: this threshold is scaled after we know more at the beginning of create_isegs() */
-
-    if (weighted->answer == FALSE &&
-	(functions->threshold <= 0 || functions->threshold >= 1))
-	G_fatal_error(_("threshold should be >= 0 and <= 1"));
-
-    /* segmentation methods: 1 = region growing */
-    if (strncmp(method->answer, "region_growing", 10) == 0)
-	functions->method = 1;
-    else
-	G_fatal_error(_("Couldn't assign segmentation method."));	/*shouldn't be able to get here */
-
-    /* distance methods for similarity measurement */
-    if (strncmp(similarity->answer, "euclidean", 5) == 0)
-	functions->calculate_similarity = &calculate_euclidean_similarity;
-    else if (strncmp(similarity->answer, "manhattan", 5) == 0)
-	functions->calculate_similarity = &calculate_manhattan_similarity;
-    else
-	G_fatal_error(_("Couldn't assign similarity method."));	/*shouldn't be able to get here */
-
-#ifdef VCLOSE
-    functions->very_close = atof(very_close->answer);
-#endif
-
-    functions->min_segment_size = atoi(min_segment_size->answer);
-
-    functions->radio_weight = atof(radio_weight->answer);
-    functions->smooth_weight = atof(smooth_weight->answer);
-
-    if (diagonal->answer == FALSE) {
-	functions->find_pixel_neighbors = &find_four_pixel_neighbors;
-	functions->num_pn = 4;
-    }
-    else if (diagonal->answer == TRUE) {
-	functions->find_pixel_neighbors = &find_eight_pixel_neighbors;
-	functions->num_pn = 8;
-    }
-    /* speed enhancement: Check if function pointer or IF statement is faster */
-
-    /* default/0 for performing the scaling, but selected/1 if 
-     * user has weighted values so scaling should be skipped. */
-    files->weighted = weighted->answer;
-
-	functions->final_merge_only = final->answer;
-
-    /* check if optional seeds map was given, if not, use all pixels as starting seeds. */
-    if (seeds->answer == NULL) {
-	files->seeds_map = NULL;
-    }
-    else {			/* seeds provided, check if valid map */
-	files->seeds_map = seeds->answer;
-	if ((files->seeds_mapset =
-	     G_find_raster2(files->seeds_map, "")) == NULL) {
-	    G_fatal_error(_("Starting seeds map not found."));
-	}
-	if (Rast_map_type(files->seeds_map, files->seeds_mapset) != CELL_TYPE) {
-	    G_fatal_error(_("Starting seeds map must be CELL type (integers)"));
-	}
-    }
-
-    /* check if optional processing boundaries were provided */
-    if (bounds->answer == NULL) {	/*no processing constraints */
-	files->bounds_map = NULL;
-    }
-    else {			/* processing constraints given, check if valid map */
-	files->bounds_map = bounds->answer;
-	if ((files->bounds_mapset =
-	     G_find_raster2(files->bounds_map, "")) == NULL) {
-	    G_fatal_error(_("Segmentation constraint/boundary map not found."));
-	}
-	if (Rast_map_type(files->bounds_map, files->bounds_mapset) !=
-	    CELL_TYPE) {
-	    G_fatal_error(_("Segmentation constraint map must be CELL type (integers)"));
-	}
-    }
-
-    /* other data */
-    files->nrows = Rast_window_rows();
-    files->ncols = Rast_window_cols();
-
-    if (endt->answer != NULL && atoi(endt->answer) >= 0)
-	functions->end_t = atoi(endt->answer);
-    else {
-	functions->end_t = 1000;
-	G_warning(_("invalid number of iterations, 1000 will be used."));
-    }
-
-    /* other parameters */
-
-    /* default/0 for no pathflag, but selected/1 to use 
-     * Rk as next Ri if not mutually best neighbors. */
-    /* functions->path = path->answer; */
-    functions->path = TRUE;
-    /* see notes above about pathflag. */
-
-    functions->limited = limited->answer;
-
-    if (outband->answer == NULL)
-	files->out_band = NULL;
-    else {
-	if (G_legal_filename(outband->answer) == TRUE)
-	    files->out_band = outband->answer;	/* name of current means */
-	else
-	    G_fatal_error(_("Invalid output raster name for means."));
-    }
-
-    return TRUE;
-}

+ 0 - 94
imagery/i.segment/write_output.c

@@ -1,94 +0,0 @@
-/* write_output(): transfer the segmented regions from the segmented data file to a raster file */
-/* close_files(): close SEG files and free memory */
-
-#include <stdlib.h>
-#include <grass/gis.h>
-#include <grass/raster.h>
-#include <grass/segment.h>	/* segmentation library */
-#include "iseg.h"
-
-int write_output(struct files *files)
-{
-    int out_fd, mean_fd, row, col;	/* mean_fd for validiating/debug of means */
-    CELL *outbuf;
-    DCELL *meanbuf;
-    struct Colors colors;
-    struct History history;
-
-
-    outbuf = Rast_allocate_c_buf();	/* hold one row of data to put into raster */
-    meanbuf = Rast_allocate_d_buf();
-
-    /* force all data to disk */
-    segment_flush(&files->bands_seg);
-    segment_flush(&files->iseg_seg);
-
-    /* open output raster map */
-    out_fd = Rast_open_new(files->out_name, CELL_TYPE);
-    if (files->out_band != NULL)
-	mean_fd = Rast_open_new(files->out_band, DCELL_TYPE);
-
-    /* transfer data from segmentation file to raster */
-    for (row = 0; row < files->nrows; row++) {
-	Rast_set_c_null_value(outbuf, files->ncols);	/*set buffer to NULLs, only write those that weren't originally masked */
-	Rast_set_d_null_value(meanbuf, files->ncols);
-	for (col = 0; col < files->ncols; col++) {
-	    segment_get(&files->bands_seg, (void *)files->bands_val, row,
-			col);
-	    if (!(FLAG_GET(files->null_flag, row, col))) {
-		segment_get(&files->iseg_seg, &(outbuf[col]), row, col);
-		meanbuf[col] = files->bands_val[0];
-	    }
-	}
-	Rast_put_row(out_fd, outbuf, CELL_TYPE);
-	if (files->out_band != NULL)
-	    Rast_put_row(mean_fd, meanbuf, DCELL_TYPE);
-
-	G_percent(row, files->nrows, 1);
-    }
-
-    /* close and save file */
-    Rast_close(out_fd);
-    if (files->out_band != NULL)
-	Rast_close(mean_fd);
-
-    /* set colors */
-    Rast_init_colors(&colors);
-    Rast_make_random_colors(&colors, 1, files->nrows * files->ncols);
-    Rast_write_colors(files->out_name, G_mapset(), &colors);
-
-    /* add command line to history */
-    /* see i.pca as an example of setting custom info */
-    Rast_short_history(files->out_name, "raster", &history);
-    Rast_command_history(&history);
-    Rast_write_history(files->out_name, &history);
-
-    /* free memory */
-    G_free(outbuf);
-    G_free(meanbuf);
-    Rast_free_colors(&colors);
-
-    return TRUE;
-}
-
-int close_files(struct files *files)
-{
-
-    /* close segmentation files and output raster */
-    segment_close(&files->bands_seg);
-    if (files->bounds_map != NULL)
-	segment_close(&files->bounds_seg);
-
-    G_free(files->bands_val);
-    G_free(files->second_val);
-
-    segment_close(&files->iseg_seg);
-
-    flag_destroy(files->null_flag);
-    flag_destroy(files->candidate_flag);
-    flag_destroy(files->seeds_flag);
-
-    link_cleanup(files->token);
-
-    return TRUE;
-}