Main Page   Compound List   File List   Compound Members   File Members  

graytobw.c

00001 /*
00002   The following code was send by Ryan Dibble <dibbler@umich.edu>
00003  
00004   The algorithm is very simple but works well.
00005  
00006   Compare the grayscale histogram with a mass density diagram:
00007   I think the algorithm is a kind of
00008   divide a body into two parts in a way that the mass 
00009   centers have the largest distance from each other,
00010   the function is weighted in a way that same masses have a advantage
00011   
00012   TODO:
00013     RGB: do the same with all colors (CMYG?) seperately 
00014 
00015     test: hardest case = two colors
00016        bbg: test done, using a two color gray file. Output:
00017        # OTSU: thresholdValue = 43 gmin=43 gmax=188
00018 
00019  my changes:
00020    - float -> double
00021    - debug option added (vvv & 1..2)
00022    - **image => *image,  &image[i][1] => &image[i*cols+1]
00023      Joerg.Schulenburg@physik.uni-magdeburg.de
00024 
00025  adapted for GOCR API by Bruno Barberi Gnecco
00026 */
00027 
00028 #include "_gocr.h"
00029 
00030 /*======================================================================*/
00031 /* OTSU global thresholding routine                                     */
00032 /*   takes a 2D unsigned char array pointer, number of rows, and        */
00033 /*   number of cols in the array. returns the value of the threshold    */
00034 /*   in addition to thresholding the image at that value                */ 
00035 /*======================================================================*/
00036 int otsu ( gocrImage *image, void *v ) {
00037   int thresholdValue; // value we will threshold at
00038   int ihist[256];     // image histogram
00039 
00040   int i, j, k;        // various counters
00041   int n, n1, n2, gmin, gmax;
00042   double m1, m2, sum, csum, fmax, sb;
00043   unsigned char **data = (unsigned char **)image->data, *c;
00044   gocrPixel p;
00045   
00046   _gocr_debug(3, fprintf(_data.error, "otsu(%p, %p)\n", image, v);)
00047 
00048   memset(&p, 0, sizeof(gocrPixel));
00049 
00050   // zero out histogram ...
00051   memset(ihist, 0, sizeof(ihist));
00052 
00053   gmin=255; gmax=0;
00054   // generate the histogram
00055   for (i = 1; i < image->x - 1; i++) {
00056     for (j = 1; j < image->y - 1; j++) {
00057       ihist[data[i][j]]++;
00058       if (data[i][j] > gmax) 
00059         gmax = data[i][j];
00060       if (data[i][j] < gmin) 
00061         gmin = data[i][j];
00062     }
00063   }
00064 
00065   // set up everything
00066   sum = csum = 0.0;
00067   n = 0;
00068 
00069   for (k = 0; k <= 255; k++) {
00070     sum += (double) k * (double) ihist[k];  /* x*f(x) mass moment */
00071     n   += ihist[k];                        /*  f(x)    mass      */
00072   }
00073 
00074   if (!n) {
00075     // if n has no value we have problems...
00076     _gocr_debug(1, fprintf(_data.error, "NOT NORMAL thresholdValue = %d\n", thresholdValue);)
00077     return -1;
00078   }
00079 
00080   // do the otsu global thresholding method
00081 
00082   fmax = -1.0;
00083   n1 = 0;
00084   for (k = 0; k < 255; k++) {
00085     n1 += ihist[k];
00086     if (!n1) { continue; }
00087     n2 = n - n1;
00088     if (n2 == 0) { break; }
00089     csum += (double) k *ihist[k];
00090     m1 = csum / n1;
00091     m2 = (sum - csum) / n2;
00092     sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
00093     /* bbg: note: can be optimized. */
00094     if (sb > fmax) {
00095       fmax = sb;
00096       thresholdValue = k;
00097     }
00098   }
00099 
00100   // at this point we have our thresholding value
00101 
00102   // debug code to display thresholding values
00103   _gocr_debug(3, fprintf(_data.error, "thresholdValue=%d  gmin=%d  gmax=%d\n",
00104      thresholdValue, gmin, gmax);)
00105 
00106   // actually performs the thresholding of the image...
00107   // comment it out if you only want to know what value to threshold at...
00108   for (i = 0; i < image->x; i++)
00109     for (j = 0; j < image->y; j++)
00110       image->data[i][j].value = (data[i][j] > thresholdValue ? 
00111           GOCR_WHITE : GOCR_BLACK );
00112 
00113   return 0;
00114 }

Generated at Thu Mar 1 10:05:32 2001 for GOCR API by doxygen1.2.2 written by Dimitri van Heesch, © 1997-2000