home *** CD-ROM | disk | FTP | other *** search
- /*
- * structfeat.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* STRUCTFEAT: program decodes PCC and writes out line structure features
- * usage: structfeat in.pcc out.pcc
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "pcc2.h" /* header file for PCC programs */
- extern void print_sos_lic ();
-
- unsigned char *fcCode; /* code storage */
- long nByteCode; /* no. bytes in code storage */
-
- long tlc3rid (struct attributes *, long, struct structures *,
- long *, long, long, long, long);
- long usage (short);
- long input (int, char **, short *);
-
- main (argc, argv)
- int argc;
- char *argv[];
-
- {
- long width, height; /* image size */
- short sumFlag; /* flag=1 to print only summary; 0 otherwise */
- struct attributes *attr; /* level 1 attributes */
- long nAttr; /* no. of line structures in attr. array */
- struct structures *structs; /* level 3 line structures */
- long nStructs; /* no. of connected structures in image */
- long sumNLines; /* sum of no. of lines in all struct.s */
- long sumNEnds; /* sum of no. of endlines in all struct.s */
- long sumLength; /* sum of total line lengths for all structs */
- long sumMaxLength; /* sum of max. line lengths in all structs */
- double sumX, sumY; /* sum of structure x,y centroids */
- long sumBoxX, sumBoxY; /* sum of x,y bounding box lengths */
- long sumArea; /* sum of bounding box areas */
- int i;
-
- if (input (argc, argv, &sumFlag) < 0)
- return (-1);
-
- /* open input PCC file */
- if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
- exit (1);
- printf ("image size: %dx%d, PCC length = %d\n",
- width, height, nByteCode);
-
- /* construct tables of PCC decodes */
- pccdecodes ();
-
- /* construct TLC level 1 array of attributes */
- tlc1attr (&attr, &nAttr);
- printf ("%d level 1 line features\n", nAttr);
-
- /* find level 3 connected structures */
- tlc3structs (attr, nAttr, &structs, &nStructs);
-
- /* determine level 3 features */
- tlc3feats (attr, nAttr, structs, nStructs);
-
- /* summary information */
- sumNLines = sumNEnds = sumLength = sumMaxLength = 0;
- sumX = sumY = 0.0;
- sumBoxX = sumBoxY = sumArea = 0;
- for (i = 0; i < nStructs; i++) {
- sumNLines += structs[i].nLines;
- sumNEnds += structs[i].nEnds;
- sumLength += structs[i].length;
- sumMaxLength += structs[i].maxLength;
- sumX += structs[i].centroidX;
- sumY += structs[i].centroidY;
- sumBoxX += (structs[i].box.max.x - structs[i].box.min.x);
- sumBoxY += (structs[i].box.max.y - structs[i].box.min.y);
- sumArea += (structs[i].box.max.x - structs[i].box.min.x)
- * (structs[i].box.max.y - structs[i].box.min.y);
- }
- printf ("Structure Feature Summary:\n");
- printf ("\tnumber of line structures = %d\n", nStructs);
- printf ("\taverage number of lines per structure = %5.1f\n",
- (double) sumNLines / (double) nStructs);
- printf ("\taverage number of endlines per structure = %5.1f\n",
- (double) sumNEnds / (double) nStructs);
- printf ("\taverage total line length per structure %5.1f\n",
- (double) sumLength / ((double) nStructs * 10.0));
- printf ("\taverage maximum line length per structure = %5.1f\n",
- (double) sumMaxLength / ((double) nStructs * 10.0));
- printf ("\taverage bounding box size = %5.1f x %5.1f, area = %5.1f [pix]\n",
- (double) sumBoxX / (double) nStructs,
- (double) sumBoxY / (double) nStructs,
- (double) sumArea / (double) nStructs);
- printf ("\taverage of structure centroids = (%5.1f,%5.1f) [pixels]\n",
- sumX / (double) nStructs,
- sumY / (double) nStructs);
-
- /* print features for each line structure */
-
- if (sumFlag)
- return (-1);
- printf ("\nLine Structure Features:\n");
- for (i = 0; i < nStructs; i++) {
- printf ("\n%d: ", i);
- printf ("\tno. lines = %d, no. endlines = %d\n",
- structs[i].nLines, structs[i].nEnds);
- printf ("\ttotal line length = %5.1f, max. length of a segment = %5.1f\n",
- (double) structs[i].length / 10.0,
- (double) structs[i].maxLength / 10.0);
- printf ("\tbounding box: (%d,%d),(%d,%d), area = %d\n",
- structs[i].box.min.x, structs[i].box.min.y,
- structs[i].box.max.x, structs[i].box.max.y,
- (structs[i].box.max.x - structs[i].box.min.x)
- * (structs[i].box.max.y - structs[i].box.min.y));
- printf ("\tcentroid: (%5.1f,%5.1f)\n",
- structs[i].centroidX, structs[i].centroidY);
- }
-
- return (0);
- }
-
-
-
- /* TLC3RID: function removes any level 3 structures above or below threshold
- * usage: tlc3rid (attr, nAttr, structs, &nStructs,
- * lowLength, highLength, lowArea, highArea)
- */
-
- long
- tlc3rid (attr, nAttr, structs, nStructs, lowLength, highLength,
- lowArea, highArea)
- struct attributes *attr; /* level 1 attributes */
- long nAttr; /* no. level 1 attributes */
- struct structures *structs; /* level 3 attributes */
- long *nStructs; /* no. level 3 attributes */
- long lowLength, highLength, /* length range to retain (*10) */
- lowArea, highArea; /* area range to retain */
- {
- long strtCode, endCode, /* bounds of code for structure */
- iStopByte, /* position of STOPBYTE */
- nStructsOut, /* no. of structures after removal */
- iStructs, /* level 3 increment */
- iCode, /* input PCC incrementor */
- iOut; /* output PCC incrementor */
- struct structures strct; /* level 3 structure */
- long lx, ly, /* lengths of bounding box */
- area; /* area of bounding box */
-
- /* find position of STOPCODE (I'm inconsistent I think in putting 4 bytes
- * trailing this or not, so we'll find it) */
- for (iStopByte = nByteCode - 1; iStopByte > 0; --iStopByte)
- if (fcCode[iStopByte] == STOPCODE)
- break;
-
- /* read code, and write code which is not deleted */
- nStructsOut = 0;
- for (iStructs = 0, iOut = 0; iStructs < *nStructs; iStructs++) {
- strct = structs[iStructs];
- strtCode = attr[strct.iAttr].iByteCode - 5;
- endCode = (iStructs + 1 < *nStructs) ?
- attr[structs[iStructs + 1].iAttr].iByteCode - 6 : iStopByte - 1;
- lx = (strct.box.max.x - strct.box.min.x);
- ly = (strct.box.max.y - strct.box.min.y);
- if (lx == 0)
- lx = 1;
- if (ly == 0)
- ly = 1;
- area = lx * ly;
- if (area < 0)
- area *= -1;
- if (strct.length >= lowLength && strct.length < highLength
- && area >= lowArea && area < highArea) {
- nStructsOut++;
- for (iCode = strtCode; iCode <= endCode; iCode++)
- fcCode[iOut++] = fcCode[iCode];
- }
- }
-
- for (iCode = iStopByte; iCode < nByteCode; iCode++)
- fcCode[iOut++] = fcCode[iCode];
- *nStructs = nStructsOut;
- nByteCode = iOut;
- return (0);
- }
-
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("USAGE: structfeat infile [-s] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nstructfeat lists line structures, that is, objects\n");
- printf ("made up of one or many connected line segments.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (PCC) \n\n");
- printf ("OPTIONS:\n");
- printf (" -s: print summary only.\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &sumFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, sumFlag)
- int argc;
- char *argv[];
- short *sumFlag; /* flag =1, print only summary; 0 otherwise */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
-
- *sumFlag = 0;
-
- for (n = 2; n < argc; n++) {
- if (strcmp (argv[n], "-s") == 0)
- *sumFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- return (0);
- }
-