00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026
00027
00028 #include "_gocr.h"
00029
00030
00031
00032
00033
00034
00035
00036 int otsu ( gocrImage *image, void *v ) {
00037 int thresholdValue;
00038 int ihist[256];
00039
00040 int i, j, k;
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 }