home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / TARFILE.GZ / tarfile / ch_3.9 / threshm / threshm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  4.9 KB  |  201 lines

  1. /*
  2.  * threshm.c
  3.  *
  4.  * Practical Algorithms for Image Analysis
  5.  *
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* THRESHM:     program performs binarization by moment-preservation method
  10.  *                    usage: threshm inimg outimg [-i] [-L]
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <images.h>
  18. #include <tiffimage.h>          /* tiff file format info */
  19. #include <math.h>
  20. #include "misc.h"
  21. extern void print_sos_lic ();
  22.  
  23. #define NHIST 256               /* no. bins in histogram */
  24.  
  25. long input (int, char **, short *);
  26. long usage (short);
  27.  
  28. main (
  29.        int argc,
  30.        char *argv[])
  31. {
  32.   Image *imgI, *imgO;           /* I/O image structures */
  33.   unsigned char **imgIn, **imgOut;  /* input and output images */
  34.   long width, height;           /* image size */
  35.   long iHist[NHIST];            /* hist. of intensities */
  36.   double prob[NHIST];
  37.   double pDistr;
  38.   double m1, m2, m3;
  39.   double cd, c0, c1, z0, z1, pd, p0, p1;
  40.   long thresh;
  41.   short invertFlag;             /* if =0, dark -> ON; if =1, dark -> OFF */
  42.   long i, n;
  43.   int i1, j1, i2, j2;
  44.   int c;
  45.   int x1, y1, x2, y2;
  46.   char in_buf[IN_BUF_LEN];
  47.  
  48.   if ((input (argc, argv, &invertFlag)) < 0)
  49.     return (-1);
  50.  
  51. /* allocate input and output image memory */
  52.   imgI = ImageIn (argv[1]);
  53.   imgIn = ImageGetPtr (imgI);
  54.   height = ImageGetHeight (imgI);
  55.   width = ImageGetWidth (imgI);
  56.  
  57.   x1 = y1 = 0;
  58.   x2 = width;
  59.   y2 = height;
  60.   printf ("Specify AOI? (y/n) ");
  61.   c = readlin (in_buf);
  62.   if (c == 'y') {
  63.     while (1) {
  64.       printf ("Input upper left, lower right coordinates");
  65.       if (scanf ("%d %d %d %d", &x1, &y1, &x2, &y2) != 4)
  66.         printf ("Invalid input!  Try again\n");
  67.       else
  68.         break;
  69.     }
  70.   }
  71.   imgO = ImageAlloc (y2 - y1, x2 - x1, 8);
  72.   imgOut = ImageGetPtr (imgO);
  73.  
  74. /* compile histogram */
  75.   for (i = 0; i < NHIST; i++)
  76.     iHist[i] = 0;
  77.   for (i1 = y1, n = 0; i1 < y2; i1++) {
  78.     for (j1 = x1; j1 < x2; j1++) {
  79.       iHist[imgIn[i1][j1]]++;
  80.       n++;
  81.     }
  82.   }
  83.  
  84. /* compute probabilities */
  85.   for (i = 0; i < NHIST; i++)
  86.     prob[i] = (double) iHist[i] / (double) n;
  87.  
  88. /* calculate first 3 moments */
  89.   m1 = m2 = m3 = 0.0;
  90.   for (i = 0; i < NHIST; i++) {
  91.     m1 += i * prob[i];
  92.     m2 += i * i * prob[i];
  93.     m3 += i * i * i * prob[i];
  94.   }
  95. /*  printf ("moments: m1 = %5.2f, m2 = %5.2f, m3 = %5.2f\n", m1, m2, m3); */
  96.  
  97.   cd = m2 - m1 * m1;
  98.   c0 = (-m2 * m2 + m1 * m3) / cd;
  99.   c1 = (-m3 + m2 * m1) / cd;
  100.   z0 = 0.5 * (-c1 - sqrt (c1 * c1 - 4.0 * c0));
  101.   z1 = 0.5 * (-c1 + sqrt (c1 * c1 - 4.0 * c0));
  102.  
  103.   pd = z1 - z0;
  104.   p0 = (z1 - m1) / pd;
  105.   p1 = 1.0 - p0;
  106.  
  107. /* find threshold */
  108.   for (thresh = 0, pDistr = 0.0; thresh < NHIST; thresh++) {
  109.     pDistr += prob[thresh];
  110.     if (pDistr > p0)
  111.       break;
  112.   }
  113.  
  114.   printf ("Calculated threshold value (by moment method) = %d.\n", thresh);
  115.  
  116. /* output thresholded image */
  117.   if (invertFlag == 0) {
  118.     for (i1 = y1, i2 = 0, n = 0; i1 < y2; i1++, i2++)
  119.       for (j1 = x1, j2 = 0; j1 < x2; j1++, j2++)
  120.         imgOut[i2][j2] = (imgIn[i1][j1] > thresh) ? 255 : 0;
  121.   }
  122.   else {
  123.     for (i1 = y1, i2 = 0, n = 0; i1 < y2; i1++, i2++)
  124.       for (j1 = x1, j2 = 0; j1 < x2; j1++, j2++)
  125.         imgOut[i2][j2] = (imgIn[i1][j1] < thresh) ? 255 : 0;
  126.   }
  127.  
  128.   ImageOut (argv[2], imgO);
  129.  
  130.   return (0);
  131. }
  132.  
  133.  
  134.  
  135. /* USAGE:       function gives instructions on usage of program
  136.  *                    usage: usage (flag)
  137.  *              When flag is 1, the long message is given, 0 gives short.
  138.  */
  139.  
  140. long
  141. usage (flag)
  142.      short flag;                /* flag =1 for long message; =0 for short message */
  143. {
  144.  
  145. /* print short usage message or long */
  146.   printf ("USAGE: threshm inimg outimg [-i] [-L]\n");
  147.   if (flag == 0)
  148.     return (-1);
  149.  
  150.   printf ("\nthreshm performs binarization with respect to\n");
  151.   printf ("automatically determined intensity threshold;\n");
  152.   printf ("the input gray-level image is converted to a binary image;\n");
  153.   printf ("threshold determination is made by the moment-preservation\n");
  154.   printf ("method.\n\n");
  155.   printf ("ARGUMENTS:\n");
  156.   printf ("    inimg: input image filename (TIF)\n");
  157.   printf ("   outimg: output image filename (TIF)\n\n");
  158.   printf ("OPTIONS:\n");
  159.   printf ("       -i: INVERT: intensities ABOVE (lighter) threshold set to 0\n");
  160.   printf ("           and those BELOW (darker) threshold set to 255\n");
  161.   printf ("       -L: print Software License for this module\n");
  162.   return (-1);
  163. }
  164.  
  165.  
  166. /* INPUT:       function reads input parameters
  167.  *                  usage: input (argc, argv)
  168.  */
  169.  
  170. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  171.  
  172. long
  173. input (argc, argv, invertFlag)
  174.      int argc;
  175.      char *argv[];
  176.      short *invertFlag;         /* if =0, dark -> ON; if =1, dark -> OFF */
  177. {
  178.   long n;
  179.  
  180.   *invertFlag = 0;
  181.  
  182.   if (argc == 1)
  183.     USAGE_EXIT (1);
  184.   if (argc == 2)
  185.     USAGE_EXIT (0);
  186.  
  187.   for (n = 3; n < argc; n++) {
  188.     if (strcmp (argv[n], "-i") == 0) {
  189.       *invertFlag = 1;
  190.     }
  191.     else if (strcmp (argv[n], "-L") == 0) {
  192.       print_sos_lic ();
  193.       exit (0);
  194.     }
  195.     else
  196.       USAGE_EXIT (0);
  197.   }
  198.  
  199.   return (0);
  200. }
  201.