home *** CD-ROM | disk | FTP | other *** search
- /*
- * fitcrit.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* FITCRIT: program fits lines between high curvature points (critical
- * points)
- * usage: fitcrit infile outimg [-l FIT_LENGTH] [-r CORNER_ARC] [-c] [-L]
- */
-
- #define NOCURVES 0 /* fit 2 lines to circ curves, not curves */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <images.h>
- #include "tiffimage.h"
- #include "pcc2.h" /* for PCC programs */
- extern void print_sos_lic ();
-
- unsigned char *fcCode; /* code storage */
- long nByteCode; /* no. bytes in code storage */
- long maxCorner; /* maximum arc length of corner curvature */
- /* needed for zzWidth calc in FEATDETERM */
- struct featNode *featHead = NULL, /* linked list of features head/tail */
- *featTail;
- long nFeats; /* number of ww features */
-
- int linkcorner (int, struct point);
-
- long xytoline (struct point *, long *, long *, long *);
- long wwtofeats (struct wwfeats *, long *, long *, long *);
- long usage (short);
- long input (int, char **, long *, long *, short *);
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- Image *imgO; /* pointer to output image structure */
- unsigned char **image; /* output image array */
- long width, height; /* image size */
- struct point imgSize; /* image size */
- short coordFlag; /* flag = 1, print fit coord.s; or 0 */
- short curveFlag; /* =0 for curve fit by 2 lines; =1 for curve */
- struct point *data; /* data curve */
- long nData; /* no. coords in data curve */
- long nSegments; /* number of segments found */
- long nStructs; /* number of line structures found */
- long drawline8 (); /* joins points in 8-connected lines */
- long wwtheta (); /* finds critical points from theta plot */
- long nThetaFeats; /* no. of features found from plot */
- struct edge edge; /* lower/upper indices of segment in data */
- long minLength; /* minimum feature length */
- struct wwPar wwPar; /* wing-walk parameters */
- long nWWFeats; /* number of line critical features */
- struct wwfeats *feats; /* array of output ww features */
- long nLines, nCurves; /* number of lines and curves fit */
- struct point midArc; /* middle arc point of curve */
- long x, y;
- long i;
-
- /* user input */
- if (input (argc, argv, &minLength, &maxCorner, &coordFlag) < 0)
- return (-1);
- curveFlag = NOCURVES;
-
- /* open input PCC file */
- if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
- exit (0);
- if (!coordFlag)
- printf ("image size: %dx%d, PCC length = %d\n", width, height, nByteCode);
- imgSize.x = width;
- imgSize.y = height;
-
- /* allocate space for data coordinate array */
- if ((data = (struct point *)
- calloc (nByteCode * MAXPERCODE, sizeof (long))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-1);
- }
-
- /* construct tables of feature chain decodes */
- pccdecodes ();
-
- /* perform feature chain decoding */
- pcc2xy (data, &nData);
-
- data[nData++].x = -STOPCODE;
- if ((data = (struct point *)
- realloc (data, nData * sizeof (struct point))) == NULL) {
- printf ("FITPOLYG: not enough memory -- sorry");
- return (-2);
- }
-
- /* find x,y coordinates for each line */
- if (xytoline (data, &nData, &nSegments, &nStructs) < 0)
- return (-1);
-
- /* determine geometric features in line data */
- wwPar.m = (maxCorner % 2) ? maxCorner : maxCorner + 1;
- wwPar.l = (minLength % 2) ? minLength : minLength - 1;
- if (wwPar.m > wwPar.l - 2) {
- wwPar.m = wwPar.l - 2;
- }
- wwPar.w = (wwPar.l - wwPar.m) / 2;
-
- for (i = 0; i < nData; i++) {
- if (data[i].x != -1) {
- edge.iLow = i;
- linkcorner (WWSTRT, data[edge.iLow]);
- while (data[++i].x >= 0);
- --i;
- edge.iHigh = i;
- nThetaFeats = wwtheta (data, edge, wwPar, curveFlag);
- if (nThetaFeats < 0)
- return (-1);
- linkcorner (WWEND, data[edge.iHigh]);
- }
- }
-
- /* write corner features to ww features */
- nWWFeats = nData;
- if ((feats = (struct wwfeats *) calloc (nWWFeats, sizeof (*feats)))
- == NULL) {
- printf ("FITFEAT: nuts, not enough memory for <feats> array");
- return (-3);
- }
-
- wwtofeats (feats, &nWWFeats, &nLines, &nCurves);
-
- /* print line features */
- if (!coordFlag)
- printf ("Number of lines = %d, curves = %d\n", nLines, nCurves);
-
- if (coordFlag)
- for (i = 0; i < nWWFeats; i++) {
- if (feats[i].radius == 0.0)
- printf ("%d (LINE): (%3d,%3d) to (%3d,%3d)\n", i, feats[i].strt.x,
- feats[i].strt.y, feats[i].end.x, feats[i].end.y);
- else {
- printf ("%d (CURVE): (%3d,%3d) to (%3d,%3d), ", i, feats[i].strt.x,
- feats[i].strt.y, feats[i].end.x, feats[i].end.y);
-
- printf ("radius = %5.2f, center = (%5.2f,%5.2f)\n",
- feats[i].radius, feats[i].center.x, feats[i].center.y);
- }
- }
-
- /* allocate output image */
- imgO = ImageAlloc (height, width, 8);
- image = ImageGetPtr (imgO);
-
- /* initialize image */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- image[y][x] = 255;
-
- /* draw fits into output image */
- for (i = 0; i < nWWFeats; i++) {
- if (feats[i].radius == 0.0) { /* straight line */
- if (feats[i].strt.x < 0)
- feats[i].strt.x = 0;
- if (feats[i].strt.x >= width)
- feats[i].strt.x = width - 1;
- if (feats[i].strt.y < 0)
- feats[i].strt.y = 0;
- if (feats[i].strt.y >= height)
- feats[i].strt.y = height - 1;
-
- if (feats[i].end.x < 0)
- feats[i].end.x = 0;
- if (feats[i].end.x >= width)
- feats[i].end.x = width - 1;
- if (feats[i].end.y < 0)
- feats[i].end.y = 0;
- if (feats[i].end.y >= height)
- feats[i].end.y = height - 1;
-
- drawline8 (image, imgSize, feats[i].strt, feats[i].end, 0);
- }
- else { /* curve -- approx by 2 lines */
- if (feats[i].strt.x < 0)
- feats[i].strt.x = 0;
- if (feats[i].strt.x >= width)
- feats[i].strt.x = width - 1;
- if (feats[i].strt.y < 0)
- feats[i].strt.y = 0;
- if (feats[i].strt.y >= height)
- feats[i].strt.y = height - 1;
-
- midArc.x = (long) (feats[i].center.x + 0.5);
- midArc.y = (long) (feats[i].center.y + 0.5);
- if (feats[i].center.x < 0.0)
- midArc.x = 0;
- if (feats[i].center.x >= width)
- midArc.x = width - 1;
- if (feats[i].center.y < 0)
- midArc.y = 0;
- if (feats[i].center.y >= height)
- midArc.y = height - 1;
-
- if (feats[i].end.x < 0)
- feats[i].end.x = 0;
- if (feats[i].end.x >= width)
- feats[i].end.x = width - 1;
- if (feats[i].end.y < 0)
- feats[i].end.y = 0;
- if (feats[i].end.y >= height)
- feats[i].end.y = height - 1;
-
- drawline8 (image, imgSize, feats[i].strt, midArc, 0);
- drawline8 (image, imgSize, midArc, feats[i].end, 0);
- }
-
-
- }
-
- /* write image output file */
- ImageOut (argv[2], imgO);
-
- return (0);
- }
-
-
- /* WWTOFEATS: function produces list of line features from linked list
- * of critical points
- * usage: wwtofeats (feats, &nWWFeats, &nLines, &nCurves)
- */
-
- long
- wwtofeats (feats, nWWFeats, nLines, nCurves)
- struct wwfeats *feats; /* array of output ww features */
- long *nWWFeats; /* number of line critical features */
- long *nLines, *nCurves; /* number of lines and curves fit */
- {
- struct featK *featK; /* corner and curve parameters */
- struct featC *featC;
- struct point lineStrt; /* start of ww line feature */
- long i;
-
- /* go through linked list of critical points and copy features to list */
- featTail = featHead;
- *nWWFeats = 0;
- *nLines = *nCurves = 0;
- for (i = 0; i < 10000; i++) {
- switch (featTail->type) {
- case WWSTRT: /* start line */
- featK = (struct featK *) featTail->info;
- lineStrt = featK->coord;
- break;
- case WWCORNER: /* corner */
- featK = (struct featK *) featTail->info;
- feats[*nWWFeats].strt = lineStrt;
- feats[*nWWFeats].end = featK->coord;
- (*nWWFeats)++;
- (*nLines)++;
- lineStrt = featK->coord;
- break;
- case WWCURVE: /* curve feature */
- featC = (struct featC *) featTail->info;
- feats[*nWWFeats].strt = lineStrt; /* first store line */
- feats[*nWWFeats].end = featC->trans1;
- (*nWWFeats)++;
- (*nLines)++;
- if (featC->dirn == 1) { /* then store curve */
- feats[*nWWFeats].strt = featC->trans1; /* correct order */
- feats[*nWWFeats].end = featC->trans2;
- }
- else { /* reverse direction curve */
- feats[*nWWFeats].strt = featC->trans2;
- feats[*nWWFeats].end = featC->trans1;
- }
- feats[*nWWFeats].center = featC->center;
- feats[*nWWFeats].radius = featC->radiusC;
- lineStrt = featC->trans2;
- (*nWWFeats)++;
- (*nCurves)++;
- break;
- case WWEND: /* end line */
- featK = (struct featK *) featTail->info;
- feats[*nWWFeats].strt = lineStrt;
- feats[*nWWFeats].end = featK->coord;
- (*nWWFeats)++;
- (*nLines)++;
- break;
- }
- featTail = featTail->next;
- if (featTail == NULL)
- break;
- }
- 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: fitcrit infile outimg [-l FIT_LENGTH] [-r CORNER_ARC] [-c] [-L]\n");
- if (flag == 0)
- return (-1);
-
- printf ("\nfitcrit fits straight lines between critical points\n");
- printf ("(curvature maxima) in the segments of pixel chains;\n");
- printf ("corners are located at the location of intersection of their\n");
- printf ("two boundary lines; curves are located by two straight lines\n");
- printf ("drawn from curve onsets (transition points) to the middle\n");
- printf ("point in the arc of the curve.\n\n");
- printf ("ARGUMENTS:\n");
- printf (" infile: input filename (PCC)\n");
- printf (" outimg: input image filename (TIF)\n\n");
- printf ("OPTIONS:\n");
- printf (" -l FIT_LENGTH: is the arc-length of the fit along the data\n");
- printf (" segments; the longer is this length, the greater is\n");
- printf (" smoothing, but the less ability to fit small features;\n");
- printf (" this is usually chosen as the minimum arc-length between\n");
- printf (" critical points on the data.\n");
- printf (" (default = %d [connected pixels]. minimum is %d.)\n",
- L_DFLT, L_MIN);
- printf (" -r CORNER_ARC: maximum arc-length of a corner; since a \n");
- printf (" corner feature will usually be rounded, there is a maximum\n");
- printf (" arc-length before over which that feature is considered\n");
- printf (" a curve and not a corner. (default = %d [connected pixels].\n", M_MAX);
- printf (" -c: when set, prints out the (x,y) coordinates of the\n");
- printf (" straight-line fits between critical points.\n");
- printf (" -L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &minLength, &coordFlag)
- */
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, minLength, maxCorner, coordFlag)
- int argc;
- char *argv[];
- long *minLength; /* minimum length of feature */
- long *maxCorner; /* maximum arc length of corner curvature */
- short *coordFlag; /* flag = 1, print coordinates of fit; or 0 */
- {
- long n;
-
- if (argc == 1)
- USAGE_EXIT (1);
- if (argc == 2)
- USAGE_EXIT (0);
-
- *minLength = L_DFLT;
- *maxCorner = M_MAX;
- *coordFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-l") == 0) {
- if (++n == argc)
- USAGE_EXIT (0);
- *minLength = (long) atol (argv[n]);
- }
- else if (strcmp (argv[n], "-r") == 0) {
- if (++n == argc)
- usage (0);
- *maxCorner = (long) atol (argv[n]);
- }
- else if (strcmp (argv[n], "-c") == 0)
- *coordFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (0);
- }
-
- if (*minLength < L_MIN)
- *minLength = L_MIN;
-
- return (0);
- }
-