l_int32 main(int    argc,
             char **argv)
{
l_float32     dist, distr, distg, distb;
NUMA         *na1, *na2;
PIX          *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

        /* Test earthmover distance: extreme DC */
    fprintf(stderr, "Test earthmover distance\n");
    na1 = numaMakeConstant(0, 201);
    na2 = numaMakeConstant(0, 201);
    numaSetValue(na1, 0, 100);
    numaSetValue(na2, 200, 100);
    numaEarthMoverDistance(na1, na2, &dist);
    regTestCompareValues(rp, 200.0, dist, 0.0001);  /* 0 */
    numaDestroy(&na1);
    numaDestroy(&na2);

        /* Test connected component labelling */
    fprintf(stderr, "Test c.c. labelling\n");
    pix1 = pixRead("feyn-fract.tif");
    pix2 = pixConnCompTransform(pix1, 8, 8);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display);
    pix3 = pixConnCompTransform(pix1, 8, 16);
    pix4 = pixConvert16To8(pix3, L_LS_BYTE);
    regTestCompareSimilarPix(rp, pix2, pix4, 3, 0.001, 0);  /* 2 */
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);

        /* Test connected component area labelling */
    fprintf(stderr, "Test c.c. area labelling\n");
    pix2 = pixConnCompAreaTransform(pix1, 8);
    pix3 = pixConvert16To8(pix2, L_CLIP_TO_255);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pix3, 0, 350, NULL, rp->display);
    pixMultConstantGray(pix2, 0.3);
    pix4 = pixConvert16To8(pix2, L_LS_BYTE);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pix4, 0, 700, NULL, rp->display);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);

        /* Test color transform: 4-fold symmetry */
    fprintf(stderr, "Test color transform: 4-fold symmetry\n");
    pix1 = pixRead("form1.tif");
    pix2 = pixRotateOrth(pix1, 1);
    pix3 = pixRotateOrth(pix1, 2);
    pix4 = pixRotateOrth(pix1, 3);
    pix5 = pixLocToColorTransform(pix1);
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 5 */
    pix6 = pixLocToColorTransform(pix2);
    regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 6 */
    FindEMD(pix5, pix6, &distr, &distg, &distb);
    regTestCompareValues(rp, 0.12, distr, 0.01);  /* 7 */
    regTestCompareValues(rp, 0.00, distg, 0.01);  /* 8 */
    regTestCompareValues(rp, 0.00, distb, 0.01);  /* 9 */
    fprintf(stderr, "90 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix6);
    pix6 = pixLocToColorTransform(pix3);
    regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 10 */
    FindEMD(pix5, pix6, &distr, &distg, &distb);
    regTestCompareValues(rp, 0.12, distr, 0.01);  /* 11 */
    regTestCompareValues(rp, 0.09, distg, 0.01);  /* 12 */
    regTestCompareValues(rp, 0.00, distb, 0.01);  /* 13 */
    fprintf(stderr, "180 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix6);
    pix6 = pixLocToColorTransform(pix4);
    regTestWritePixAndCheck(rp, pix6, IFF_PNG);  /* 14 */
    FindEMD(pix5, pix6, &distr, &distg, &distb);
    regTestCompareValues(rp, 0.00, distr, 0.01);  /* 15 */
    regTestCompareValues(rp, 0.09, distg, 0.01);  /* 16 */
    regTestCompareValues(rp, 0.00, distb, 0.01);  /* 17 */
    fprintf(stderr, "270 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);

        /* Test color transform: same form with translation */
    fprintf(stderr, "Test color transform with translation\n");
    pix1 = pixRead("form1.tif");
    pix2 = pixLocToColorTransform(pix1);
    pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display);
    pixTranslate(pix1, pix1, 10, 10, L_BRING_IN_WHITE);
    pix3 = pixLocToColorTransform(pix1);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 18 */
    pixDisplayWithTitle(pix3, 470, 0, NULL, rp->display);
    FindEMD(pix2, pix3, &distr, &distg, &distb);
    regTestCompareValues(rp, 1.76, distr, 0.01);  /* 19 */
    regTestCompareValues(rp, 2.65, distg, 0.01);  /* 20 */
    regTestCompareValues(rp, 2.03, distb, 0.01);  /* 21 */
    fprintf(stderr, "Translation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

        /* Test color transform: same form with small rotation */
    fprintf(stderr, "Test color transform with small rotation\n");
    pix1 = pixRead("form1.tif");
    pix2 = pixLocToColorTransform(pix1);
    pixRotateShearCenterIP(pix1, 0.1, L_BRING_IN_WHITE);
    pix3 = pixLocToColorTransform(pix1);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 22 */
    pixDisplayWithTitle(pix3, 880, 0, NULL, rp->display);
    FindEMD(pix2, pix3, &distr, &distg, &distb);
    regTestCompareValues(rp, 1.50, distr, 0.01);  /* 23 */
    regTestCompareValues(rp, 1.71, distg, 0.01);  /* 24 */
    regTestCompareValues(rp, 1.42, distb, 0.01);  /* 25 */
    fprintf(stderr, "Rotation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

        /* Test color transform: 2 different forms */
    fprintf(stderr, "Test color transform (2 forms)\n");
    pix1 = pixRead("form1.tif");
    pix2 = pixLocToColorTransform(pix1);
    pixDisplayWithTitle(pix2, 0, 600, NULL, rp->display);
    pix3 = pixRead("form2.tif");
    pix4 = pixLocToColorTransform(pix3);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 25 */
    pixDisplayWithTitle(pix4, 470, 600, NULL, rp->display);
    FindEMD(pix2, pix4, &distr, &distg, &distb);
    regTestCompareValues(rp, 6.10, distr, 0.02);  /* 27 */
    regTestCompareValues(rp, 11.13, distg, 0.01);  /* 28 */
    regTestCompareValues(rp, 10.53, distb, 0.01);  /* 29 */
    fprintf(stderr, "Different forms: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n",
            distr, distg, distb);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);

    return regTestCleanup(rp);
}
Exemple #2
0
/*!
 *  pixLocToColorTransform()
 *
 *      Input:   pixs (1 bpp)
 *      Return:  pixd (32 bpp rgb), or null on error
 *
 *  Notes:
 *      (1) This generates an RGB image where each component value
 *          is coded depending on the (x.y) location and the size
 *          of the fg connected component that the pixel in pixs belongs to.
 *          It is independent of the 4-fold orthogonal orientation, and
 *          only weakly depends on translations and small angle rotations.
 *          Background pixels are black.
 *      (2) Such encodings can be compared between two 1 bpp images
 *          by performing this transform and calculating the
 *          "earth-mover" distance on the resulting R,G,B histograms.
 */
PIX *
pixLocToColorTransform(PIX  *pixs)
{
l_int32    w, h, w2, h2, wpls, wplr, wplg, wplb, wplcc, i, j, rval, gval, bval;
l_float32  invw2, invh2;
l_uint32  *datas, *datar, *datag, *datab, *datacc;
l_uint32  *lines, *liner, *lineg, *lineb, *linecc;
PIX       *pix1, *pixcc, *pixr, *pixg, *pixb, *pixd;

    PROCNAME("pixLocToColorTransform");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);

        /* Label each pixel with the area of the c.c. to which it belongs.
         * Clip the result to 255 in an 8 bpp pix. This is used for
         * the blue component of pixd.  */
    pixGetDimensions(pixs, &w, &h, NULL);
    w2 = w / 2;
    h2 = h / 2;
    invw2 = 255.0 / (l_float32)w2;
    invh2 = 255.0 / (l_float32)h2;
    pix1 = pixConnCompAreaTransform(pixs, 8);
    pixcc = pixConvert16To8(pix1, L_CLIP_TO_255);
    pixDestroy(&pix1);

        /* Label the red and green components depending on the location
         * of the fg pixels, in a way that is 4-fold rotationally invariant. */
    pixr = pixCreate(w, h, 8);
    pixg = pixCreate(w, h, 8);
    pixb = pixCreate(w, h, 8);
    wpls = pixGetWpl(pixs);
    wplr = pixGetWpl(pixr);
    wplg = pixGetWpl(pixg);
    wplb = pixGetWpl(pixb);
    wplcc = pixGetWpl(pixcc);
    datas = pixGetData(pixs);
    datar = pixGetData(pixr);
    datag = pixGetData(pixg);
    datab = pixGetData(pixb);
    datacc = pixGetData(pixcc);
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        liner = datar + i * wplr;
        lineg = datag + i * wplg;
        lineb = datab + i * wplb;
        linecc = datacc+ i * wplcc;
        for (j = 0; j < w; j++) {
            if (GET_DATA_BIT(lines, j) == 0) continue;
            if (w < h) {
                rval = invh2 * L_ABS((l_float32)(i - h2));
                gval = invw2 * L_ABS((l_float32)(j - w2));
            } else {
                rval = invw2 * L_ABS((l_float32)(j - w2));
                gval = invh2 * L_ABS((l_float32)(i - h2));
            }
            bval = GET_DATA_BYTE(linecc, j);
            SET_DATA_BYTE(liner, j, rval);
            SET_DATA_BYTE(lineg, j, gval);
            SET_DATA_BYTE(lineb, j, bval);
        }
    }
    pixd = pixCreateRGBImage(pixr, pixg, pixb);

    pixDestroy(&pixcc);
    pixDestroy(&pixr);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    return pixd;
}