summaryrefslogtreecommitdiff
blob: cbe94f45db4f8774eb1e3f6b43371cec2a478154 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*====================================================================*
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
 -
 -  Redistribution and use in source and binary forms, with or without
 -  modification, are permitted provided that the following conditions
 -  are met:
 -  1. Redistributions of source code must retain the above copyright
 -     notice, this list of conditions and the following disclaimer.
 -  2. Redistributions in binary form must reproduce the above
 -     copyright notice, this list of conditions and the following
 -     disclaimer in the documentation and/or other materials
 -     provided with the distribution.
 -
 -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
 -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *====================================================================*/

/*
 *   otsutest2.c
 *
 *   This demonstrates the usefulness of the modified version of Otsu
 *   for thresholding an image that doesn't have a well-defined
 *   background color.
 *
 *   Standard Otsu binarization is done with scorefract = 0.0, which
 *   returns the threshold at the maximum value of the score.  However.
 *   this value is up on the shoulder of the background, and its
 *   use causes some of the dark background to be binarized as foreground.
 *
 *   Using the modified Otsu with scorefract = 0.1 returns a threshold
 *   at the lowest value of this histogram such that the score
 *   is at least 0.9 times the maximum value of the score.  This allows
 *   the threshold to be taken in the histogram minimum between
 *   the fg and bg peaks, producing a much cleaner binarization.
 */


#ifdef HAVE_CONFIG_H
#include <config_auto.h>
#endif  /* HAVE_CONFIG_H */

#include "allheaders.h"


int main(int    argc,
         char **argv)
{
char       textstr[256];
l_int32    i, thresh, fgval, bgval;
l_float32  scorefract;
L_BMF     *bmf;
PIX       *pixs, *pixb, *pixg, *pixp, *pix1, *pix2, *pix3;
PIXA      *pixa1, *pixad;

    setLeptDebugOK(1);
    lept_mkdir("lept/otsu");

    pixs = pixRead("1555.007.jpg");
    pixg = pixConvertTo8(pixs, 0);
    bmf = bmfCreate(NULL, 8);
    pixad = pixaCreate(0);
    for (i = 0; i < 3; i++) {
        pixa1 = pixaCreate(2);
        scorefract = 0.1 * i;

            /* Get a 1 bpp version; use a single tile */
        pixOtsuAdaptiveThreshold(pixg, 2000, 2000, 0, 0, scorefract,
                                 NULL, &pixb);
        pixaAddPix(pixa1, pixg, L_COPY);
        pixaAddPix(pixa1, pixb, L_INSERT);

            /* Show the histogram of gray values and the split location */
        pixSplitDistributionFgBg(pixg, scorefract, 1,
                                 &thresh, &fgval, &bgval, &pixp);
        lept_stderr("thresh = %d, fgval = %d, bgval = %d\n",
                    thresh, fgval, bgval);
        pixaAddPix(pixa1, pixp, L_INSERT);

            /* Join these together and add some text */
        pix1 = pixaDisplayTiledInColumns(pixa1, 3, 1.0, 20, 2);
        snprintf(textstr, sizeof(textstr),
             "Scorefract = %3.1f ........... Thresh = %d", scorefract, thresh);
        pix2 = pixAddSingleTextblock(pix1, bmf, textstr, 0x00ff0000,
                                     L_ADD_BELOW, NULL);

            /* Save and display the result */
        pixaAddPix(pixad, pix2, L_INSERT);
        snprintf(textstr, sizeof(textstr), "/tmp/lept/otsu/%03d.png", i);
        pixWrite(textstr, pix2, IFF_PNG);
        pixDisplay(pix2, 100, 100);
        pixDestroy(&pix1);
        pixaDestroy(&pixa1);
    }

        /* Use a smaller tile for Otsu */
    for (i = 0; i < 2; i++) {
        scorefract = 0.1 * i;
        pixOtsuAdaptiveThreshold(pixg, 300, 300, 0, 0, scorefract,
                                 NULL, &pixb);
        pix1 = pixAddBlackOrWhiteBorder(pixb, 2, 2, 2, 2, L_GET_BLACK_VAL);
        pix2 = pixScale(pix1, 0.5, 0.5);
        snprintf(textstr, sizeof(textstr),
             "Scorefract = %3.1f", scorefract);
        pix3 = pixAddSingleTextblock(pix2, bmf, textstr, 1,
                                     L_ADD_BELOW, NULL);
        pixaAddPix(pixad, pix3, L_INSERT);
        pixDestroy(&pixb);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }

    lept_stderr("Writing to: /tmp/lept/otsu/result1.pdf\n");
    pixaConvertToPdf(pixad, 75, 1.0, 0, 0, "Otsu thresholding",
                     "/tmp/lept/otsu/result1.pdf");
    bmfDestroy(&bmf);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixaDestroy(&pixad);
    return 0;
}