Example #1
0
/*!
 * \brief   pixFindStrokeWidth()
 *
 * \param[in]    pixs 1 bpp
 * \param[in]    thresh  fractional count threshold relative to distance 1
 * \param[in]    tab8  [optional] table for counting fg pixels; can be NULL
 * \param[out]  *pwidth  estimated width of the strokes
 * \param[out]  *pnahisto  [optional] histo of pixel distances from bg
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This uses two methods to estimate the stroke width:
 *          (a) half the fg boundary length
 *          (b) a value derived from the histogram of the fg distance transform
 *      (2) Distance is measured in 8-connected
 *      (3) %thresh is the minimum fraction N(dist=d)/N(dist=1) of pixels
 *          required to determine if the pixels at distance d are above
 *          the noise. It is typically about 0.15.
 * </pre>
 */
l_int32
pixFindStrokeWidth(PIX        *pixs,
                   l_float32   thresh,
                   l_int32    *tab8,
                   l_float32  *pwidth,
                   NUMA      **pnahisto)
{
l_int32     i, n, count, length, first, last;
l_int32    *tab;
l_float32   width1, width2, ratio, extra;
l_float32  *fa;
NUMA       *na1, *na2;
PIX        *pix1;

    PROCNAME("pixFindStrokeWidth");

    if (!pwidth)
        return ERROR_INT("&width not defined", procName, 1);
    *pwidth = 0;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);

    tab = (tab8) ? tab8 : makePixelSumTab8();

    /* ------- Method 1: via boundary length ------- */
        /* The computed stroke length is a bit larger than that actual
         * length, because of the addition of the 'caps' at the
         * stroke ends.  Therefore the computed width is a bit
         * smaller than the average width. */
    pixFindStrokeLength(pixs, tab8, &length);
    pixCountPixels(pixs, &count, tab8);
    width1 = (l_float32)count / (l_float32)length;

    /* ------- Method 2: via distance transform ------- */
        /* First get the histogram of distances */
    pix1 = pixDistanceFunction(pixs, 8, 8, L_BOUNDARY_BG);
    na1 = pixGetGrayHistogram(pix1, 1);
    pixDestroy(&pix1);
    numaGetNonzeroRange(na1, 0.1, &first, &last);
    na2 = numaClipToInterval(na1, 0, last);
    numaWriteStream(stderr, na2);

        /* Find the bucket with the largest distance whose contents
         * exceed the threshold. */
    fa = numaGetFArray(na2, L_NOCOPY);
    n = numaGetCount(na2);
    for (i = n - 1; i > 0; i--) {
        ratio = fa[i] / fa[1];
        if (ratio > thresh) break;
    }
        /* Let the last skipped bucket contribute to the stop bucket.
         * This is the 'extra' term below.  The result may be a slight
         * over-correction, so the computed width may be a bit larger
         * than the average width. */
    extra = (i < n - 1) ? fa[i + 1] / fa[1] : 0;
    width2 = 2.0 * (i - 1.0 + ratio + extra);
    fprintf(stderr, "width1 = %5.2f, width2 = %5.2f\n", width1, width2);

        /* Average the two results */
    *pwidth = (width1 + width2) / 2.0;

    if (!tab8) LEPT_FREE(tab);
    numaDestroy(&na1);
    if (pnahisto)
        *pnahisto = na2;
    else
        numaDestroy(&na2);
    return 0;
}
Example #2
0
int main(int    argc,
         char **argv)
{
l_int32      type, comptype, d1, d2, same, first, last;
l_float32    fract, diff, rmsdiff;
char        *filein1, *filein2, *fileout;
GPLOT       *gplot;
NUMA        *na1, *na2;
PIX         *pixs1, *pixs2, *pixd;
static char  mainName[] = "comparetest";

    if (argc != 5)
        return ERROR_INT(" Syntax:  comparetest filein1 filein2 type fileout",
                         mainName, 1);

    filein1 = argv[1];
    filein2 = argv[2];
    type = atoi(argv[3]);
    pixd = NULL;
    fileout = argv[4];
    l_pngSetReadStrip16To8(0);

    if ((pixs1 = pixRead(filein1)) == NULL)
        return ERROR_INT("pixs1 not made", mainName, 1);
    if ((pixs2 = pixRead(filein2)) == NULL)
        return ERROR_INT("pixs2 not made", mainName, 1);
    d1 = pixGetDepth(pixs1);
    d2 = pixGetDepth(pixs2);

    if (d1 == 1 && d2 == 1) {
        pixEqual(pixs1, pixs2, &same);
        if (same) {
            fprintf(stderr, "Images are identical\n");
            pixd = pixCreateTemplate(pixs1);  /* write empty pix for diff */
        }
        else {
            if (type == 0)
                comptype = L_COMPARE_XOR;
            else
                comptype = L_COMPARE_SUBTRACT;
            pixCompareBinary(pixs1, pixs2, comptype, &fract, &pixd);
            fprintf(stderr, "Fraction of different pixels: %10.6f\n", fract);
        }
        pixWrite(fileout, pixd, IFF_PNG);
    }
    else {
        if (type == 0)
            comptype = L_COMPARE_ABS_DIFF;
        else
            comptype = L_COMPARE_SUBTRACT;
        pixCompareGrayOrRGB(pixs1, pixs2, comptype, GPLOT_X11, &same, &diff,
                            &rmsdiff, &pixd);
        if (type == 0) {
            if (same)
                fprintf(stderr, "Images are identical\n");
            else {
                fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff);
                fprintf(stderr, "               <rmsdiff> = %10.6f\n", rmsdiff);
            }
        }
        else {  /* subtraction */
            if (same)
                fprintf(stderr, "pixs2 strictly greater than pixs1\n");
            else {
                fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff);
                fprintf(stderr, "               <rmsdiff> = %10.6f\n", rmsdiff);
            }
        }
        if (d1 != 16)
            pixWrite(fileout, pixd, IFF_JFIF_JPEG);
        else
            pixWrite(fileout, pixd, IFF_PNG);

        if (d1 != 16 && !same) {
            na1 = pixCompareRankDifference(pixs1, pixs2, 1);
            if (na1) {
                fprintf(stderr, "na1[150] = %20.10f\n", na1->array[150]);
                fprintf(stderr, "na1[200] = %20.10f\n", na1->array[200]);
                fprintf(stderr, "na1[250] = %20.10f\n", na1->array[250]);
                numaGetNonzeroRange(na1, 0.00005, &first, &last);
                fprintf(stderr, "Nonzero diff range: first = %d, last = %d\n",
                        first, last);
                na2 = numaClipToInterval(na1, first, last);
                gplot = gplotCreate("/tmp/junkrank", GPLOT_X11,
                                    "Pixel Rank Difference", "pixel val",
                                    "rank");
                gplotAddPlot(gplot, NULL, na2, GPLOT_LINES, "rank");
                gplotMakeOutput(gplot);
                gplotDestroy(&gplot);
                numaDestroy(&na1);
                numaDestroy(&na2);
            }
        }
    }

    pixDestroy(&pixs1);
    pixDestroy(&pixs2);
    pixDestroy(&pixd);
    return 0;
}