GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-602118adcc
sigset.c
Go to the documentation of this file.
1 #include <string.h>
2 #include <stdlib.h>
3 #include <grass/gis.h>
4 #include <grass/glocale.h>
5 #include <grass/imagery.h>
6 
7 static int gettag(FILE *, char *);
8 static int get_semantic_labels(FILE *, struct SigSet *);
9 static int get_title(FILE *, struct SigSet *);
10 static int get_class(FILE *, struct SigSet *);
11 static int get_classnum(FILE *, struct ClassSig *);
12 static int get_classtype(FILE *, struct ClassSig *);
13 static int get_classtitle(FILE *, struct ClassSig *);
14 static int get_subclass(FILE *, struct SigSet *, struct ClassSig *);
15 static int get_subclass_pi(FILE *, struct SubSig *);
16 static int get_subclass_means(FILE *, struct SubSig *, int);
17 static int get_subclass_covar(FILE *, struct SubSig *, int);
18 
19 static double **alloc_matrix(int rows, int cols)
20 {
21  double **m;
22  int i;
23 
24  m = (double **)G_calloc(rows, sizeof(double *));
25  m[0] = (double *)G_calloc(rows * cols, sizeof(double));
26  for (i = 1; i < rows; i++)
27  m[i] = m[i - 1] + cols;
28 
29  return m;
30 }
31 
32 int I_SigSetNClasses(struct SigSet *S)
33 {
34  int i, count;
35 
36  for (i = 0, count = 0; i < S->nclasses; i++)
37  if (S->ClassSig[i].used)
38  count++;
39 
40  return count;
41 }
42 
43 struct ClassData *I_AllocClassData(struct SigSet *S, struct ClassSig *C,
44  int npixels)
45 {
46  struct ClassData *Data;
47 
48  Data = &(C->ClassData);
49  Data->npixels = npixels;
50  Data->count = 0;
51  Data->x = alloc_matrix(npixels, S->nbands);
52  Data->p = alloc_matrix(npixels, C->nsubclasses);
53  return Data;
54 }
55 
56 /*!
57  * \brief Initialize struct SigSet before use
58  *
59  * No need to call before calling I_ReadSigSet.
60  *
61  * \param *Signature to initialize
62  * \param nbands band (imagery group member) count
63  */
64 int I_InitSigSet(struct SigSet *S, int nbands)
65 {
66  S->nbands = nbands;
67  S->semantic_labels = (char **)G_malloc(nbands * sizeof(char **));
68  for (int i = 0; i < nbands; i++)
69  S->semantic_labels[i] = NULL;
70  S->nclasses = 0;
71  S->ClassSig = NULL;
72  S->title = NULL;
73 
74  return 0;
75 }
76 
77 struct ClassSig *I_NewClassSig(struct SigSet *S)
78 {
79  struct ClassSig *Sp;
80 
81  if (S->nclasses == 0)
82  S->ClassSig = (struct ClassSig *)G_malloc(sizeof(struct ClassSig));
83  else
84  S->ClassSig = (struct ClassSig *)G_realloc(
85  (char *)S->ClassSig, sizeof(struct ClassSig) * (S->nclasses + 1));
86 
87  Sp = &S->ClassSig[S->nclasses++];
88  Sp->classnum = 0;
89  Sp->nsubclasses = 0;
90  Sp->used = 1;
92  Sp->title = NULL;
93  return Sp;
94 }
95 
96 struct SubSig *I_NewSubSig(struct SigSet *S, struct ClassSig *C)
97 {
98  struct SubSig *Sp;
99  int i;
100 
101  if (C->nsubclasses == 0)
102  C->SubSig = (struct SubSig *)G_malloc(sizeof(struct SubSig));
103  else
104  C->SubSig = (struct SubSig *)G_realloc(
105  (char *)C->SubSig, sizeof(struct SubSig) * (C->nsubclasses + 1));
106 
107  Sp = &C->SubSig[C->nsubclasses++];
108  Sp->used = 1;
109  Sp->R = (double **)G_calloc(S->nbands, sizeof(double *));
110  Sp->R[0] = (double *)G_calloc(S->nbands * S->nbands, sizeof(double));
111  for (i = 1; i < S->nbands; i++)
112  Sp->R[i] = Sp->R[i - 1] + S->nbands;
113  Sp->Rinv = (double **)G_calloc(S->nbands, sizeof(double *));
114  Sp->Rinv[0] = (double *)G_calloc(S->nbands * S->nbands, sizeof(double));
115  for (i = 1; i < S->nbands; i++)
116  Sp->Rinv[i] = Sp->Rinv[i - 1] + S->nbands;
117  Sp->means = (double *)G_calloc(S->nbands, sizeof(double));
118  Sp->N = 0;
119  Sp->pi = 0;
120  Sp->cnst = 0;
121  return Sp;
122 }
123 
124 #define eq(a, b) strcmp(a, b) == 0
125 
126 /*!
127  * \brief Read sigset signatures from file
128  *
129  * File stream should be opened in advance by call to
130  * I_fopen_sigset_file_old()
131  * It is up to caller to fclose the file stream afterwards.
132  *
133  * There is no need to initialise struct SigSet in advance, as this
134  * function internally calls I_InitSigSet.
135  *
136  * \param pointer to FILE*
137  * \param pointer to struct SigSet *S
138  *
139  * \return 1 on success, -1 on failure
140  */
141 int I_ReadSigSet(FILE *fd, struct SigSet *S)
142 {
143  char tag[256];
144  unsigned int version;
145 
146  if (fscanf(fd, "%u", &version) != 1) {
147  G_warning(_("Invalid signature file"));
148  return -1;
149  }
150  if (version != 1) {
151  G_warning(_("Invalid signature file version"));
152  return -1;
153  }
154 
155  I_InitSigSet(S, 0);
156  while (gettag(fd, tag)) {
157  if (eq(tag, "title:"))
158  if (get_title(fd, S) != 0)
159  return -1;
160  if (eq(tag, "semantic_labels:"))
161  if (get_semantic_labels(fd, S) != 0)
162  return -1;
163  if (eq(tag, "class:"))
164  if (get_class(fd, S) != 0)
165  return -1;
166  }
167  return 1; /* for now assume success */
168 }
169 
170 static int gettag(FILE *fd, char *tag)
171 {
172  if (fscanf(fd, "%255s", tag) != 1)
173  return 0;
174  G_strip(tag);
175  return 1;
176 }
177 
178 static int get_semantic_labels(FILE *fd, struct SigSet *S)
179 {
180  int n, pos;
181  char c, prev;
182  char semantic_label[GNAME_MAX];
183 
184  /* Read semantic labels and count them to set nbands */
185  n = 0;
186  pos = 0;
187  S->semantic_labels =
188  (char **)G_realloc(S->semantic_labels, (n + 1) * sizeof(char **));
189  while ((c = (char)fgetc(fd)) != EOF) {
190  if (c == '\n') {
191  if (prev != ' ') {
192  semantic_label[pos] = '\0';
193  if (strlen(semantic_label) > 0) {
194  S->semantic_labels[n] = G_store(semantic_label);
195  n++;
196  }
197  }
198  S->nbands = n;
199  break;
200  }
201  if (c == ' ') {
202  semantic_label[pos] = '\0';
203  if (strlen(semantic_label) > 0) {
204  S->semantic_labels[n] = G_store(semantic_label);
205  n++;
206  /* [n] is 0 based thus: (n + 1) */
207  S->semantic_labels = (char **)G_realloc(
208  S->semantic_labels, (n + 1) * sizeof(char **));
209  }
210  pos = 0;
211  prev = c;
212  continue;
213  }
214  /* Semantic labels are limited to GNAME_MAX - 1 + \0 in length;
215  * n is 0-based */
216  if (pos == (GNAME_MAX - 2)) {
217  G_warning(_("Invalid signature file: semantic label length limit "
218  "exceeded"));
219  return -1;
220  }
221  semantic_label[pos] = c;
222  pos++;
223  prev = c;
224  }
225  if (!(S->nbands > 0)) {
226  G_warning(_("Signature file does not contain bands"));
227  return -1;
228  }
229 
230  return 0;
231 }
232 
233 static int get_title(FILE *fd, struct SigSet *S)
234 {
235  char title[1024];
236 
237  *title = 0;
238  if (fscanf(fd, "%1023[^\n]", title) != 1)
239  return -1;
240  G_strip(title);
241  I_SetSigTitle(S, title);
242 
243  return 0;
244 }
245 
246 static int get_class(FILE *fd, struct SigSet *S)
247 {
248  char tag[1024];
249  struct ClassSig *C;
250 
251  C = I_NewClassSig(S);
252  while (gettag(fd, tag)) {
253  if (eq(tag, "endclass:"))
254  break;
255  if (eq(tag, "classnum:"))
256  if (get_classnum(fd, C) != 0)
257  return -1;
258  if (eq(tag, "classtype:"))
259  if (get_classtype(fd, C) != 0)
260  return -1;
261  if (eq(tag, "classtitle:"))
262  if (get_classtitle(fd, C) != 0)
263  return -1;
264  if (eq(tag, "subclass:"))
265  if (get_subclass(fd, S, C) != 0)
266  return -1;
267  }
268 
269  return 0;
270 }
271 
272 static int get_classnum(FILE *fd, struct ClassSig *C)
273 {
274  if (fscanf(fd, "%ld", &C->classnum) != 1)
275  return -1;
276 
277  return 0;
278 }
279 
280 static int get_classtype(FILE *fd, struct ClassSig *C)
281 {
282  if (fscanf(fd, "%d", &C->type) != 1)
283  return -1;
284 
285  return 0;
286 }
287 
288 static int get_classtitle(FILE *fd, struct ClassSig *C)
289 {
290  char title[1024];
291 
292  *title = 0;
293  if (fscanf(fd, "%1023[^\n]", title) != 1)
294  return -1;
295  G_strip(title);
297 
298  return 0;
299 }
300 
301 static int get_subclass(FILE *fd, struct SigSet *S, struct ClassSig *C)
302 {
303  struct SubSig *Sp;
304  char tag[1024];
305 
306  Sp = I_NewSubSig(S, C);
307 
308  while (gettag(fd, tag)) {
309  if (eq(tag, "endsubclass:"))
310  break;
311  if (eq(tag, "pi:"))
312  if (get_subclass_pi(fd, Sp) != 0)
313  return -1;
314  if (eq(tag, "means:"))
315  if (get_subclass_means(fd, Sp, S->nbands) != 0)
316  return -1;
317  if (eq(tag, "covar:"))
318  if (get_subclass_covar(fd, Sp, S->nbands) != 0)
319  return -1;
320  }
321 
322  return 0;
323 }
324 
325 static int get_subclass_pi(FILE *fd, struct SubSig *Sp)
326 {
327  if (fscanf(fd, "%lf", &Sp->pi) != 1)
328  return -1;
329 
330  return 0;
331 }
332 
333 static int get_subclass_means(FILE *fd, struct SubSig *Sp, int nbands)
334 {
335  int i;
336 
337  for (i = 0; i < nbands; i++)
338  if (fscanf(fd, "%lf", &Sp->means[i]) != 1)
339  return -1;
340 
341  return 0;
342 }
343 
344 static int get_subclass_covar(FILE *fd, struct SubSig *Sp, int nbands)
345 {
346  int i, j;
347 
348  for (i = 0; i < nbands; i++)
349  for (j = 0; j < nbands; j++)
350  if (fscanf(fd, "%lf", &Sp->R[i][j]) != 1)
351  return -1;
352 
353  return 0;
354 }
355 
356 int I_SetSigTitle(struct SigSet *S, const char *title)
357 {
358  if (title == NULL)
359  title = "";
360  if (S->title)
361  free(S->title);
362  S->title = G_store(title);
363 
364  return 0;
365 }
366 
367 const char *I_GetSigTitle(const struct SigSet *S)
368 {
369  if (S->title)
370  return S->title;
371  else
372  return "";
373 }
374 
375 int I_SetClassTitle(struct ClassSig *C, const char *title)
376 {
377  if (title == NULL)
378  title = "";
379  if (C->title)
380  free(C->title);
381  C->title = G_store(title);
382 
383  return 0;
384 }
385 
386 const char *I_GetClassTitle(const struct ClassSig *C)
387 {
388  if (C->title)
389  return C->title;
390  else
391  return "";
392 }
393 
394 int I_WriteSigSet(FILE *fd, const struct SigSet *S)
395 {
396  const struct ClassSig *Cp;
397  const struct SubSig *Sp;
398  int i, j, b1, b2;
399 
400  /* This is version 1 sigset file format */
401  fprintf(fd, "1\n");
402  fprintf(fd, "title: %s\n", I_GetSigTitle(S));
403  fprintf(fd, "semantic_labels: ");
404  for (i = 0; i < S->nbands; i++) {
405  fprintf(fd, "%s ", S->semantic_labels[i]);
406  }
407  fprintf(fd, "\n");
408  for (i = 0; i < S->nclasses; i++) {
409  Cp = &S->ClassSig[i];
410  if (!Cp->used)
411  continue;
412  if (Cp->nsubclasses <= 0)
413  continue;
414  fprintf(fd, "class:\n");
415  fprintf(fd, " classnum: %ld\n", Cp->classnum);
416  fprintf(fd, " classtitle: %s\n", I_GetClassTitle(Cp));
417  fprintf(fd, " classtype: %d\n", Cp->type);
418 
419  for (j = 0; j < Cp->nsubclasses; j++) {
420  Sp = &Cp->SubSig[j];
421  fprintf(fd, " subclass:\n");
422  fprintf(fd, " pi: %g\n", Sp->pi);
423  fprintf(fd, " means:");
424  for (b1 = 0; b1 < S->nbands; b1++)
425  fprintf(fd, " %g", Sp->means[b1]);
426  fprintf(fd, "\n");
427  fprintf(fd, " covar:\n");
428  for (b1 = 0; b1 < S->nbands; b1++) {
429  fprintf(fd, " ");
430  for (b2 = 0; b2 < S->nbands; b2++)
431  fprintf(fd, " %g", Sp->R[b1][b2]);
432  fprintf(fd, "\n");
433  }
434  fprintf(fd, " endsubclass:\n");
435  }
436  fprintf(fd, "endclass:\n");
437  }
438 
439  return 0;
440 }
441 
442 /*!
443  * \brief Reorder struct SigSet to match imagery group member order
444  *
445  * The function will check for semantic label match between sigset struct
446  * and imagery group.
447  *
448  * In the case of a complete semantic label match, values of passed in
449  * struct SigSet are reordered to match the order of imagery group items.
450  * This reordering is done only for items present in the sigset file.
451  * Thus reordering should be done only after calling I_ReadSigSet.
452  *
453  * If all semantic labels are not identical (in
454  * arbitrary order), function will return two dimensional array with
455  * comma separated list of:
456  * - [0] semantic labels present in the signature struct but
457  * absent in the imagery group
458  * - [1] semantic labels present in the imagery group but
459  * absent in the signature struct
460  *
461  * If no mismatch of semantic labels for signatures or imagery group are
462  * detected (== all are present in the other list), a NULL value will be
463  * returned in the particular list of mismatches (not an empty string).
464  * For example:
465  * \code if (ret && ret[1]) printf("List of imagery group bands without
466  * signatures: %s\n, ret[1]); \endcode
467  *
468  * \param *SigSet existing signatures to check & sort
469  * \param *Ref group reference
470  *
471  * \return NULL successfully sorted
472  * \return err_array two comma separated lists of mismatches
473  */
474 char **I_SortSigSetBySemanticLabel(struct SigSet *S, const struct Ref *R)
475 {
476  unsigned int total, complete;
477  unsigned int *match1, *match2, mc1, mc2, *new_order;
478  double ***new_means, ****new_vars;
479  char **group_semantic_labels, **mismatches, **new_semantic_labels;
480 
481  /* Safety measure. Untranslated as this should not happen in production! */
482  if (S->nbands < 1 || R->nfiles < 1)
483  G_fatal_error("Programming error. Invalid length structs passed to "
484  "I_sort_signatures_by_semantic_label(%d, %d);",
485  S->nbands, R->nfiles);
486 
487  /* Obtain group semantic labels */
488  group_semantic_labels = (char **)G_malloc(R->nfiles * sizeof(char *));
489  for (unsigned int j = R->nfiles; j--;) {
490  group_semantic_labels[j] =
491  Rast_get_semantic_label_or_name(R->file[j].name, R->file[j].mapset);
492  }
493 
494  /* If lengths are not equal, there will be a mismatch */
495  complete = S->nbands == R->nfiles;
496 
497  /* Initialize match tracker */
498  new_order = (unsigned int *)G_malloc(S->nbands * sizeof(unsigned int));
499  match1 = (unsigned int *)G_calloc(S->nbands, sizeof(unsigned int));
500  match2 = (unsigned int *)G_calloc(R->nfiles, sizeof(unsigned int));
501 
502  /* Allocate memory for temporary storage of sorted values */
503  new_semantic_labels = (char **)G_malloc(S->nbands * sizeof(char *));
504  new_means = (double ***)G_malloc(S->nclasses * sizeof(double **));
505  // new_vars[S.ClassSig[x]][.SubSig[y]][R[band1]][R[band1]]
506  new_vars = (double ****)G_malloc(S->nclasses * sizeof(double ***));
507  for (unsigned int c = S->nclasses; c--;) {
508  new_means[c] =
509  (double **)G_malloc(S->ClassSig[c].nsubclasses * sizeof(double *));
510  new_vars[c] = (double ***)G_malloc(S->ClassSig[c].nsubclasses *
511  sizeof(double **));
512  for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
513  new_means[c][s] = (double *)G_malloc(S->nbands * sizeof(double));
514  new_vars[c][s] = (double **)G_malloc(S->nbands * sizeof(double *));
515  for (unsigned int i = S->nbands; i--;)
516  new_vars[c][s][i] =
517  (double *)G_malloc(S->nbands * sizeof(double));
518  }
519  }
520 
521  /* Obtain order of matching items */
522  for (unsigned int j = R->nfiles; j--;) {
523  for (unsigned int i = S->nbands; i--;) {
524  if (S->semantic_labels[i] && group_semantic_labels[j] &&
525  !strcmp(S->semantic_labels[i], group_semantic_labels[j])) {
526  if (complete) {
527  /* Reorder pointers to existing strings only */
528  new_semantic_labels[j] = S->semantic_labels[i];
529  new_order[i] = j;
530  }
531  /* Keep a track of matching items for error reporting */
532  match1[i] = 1;
533  match2[j] = 1;
534  break;
535  }
536  }
537  }
538 
539  /* Check for semantic label mismatch */
540  mc1 = mc2 = 0;
541  mismatches = (char **)G_malloc(2 * sizeof(char **));
542  mismatches[0] = NULL;
543  mismatches[1] = NULL;
544  total = 1;
545  for (unsigned int i = 0; i < (unsigned int)S->nbands; i++) {
546  if (!match1[i]) {
547  if (S->semantic_labels[i])
548  total = total + strlen(S->semantic_labels[i]);
549  else
550  total = total + 24;
551  mismatches[0] =
552  (char *)G_realloc(mismatches[0], total * sizeof(char *));
553  if (mc1)
554  strcat(mismatches[0], ",");
555  else
556  mismatches[0][0] = '\0';
557  if (S->semantic_labels[i])
558  strcat(mismatches[0], S->semantic_labels[i]);
559  else
560  strcat(mismatches[0], "<semantic label missing>");
561  mc1++;
562  total = total + 1;
563  }
564  }
565  total = 1;
566  for (unsigned int j = 0; j < (unsigned int)R->nfiles; j++) {
567  if (!match2[j]) {
568  if (group_semantic_labels[j])
569  total = total + strlen(group_semantic_labels[j]);
570  else
571  total = total + 24;
572  mismatches[1] =
573  (char *)G_realloc(mismatches[1], total * sizeof(char *));
574  if (mc2)
575  strcat(mismatches[1], ",");
576  else
577  mismatches[1][0] = '\0';
578  if (group_semantic_labels[j])
579  strcat(mismatches[1], group_semantic_labels[j]);
580  else
581  strcat(mismatches[1], "<semantic label missing>");
582  mc2++;
583  total = total + 1;
584  }
585  }
586 
587  /* Swap mean and var matrix values in each of classes */
588  if (!mc1 && !mc2) {
589  for (unsigned int c = S->nclasses; c--;) {
590  for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
591  for (unsigned int b1 = 0; b1 < (unsigned int)S->nbands; b1++) {
592  new_means[c][s][new_order[b1]] =
593  S->ClassSig[c].SubSig[s].means[b1];
594  for (unsigned int b2 = 0; b2 < (unsigned int)S->nbands;
595  b2++) {
596  new_vars[c][s][new_order[b1]][new_order[b2]] =
597  S->ClassSig[c].SubSig[s].R[b1][b2];
598  }
599  }
600  }
601  }
602 
603  /* Replace values in struct with ordered ones */
604  memcpy(S->semantic_labels, new_semantic_labels,
605  S->nbands * sizeof(char **));
606  for (unsigned int c = S->nclasses; c--;) {
607  for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
608  memcpy(S->ClassSig[c].SubSig[s].means, new_means[c][s],
609  S->nbands * sizeof(double));
610  for (unsigned int i = S->nbands; i--;)
611  memcpy(S->ClassSig[c].SubSig[s].R[i], new_vars[c][s][i],
612  S->nbands * sizeof(double));
613  }
614  }
615  }
616 
617  /* Clean up */
618  for (unsigned int j = R->nfiles; j--;)
619  free(group_semantic_labels[j]);
620  free(group_semantic_labels);
621  free(new_order);
622  free(match1);
623  free(match2);
624  free(new_semantic_labels);
625  for (unsigned int c = S->nclasses; c--;) {
626  for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
627  free(new_means[c][s]);
628  for (unsigned int i = S->nbands; i--;)
629  free(new_vars[c][s][i]);
630  free(new_vars[c][s]);
631  }
632  free(new_means[c]);
633  free(new_vars[c]);
634  }
635 
636  free(new_means);
637  free(new_vars);
638 
639  if (mc1 || mc2) {
640  return mismatches;
641  }
642  free(mismatches);
643  return NULL;
644 }
#define NULL
Definition: ccmath.h:32
#define G_realloc(p, n)
Definition: defs/gis.h:96
#define G_calloc(m, n)
Definition: defs/gis.h:95
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition: defs/gis.h:94
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
char * Rast_get_semantic_label_or_name(const char *, const char *)
Get a raster map semantic label or fall back to its name.
#define GNAME_MAX
Definition: gis.h:191
#define _(str)
Definition: glocale.h:10
#define SIGNATURE_TYPE_MIXED
Definition: imagery.h:199
int count
int I_SetSigTitle(struct SigSet *S, const char *title)
Definition: sigset.c:356
struct ClassSig * I_NewClassSig(struct SigSet *S)
Definition: sigset.c:77
int I_ReadSigSet(FILE *fd, struct SigSet *S)
Read sigset signatures from file.
Definition: sigset.c:141
const char * I_GetSigTitle(const struct SigSet *S)
Definition: sigset.c:367
#define eq(a, b)
Definition: sigset.c:124
int I_SigSetNClasses(struct SigSet *S)
Definition: sigset.c:32
int I_SetClassTitle(struct ClassSig *C, const char *title)
Definition: sigset.c:375
struct ClassData * I_AllocClassData(struct SigSet *S, struct ClassSig *C, int npixels)
Definition: sigset.c:43
int I_InitSigSet(struct SigSet *S, int nbands)
Initialize struct SigSet before use.
Definition: sigset.c:64
struct SubSig * I_NewSubSig(struct SigSet *S, struct ClassSig *C)
Definition: sigset.c:96
const char * I_GetClassTitle(const struct ClassSig *C)
Definition: sigset.c:386
char ** I_SortSigSetBySemanticLabel(struct SigSet *S, const struct Ref *R)
Reorder struct SigSet to match imagery group member order.
Definition: sigset.c:474
int I_WriteSigSet(FILE *fd, const struct SigSet *S)
Definition: sigset.c:394
void free(void *)
int npixels
Definition: imagery.h:78
double ** p
Definition: imagery.h:81
double ** x
Definition: imagery.h:80
int count
Definition: imagery.h:79
int nsubclasses
Definition: imagery.h:89
struct ClassData ClassData
Definition: imagery.h:91
long classnum
Definition: imagery.h:85
int type
Definition: imagery.h:88
char * title
Definition: imagery.h:86
struct SubSig * SubSig
Definition: imagery.h:90
int used
Definition: imagery.h:87
Definition: imagery.h:24
Definition: imagery.h:94
int nbands
Definition: imagery.h:95
struct ClassSig * ClassSig
Definition: imagery.h:99
char ** semantic_labels
Definition: imagery.h:96
int nclasses
Definition: imagery.h:97
char * title
Definition: imagery.h:98
Definition: imagery.h:67
double pi
Definition: imagery.h:69
double N
Definition: imagery.h:68
int used
Definition: imagery.h:74
double ** R
Definition: imagery.h:71
double cnst
Definition: imagery.h:73
double * means
Definition: imagery.h:70
double ** Rinv
Definition: imagery.h:72