Ejemplo n.º 1
0
jint Java_com_googlecode_leptonica_android_Rotate_nativeRotate(JNIEnv *env, jclass clazz,
                                                               jint nativePix, jfloat degrees,
                                                               jboolean quality) {
  PIX *pixd;
  PIX *pixs = (PIX *) nativePix;

  l_float32 deg2rad = 3.1415926535 / 180.0;
  l_float32 radians = degrees * deg2rad;
  l_int32 w, h, bpp, type;

  pixGetDimensions(pixs, &w, &h, &bpp);

  if (bpp == 1 && quality == JNI_TRUE) {
    pixd = pixRotateBinaryNice(pixs, radians, L_BRING_IN_WHITE);
  } else {
    type = quality == JNI_TRUE ? L_ROTATE_AREA_MAP : L_ROTATE_SAMPLING;
    pixd = pixRotate(pixs, radians, type, L_BRING_IN_WHITE, 0, 0);
  }

  return (jint) pixd;
}
Ejemplo n.º 2
0
int main(int argc,
         char **argv) {
    l_int32 w, h, wd, hd;
    l_float32 deg2rad, angle, conf;
    PIX *pixs, *pixb1, *pixb2, *pixr, *pixf, *pixd, *pixc;
    PIXA *pixa;
    L_REGPARAMS *rp;

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

    deg2rad = 3.1415926535 / 180.;

    pixa = pixaCreate(0);
    pixs = pixRead("feyn.tif");
    pixSetOrClearBorder(pixs, 100, 250, 100, 0, PIX_CLR);
    pixb1 = pixReduceRankBinaryCascade(pixs, 2, 2, 0, 0);
    regTestWritePixAndCheck(rp, pixb1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixb1, 0, 100, NULL, rp->display);

    /* Add a border and locate and deskew a 40 degree rotation */
    pixb2 = pixAddBorder(pixb1, BORDER, 0);
    pixGetDimensions(pixb2, &w, &h, NULL);
    pixSaveTiled(pixb2, pixa, 0.5, 1, 20, 8);
    pixr = pixRotateBySampling(pixb2, w / 2, h / 2,
                               deg2rad * 40., L_BRING_IN_WHITE);
    regTestWritePixAndCheck(rp, pixr, IFF_PNG);  /* 1 */
    pixSaveTiled(pixr, pixa, 0.5, 0, 20, 0);
    pixFindSkewSweepAndSearchScorePivot(pixr, &angle, &conf, NULL, 1, 1,
                                        0.0, 45.0, 2.0, 0.03,
                                        L_SHEAR_ABOUT_CENTER);
    fprintf(stderr, "Should be 40 degrees: angle = %7.3f, conf = %7.3f\n",
            angle, conf);
    pixf = pixRotateBySampling(pixr, w / 2, h / 2,
                               deg2rad * angle, L_BRING_IN_WHITE);
    pixd = pixRemoveBorder(pixf, BORDER);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 2 */
    pixSaveTiled(pixd, pixa, 0.5, 0, 20, 0);
    pixDestroy(&pixr);
    pixDestroy(&pixf);
    pixDestroy(&pixd);

    /* Do a rotation larger than 90 degrees using embedding;
     * Use 2 sets of measurements at 90 degrees to scan the
     * full range of possible rotation angles. */
    pixGetDimensions(pixb1, &w, &h, NULL);
    pixr = pixRotate(pixb1, deg2rad * 37., L_ROTATE_SAMPLING,
                     L_BRING_IN_WHITE, w, h);
    regTestWritePixAndCheck(rp, pixr, IFF_PNG);  /* 3 */
    pixSaveTiled(pixr, pixa, 0.5, 1, 20, 0);
    startTimer();
    pixFindSkewOrthogonalRange(pixr, &angle, &conf, 2, 1,
                               47.0, 1.0, 0.03, 0.0);
    fprintf(stderr, "Orth search time: %7.3f sec\n", stopTimer());
    fprintf(stderr, "Should be about -128 degrees: angle = %7.3f\n", angle);
    pixd = pixRotate(pixr, deg2rad * angle, L_ROTATE_SAMPLING,
                     L_BRING_IN_WHITE, w, h);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 4 */
    pixGetDimensions(pixd, &wd, &hd, NULL);
    pixc = pixCreate(w, h, 1);
    pixRasterop(pixc, 0, 0, w, h, PIX_SRC, pixd, (wd - w) / 2, (hd - h) / 2);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 5 */
    pixSaveTiled(pixc, pixa, 0.5, 0, 20, 0);
    pixDestroy(&pixr);
    pixDestroy(&pixf);
    pixDestroy(&pixd);
    pixDestroy(&pixc);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);

    pixDestroy(&pixs);
    pixDestroy(&pixb1);
    pixDestroy(&pixb2);
    pixaDestroy(&pixa);
    return regTestCleanup(rp);
}
Ejemplo n.º 3
0
int main(int    argc,
         char **argv)
{
l_int32       w, h, x, y, i, n;
l_float32    *vc;
PIX          *pix1, *pix2, *pix3, *pix4, *pix5;
PIXA         *pixas, *pixa;
L_REGPARAMS  *rp;

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

    pixas = pixaCreate(11);
    for (i = 0; i < 10; i++) {  /* this preserves any alpha */
        pix1 = pixRead(fnames[i]);
        pix2 = pixScaleBySamplingToSize(pix1, 250, 150);
        pixaAddPix(pixas, pix2, L_INSERT);
        pixDestroy(&pix1);
    }

        /* Add a transparent grid over the rgb image */
    pix1 = pixaGetPix(pixas, 8, L_COPY);
    pixGetDimensions(pix1, &w, &h, NULL);
    pix2 = pixCreate(w, h, 1);
    for (i = 0; i < 5; i++) {
        y = h * (i + 1) / 6;
        pixRenderLine(pix2, 0, y, w, y, 3, L_SET_PIXELS);
    }
    for (i = 0; i < 7; i++) {
        x = w * (i + 1) / 8;
        pixRenderLine(pix2, x, 0, x, h, 3, L_SET_PIXELS);
    }
    pix3 = pixConvertTo8(pix2, 0);  /* 1 --> 0 ==> transparent */
    pixSetRGBComponent(pix1, pix3, L_ALPHA_CHANNEL);
    pixaAddPix(pixas, pix1, L_INSERT);
    n = pixaGetCount(pixas);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

#if DO_ALL
        /* Display with and without removing alpha with white bg */
    pix1 = pixaDisplayTiledInRows(pixas, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRemoveAlpha(pix1);
        pixaAddPix(pixa, pix2, L_INSERT);
        pixDestroy(&pix1);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
         /* Setting to gray */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pixSetAllGray(pix1, 170);
        pix2 = pixRemoveAlpha(pix1);
        pixaAddPix(pixa, pix2, L_INSERT);
        pixDestroy(&pix1);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pix1, 400, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* General scaling */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixScaleToSize(pix1, 350, 650);
        pix3 = pixScaleToSize(pix2, 200, 200);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Scaling by sampling */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixScaleBySamplingToSize(pix1, 350, 650);
        pix3 = pixScaleBySamplingToSize(pix2, 200, 200);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(pix1, 0, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by 3-shear; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 7 */
    pixDisplayWithTitle(pix1, 200, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL 
        /* Rotation by 3-shear; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 8 */
    pixDisplayWithTitle(pix1, 400, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by 2-shear about the center */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pixGetDimensions(pix1, &w, &h, NULL);
        pix2 = pixRotate2Shear(pix1, w / 2, h / 2, 0.25, L_BRING_IN_WHITE);
        pix3 = pixRotate2Shear(pix2, w / 2, h / 2, -0.35, L_BRING_IN_WHITE);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 9 */
    pixDisplayWithTitle(pix1, 600, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by sampling; no embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 0, 0);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 0, 0);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 10 */
    pixDisplayWithTitle(pix1, 800, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by sampling; with embedding */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotate(pix1, 0.25, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 250, 150);
        pix3 = pixRotate(pix2, -0.35, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, 250, 150);
        pix4 = pixRemoveBorderToSize(pix3, 250, 150);
        pix5 = pixRemoveAlpha(pix4);
        pixaAddPix(pixa, pix5, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 11 */
    pixDisplayWithTitle(pix1, 1000, 400, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Rotation by area mapping at corner */
    pixa = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixRotateAMCorner(pix1, 0.25, L_BRING_IN_WHITE);
        pix3 = pixRotateAMCorner(pix2, -0.35, L_BRING_IN_WHITE);
        pix4 = pixRemoveAlpha(pix3);
        pixaAddPix(pixa, pix4, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixDestroy(&pix3);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
#endif

#if DO_ALL
        /* Affine transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate3PtTransformVector();
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixAffine(pix1, vc, L_BRING_IN_WHITE);
/*        pix2 = pixAffineSampled(pix1, vc, L_BRING_IN_WHITE); */
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 13 */
    pixDisplayWithTitle(pix1, 200, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Projective transform by sampling */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(PROJECTIVE);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixProjectiveSampled(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 14 */
    pixDisplayWithTitle(pix1, 400, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Projective transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(PROJECTIVE);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixProjective(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 15 */
    pixDisplayWithTitle(pix1, 600, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

#if DO_ALL
        /* Bilinear transform by interpolation */
    pixa = pixaCreate(n);
    vc = Generate4PtTransformVector(BILINEAR);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixas, i, L_COPY);
        pix2 = pixBilinear(pix1, vc, L_BRING_IN_WHITE);
        pix3 = pixRemoveAlpha(pix2);
        pixaAddPix(pixa, pix3, L_INSERT);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }
    pix1 = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 25, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 16 */
    pixDisplayWithTitle(pix1, 800, 800, NULL, rp->display);
    pixDestroy(&pix1);
    pixaDestroy(&pixa);
    lept_free(vc);
#endif

    pixaDestroy(&pixas);
    return regTestCleanup(rp);
}
Ejemplo n.º 4
0
static void
RotateTest(PIX          *pixs,
           l_float32     scale,
           L_REGPARAMS  *rp)
{
l_int32   w, h, d, i, outformat;
PIX      *pixt, *pixd;
PIXA     *pixa;

    pixa = pixaCreate(0);
    pixGetDimensions(pixs, &w, &h, &d);
    outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG;
    pixd = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h);
    for (i = 1; i < NTIMES; i++) {
        if ((i % MODSIZE) == 0) {
            if (i == MODSIZE) {
                pixSaveTiled(pixd, pixa, scale, 1, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            } else {
                pixSaveTiled(pixd, pixa, scale, 0, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            }
        }
        pixt = pixRotate(pixd, ANGLE1, L_ROTATE_SHEAR,
                         L_BRING_IN_WHITE, w, h);
        pixDestroy(&pixd);
        pixd = pixt;
    }
    pixDestroy(&pixd);

    pixd = pixRotate(pixs, ANGLE1, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h);
    for (i = 1; i < NTIMES; i++) {
        if ((i % MODSIZE) == 0) {
            if (i == MODSIZE) {
                pixSaveTiled(pixd, pixa, scale, 1, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            } else {
                pixSaveTiled(pixd, pixa, scale, 0, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            }
        }
        pixt = pixRotate(pixd, ANGLE1, L_ROTATE_SAMPLING,
                         L_BRING_IN_WHITE, w, h);
        pixDestroy(&pixd);
        pixd = pixt;
    }
    pixDestroy(&pixd);

    pixd = pixRotate(pixs, ANGLE1, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h);
    for (i = 1; i < NTIMES; i++) {
        if ((i % MODSIZE) == 0) {
            if (i == MODSIZE) {
                pixSaveTiled(pixd, pixa, scale, 1, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            } else {
                pixSaveTiled(pixd, pixa, scale, 0, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            }
        }
        pixt = pixRotate(pixd, ANGLE1, L_ROTATE_AREA_MAP,
                         L_BRING_IN_WHITE, w, h);
        pixDestroy(&pixd);
        pixd = pixt;
    }
    pixDestroy(&pixd);

    pixd = pixRotateAMCorner(pixs, ANGLE2, L_BRING_IN_WHITE);
    for (i = 1; i < NTIMES; i++) {
        if ((i % MODSIZE) == 0) {
            if (i == MODSIZE) {
                pixSaveTiled(pixd, pixa, scale, 1, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            } else {
                pixSaveTiled(pixd, pixa, scale, 0, 20, 32);
                regTestWritePixAndCheck(rp, pixd, outformat);
            }
        }
        pixt = pixRotateAMCorner(pixd, ANGLE2, L_BRING_IN_WHITE);
        pixDestroy(&pixd);
        pixd = pixt;
    }
    pixDestroy(&pixd);

    if (d == 32) {
        pixd = pixRotateAMColorFast(pixs, ANGLE1, 0xb0ffb000);
        for (i = 1; i < NTIMES; i++) {
            if ((i % MODSIZE) == 0) {
                if (i == MODSIZE) {
                    pixSaveTiled(pixd, pixa, scale, 1, 20, 32);
                    regTestWritePixAndCheck(rp, pixd, outformat);
                } else {
                    pixSaveTiled(pixd, pixa, scale, 0, 20, 32);
                    regTestWritePixAndCheck(rp, pixd, outformat);
                }
            }
            pixt = pixRotateAMColorFast(pixd, ANGLE1, 0xb0ffb000);
            pixDestroy(&pixd);
            pixd = pixt;
        }
    }
    pixDestroy(&pixd);

    pixd = pixaDisplay(pixa, 0, 0);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    return;
}
Ejemplo n.º 5
0
// Degrade the pix as if by a print/copy/scan cycle with exposure > 0
// corresponding to darkening on the copier and <0 lighter and 0 not copied.
// Exposures in [-2,2] are most useful, with -3 and 3 being extreme.
// If rotation is nullptr, rotation is skipped. If *rotation is non-zero, the
// pix
// is rotated by *rotation else it is randomly rotated and *rotation is
// modified.
//
// HOW IT WORKS:
// Most of the process is really dictated by the fact that the minimum
// available convolution is 3X3, which is too big really to simulate a
// good quality print/scan process. (2X2 would be better.)
// 1 pixel wide inputs are heavily smeared by the 3X3 convolution, making the
// images generally biased to being too light, so most of the work is to make
// them darker. 3 levels of thickening/darkening are achieved with 2 dilations,
// (using a greyscale erosion) one heavy (by being before convolution) and one
// light (after convolution).
// With no dilation, after covolution, the images are so light that a heavy
// constant offset is required to make the 0 image look reasonable. A simple
// constant offset multiple of exposure to undo this value is enough to achieve
// all the required lightening. This gives the advantage that exposure level 1
// with a single dilation gives a good impression of the broken-yet-too-dark
// problem that is often seen in scans.
// A small random rotation gives some varying greyscale values on the edges,
// and some random salt and pepper noise on top helps to realistically jaggy-up
// the edges.
// Finally a greyscale ramp provides a continuum of effects between exposure
// levels.
Pix* DegradeImage(Pix* input, int exposure, TRand* randomizer,
                  float* rotation) {
  Pix* pix = pixConvertTo8(input, false);
  pixDestroy(&input);
  input = pix;
  int width = pixGetWidth(input);
  int height = pixGetHeight(input);
  if (exposure >= 2) {
    // An erosion simulates the spreading darkening of a dark copy.
    // This is backwards to binary morphology,
    // see http://www.leptonica.com/grayscale-morphology.html
    pix = input;
    input = pixErodeGray(pix, 3, 3);
    pixDestroy(&pix);
  }
  // A convolution is essential to any mode as no scanner produces an
  // image as sharp as the electronic image.
  pix = pixBlockconv(input, 1, 1);
  pixDestroy(&input);
  // A small random rotation helps to make the edges jaggy in a realistic way.
  if (rotation != nullptr) {
    float radians_clockwise = 0.0f;
    if (*rotation) {
      radians_clockwise = *rotation;
    } else if (randomizer != nullptr) {
      radians_clockwise = randomizer->SignedRand(kRotationRange);
    }

    input = pixRotate(pix, radians_clockwise,
                      L_ROTATE_AREA_MAP, L_BRING_IN_WHITE,
                      0, 0);
    // Rotate the boxes to match.
    *rotation = radians_clockwise;
    pixDestroy(&pix);
  } else {
    input = pix;
  }

  if (exposure >= 3 || exposure == 1) {
    // Erosion after the convolution is not as heavy as before, so it is
    // good for level 1 and in addition as a level 3.
    // This is backwards to binary morphology,
    // see http://www.leptonica.com/grayscale-morphology.html
    pix = input;
    input = pixErodeGray(pix, 3, 3);
    pixDestroy(&pix);
  }
  // The convolution really needed to be 2x2 to be realistic enough, but
  // we only have 3x3, so we have to bias the image darker or lose thin
  // strokes.
  int erosion_offset = 0;
  // For light and 0 exposure, there is no dilation, so compensate for the
  // convolution with a big darkening bias which is undone for lighter
  // exposures.
  if (exposure <= 0)
    erosion_offset = -3 * kExposureFactor;
  // Add in a general offset of the greyscales for the exposure level so
  // a threshold of 128 gives a reasonable binary result.
  erosion_offset -= exposure * kExposureFactor;
  // Add a gradual fade over the page and a small amount of salt and pepper
  // noise to simulate noise in the sensor/paper fibres and varying
  // illumination.
  l_uint32* data = pixGetData(input);
  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x) {
      int pixel = GET_DATA_BYTE(data, x);
      if (randomizer != nullptr)
        pixel += randomizer->IntRand() % (kSaltnPepper*2 + 1) - kSaltnPepper;
      if (height + width > kMinRampSize)
        pixel -= (2*x + y) * 32 / (height + width);
      pixel += erosion_offset;
      if (pixel < 0)
        pixel = 0;
      if (pixel > 255)
        pixel = 255;
      SET_DATA_BYTE(data, x, pixel);
    }
    data += input->wpl;
  }
  return input;
}
Ejemplo n.º 6
0
int main(int    argc,
         char **argv)
{
char        *filein, *fileout;
l_int32      ret;
l_float32    deg2rad;
l_float32    angle, conf, score;
PIX         *pix, *pixs, *pixd;
static char  mainName[] = "skewtest";

    if (argc != 3)
        return ERROR_INT(" Syntax:  skewtest filein fileout", mainName, 1);
    filein = argv[1];
    fileout = argv[2];

    setLeptDebugOK(1);
    pixd = NULL;
    deg2rad = 3.1415926535 / 180.;

    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);

        /* Find the skew angle various ways */
    pix = pixConvertTo1(pixs, 130);
    pixWrite("/tmp/binarized.tif", pix, IFF_TIFF_G4);
    pixFindSkew(pix, &angle, &conf);
    fprintf(stderr, "pixFindSkew():\n"
                    "  conf = %5.3f, angle = %7.3f degrees\n", conf, angle);

    pixFindSkewSweepAndSearchScorePivot(pix, &angle, &conf, &score,
                                        SWEEP_REDUCTION2, SEARCH_REDUCTION,
                                        0.0, SWEEP_RANGE2, SWEEP_DELTA2,
                                        SEARCH_MIN_DELTA,
                                        L_SHEAR_ABOUT_CORNER);
    fprintf(stderr, "pixFind...Pivot(about corner):\n"
                    "  conf = %5.3f, angle = %7.3f degrees, score = %f\n",
            conf, angle, score);

    pixFindSkewSweepAndSearchScorePivot(pix, &angle, &conf, &score,
                                        SWEEP_REDUCTION2, SEARCH_REDUCTION,
                                        0.0, SWEEP_RANGE2, SWEEP_DELTA2,
                                        SEARCH_MIN_DELTA,
                                        L_SHEAR_ABOUT_CENTER);
    fprintf(stderr, "pixFind...Pivot(about center):\n"
                    "  conf = %5.3f, angle = %7.3f degrees, score = %f\n",
            conf, angle, score);

        /* Use top-level */
    pixd = pixDeskew(pixs, 0);
    pixWriteImpliedFormat(fileout, pixd, 0, 0);


#if 0
        /* Do it piecemeal; fails if outside the range */
    if (pixGetDepth(pixs) == 1) {
        pixd = pixDeskew(pix, DESKEW_REDUCTION);
        pixWrite(fileout, pixd, IFF_PNG);
    }
    else {
        ret = pixFindSkewSweepAndSearch(pix, &angle, &conf, SWEEP_REDUCTION2,
                                        SEARCH_REDUCTION, SWEEP_RANGE2,
                                        SWEEP_DELTA2, SEARCH_MIN_DELTA);
        if (ret)
            L_WARNING("skew angle not valid\n", mainName);
        else {
            fprintf(stderr, "conf = %5.3f, angle = %7.3f degrees\n",
                    conf, angle);
            if (conf > 2.5)
                pixd = pixRotate(pixs, angle * deg2rad, L_ROTATE_AREA_MAP,
                                 L_BRING_IN_WHITE, 0, 0);
            else
                pixd = pixClone(pixs);
            pixWrite(fileout, pixd, IFF_PNG);
            pixDestroy(&pixd);
        }
    }
#endif

    pixDestroy(&pixs);
    pixDestroy(&pix);
    pixDestroy(&pixd);
    return 0;
}
Ejemplo n.º 7
0
void
RotateTest(PIX          *pixs,
           l_int32       reduction,
           L_REGPARAMS  *rp)
{
l_int32   w, h, d, outformat;
PIX      *pixt1, *pixt2, *pixt3, *pixd;
PIXA     *pixa;

    pixGetDimensions(pixs, &w, &h, &d);
    outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG;

    pixa = pixaCreate(0);
    pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 32);
    pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, outformat);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    pixa = pixaCreate(0);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 32);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0);
    pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

    if (pixGetDepth(pixs) == 1)
        pixt1 = pixScaleToGray2(pixs);
    else
        pixt1 = pixClone(pixs);
    pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h);
    pixSaveTiled(pixt2, pixa, reduction, 1, 20, 0);
    pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, w, h);
    pixSaveTiled(pixt3, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0);
    pixSaveTiled(pixt2, pixa, reduction, 1, 20, 0);
    pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, 0, 0);
    pixSaveTiled(pixt3, pixa, reduction, 0, 20, 0);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt1);
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, outformat);
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

    return;
}
Ejemplo n.º 8
0
int main(int argc,
         char **argv) {
    l_int32 i, w, h, d, rotflag;
    PIX *pixs, *pixt, *pixd;
    l_float32 angle, deg2rad, pops, ang;
    char *filein, *fileout;
    static char mainName[] = "rotatetest1";

    if (argc != 4)
        return ERROR_INT(" Syntax:  rotatetest1 filein angle fileout",
                         mainName, 1);

    filein = argv[1];
    angle = atof(argv[2]);
    fileout = argv[3];
    deg2rad = 3.1415926535 / 180.;

    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pix not made", mainName, 1);
    if (pixGetDepth(pixs) == 1) {
        pixt = pixScaleToGray3(pixs);
        pixDestroy(&pixs);
        pixs = pixAddBorderGeneral(pixt, 1, 0, 1, 0, 255);
        pixDestroy(&pixt);
    }

    pixGetDimensions(pixs, &w, &h, &d);
    fprintf(stderr, "w = %d, h = %d\n", w, h);

#if 0
    /* repertory of rotation operations to choose from */
pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE);
pixd = pixRotateAMColor(pixs, deg2rad * angle, 0xffffff00);
pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255);
pixd = pixRotateAMCorner(pixs, deg2rad * angle, L_BRING_IN_WHITE);
pixd = pixRotateShear(pixs, w /2, h / 2, deg2rad * angle,
                      L_BRING_IN_WHITE);
pixd = pixRotate3Shear(pixs, w /2, h / 2, deg2rad * angle,
                       L_BRING_IN_WHITE);
pixRotateShearIP(pixs, w / 2, h / 2, deg2rad * angle); pixd = pixs;
#endif

#if 0
    /* timing of shear rotation */
for (i = 0; i < NITERS; i++) {
    pixd = pixRotateShear(pixs, (i * w) / NITERS,
                          (i * h) / NITERS, deg2rad * angle,
                          L_BRING_IN_WHITE);
    pixDisplay(pixd, 100 + 20 * i, 100 + 20 * i);
    pixDestroy(&pixd);
}
#endif

#if 0
    /* timing of in-place shear rotation */
for (i = 0; i < NITERS; i++) {
    pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE);
/*        pixRotateShearCenterIP(pixs, deg2rad * angle, L_BRING_IN_WHITE); */
    pixDisplay(pixs, 100 + 20 * i, 100 + 20 * i);
}
pixd = pixs;
if (pixGetDepth(pixd) == 1)
    pixWrite(fileout, pixd, IFF_PNG);
else
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
pixDestroy(&pixs);
#endif

#if 0
    /* timing of various rotation operations (choose) */
startTimer();
w = pixGetWidth(pixs);
h = pixGetHeight(pixs);
for (i = 0; i < NTIMES; i++) {
    pixd = pixRotateShearCenter(pixs, deg2rad * angle, L_BRING_IN_WHITE);
    pixDestroy(&pixd);
}
pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer();
fprintf(stderr, "vers. 1, mpops: %f\n", pops);
startTimer();
w = pixGetWidth(pixs);
h = pixGetHeight(pixs);
for (i = 0; i < NTIMES; i++) {
    pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE);
}
pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer();
fprintf(stderr, "shear, mpops: %f\n", pops);
pixWrite(fileout, pixs, IFF_PNG);
for (i = 0; i < NTIMES; i++) {
    pixRotateShearIP(pixs, w/2, h/2, -deg2rad * angle, L_BRING_IN_WHITE);
}
pixWrite("/usr/tmp/junkout", pixs, IFF_PNG);
#endif

#if 0
    /* area-mapping rotation operations */
pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE);
/*    pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255); */
if (pixGetDepth(pixd) == 1)
    pixWrite(fileout, pixd, IFF_PNG);
else
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
#endif

#if 0
    /* compare the standard area-map color rotation with
     * the fast area-map color rotation, on a pixel basis */
{
PIX    *pix1, *pix2;
NUMA   *nar, *nag, *nab, *naseq;
GPLOT  *gplot;

startTimer();
pix1 = pixRotateAMColor(pixs, 0.12, 0xffffff00);
fprintf(stderr, " standard color rotate: %7.2f sec\n", stopTimer());
pixWrite("junkcolor1", pix1, IFF_JFIF_JPEG);
startTimer();
pix2 = pixRotateAMColorFast(pixs, 0.12, 0xffffff00);
fprintf(stderr, " fast color rotate: %7.2f sec\n", stopTimer());
pixWrite("junkcolor2", pix2, IFF_JFIF_JPEG);
pixd = pixAbsDifference(pix1, pix2);
pixGetColorHistogram(pixd, 1, &nar, &nag, &nab);
naseq = numaMakeSequence(0., 1., 256);
gplot = gplotCreate("junk_absdiff", GPLOT_X11, "Number vs diff",
                    "diff", "number");
gplotAddPlot(gplot, naseq, nar, GPLOT_POINTS, "red");
gplotAddPlot(gplot, naseq, nag, GPLOT_POINTS, "green");
gplotAddPlot(gplot, naseq, nab, GPLOT_POINTS, "blue");
gplotMakeOutput(gplot);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pixd);
numaDestroy(&nar);
numaDestroy(&nag);
numaDestroy(&nab);
numaDestroy(&naseq);
gplotDestroy(&gplot);
}
#endif

    /* Do a succession of 180 7-degree rotations in a cw
     * direction, and unwind the result with another set in
     * a ccw direction.  Although there is a considerable amount
     * of distortion after successive rotations, after all
     * 360 rotations, the resulting image is restored to
     * its original pristine condition! */
#if 1
    rotflag = L_ROTATE_AREA_MAP;
/*    rotflag = L_ROTATE_SHEAR;     */
/*    rotflag = L_ROTATE_SAMPLING;   */
    ang = 7.0 * deg2rad;
    pixGetDimensions(pixs, &w, &h, NULL);
    pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h);
    pixWrite("junkrot7", pixd, IFF_PNG);
    for (i = 1; i < 180; i++) {
        pixs = pixd;
        pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h);
        if ((i % 30) == 0) pixDisplay(pixd, 600, 0);
        pixDestroy(&pixs);
    }

    pixWrite("junkspin", pixd, IFF_PNG);
    pixDisplay(pixd, 0, 0);

    for (i = 0; i < 180; i++) {
        pixs = pixd;
        pixd = pixRotate(pixs, -ang, rotflag, L_BRING_IN_WHITE, w, h);
        if (i && (i % 30) == 0) pixDisplay(pixd, 600, 500);
        pixDestroy(&pixs);
    }

    pixWrite("junkunspin", pixd, IFF_PNG);
    pixDisplay(pixd, 0, 500);
    pixDestroy(&pixd);
#endif

    return 0;
}
int main(int    argc,
         char **argv)
{
l_int32      w, h, ystart, yend, y, ymax, ymid, i, window, sum1, sum2, rankx;
l_uint32     uval;
l_float32    ave, rankval, maxvar, variance, norm, conf, angle, radangle;
NUMA        *na1;
PIX         *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7;
PIXA        *pixa;
static char  mainName[] = "findbinding";

    if (argc != 1)
        return ERROR_INT(" Syntax:  findbinding", mainName, 1);

    lept_mkdir("lept/binding");
    pixa = pixaCreate(0);

    pix1 = pixRead("binding-example.45.jpg");
    pix2 = pixConvertTo8(pix1, 0);

        /* Find the skew angle */
    pix3 = pixConvertTo1(pix2, 150);
    pixFindSkewSweepAndSearch(pix3, &angle, &conf, 2, 2, 7.0, 1.0, 0.01);
    fprintf(stderr, "angle = %f, conf = %f\n", angle, conf);

        /* Deskew, bringing in black pixels at the edges */
    if (L_ABS(angle) < 0.1 || conf < 1.5) {
        pix4 = pixClone(pix2);
    } else {
        radangle = 3.1416 * angle / 180.0;
        pix4 = pixRotate(pix2, radangle, L_ROTATE_AREA_MAP,
                         L_BRING_IN_BLACK, 0, 0);
    }

        /* Rotate 90 degrees to make binding horizontal */
    pix5 = pixRotateOrth(pix4, 1);

        /* Sort pixels in each row by their gray value.
         * Dark pixels on the left, light ones on the right. */
    pix6 = pixRankRowTransform(pix5);
    pixDisplay(pix5, 0, 0);
    pixDisplay(pix6, 550, 0);
    pixaAddPix(pixa, pix4, L_COPY);
    pixaAddPix(pixa, pix5, L_COPY);
    pixaAddPix(pixa, pix6, L_COPY);

        /* Make an a priori estimate of the y-interval within which the
         * binding will be found.  The search will be done in this interval. */
    pixGetDimensions(pix6, &w, &h, NULL);
    ystart = 0.25 * h;
    yend = 0.75 * h;

        /* Choose a very light rank value; close to white, which
         * corresponds to a column in pix6 near the right side. */
    rankval = 0.98;
    rankx = (l_int32)(w * rankval);

        /* Investigate variance in a small window (vertical, size = 5)
         * of the pixels in that column.  These are the %rankval
         * pixels in each raster of pix6.  Find the y-location of
         * maximum variance. */
    window = 5;
    norm = 1.0 / window;
    maxvar = 0.0;
    na1 = numaCreate(0);
    numaSetParameters(na1, ystart, 1);
    for (y = ystart; y <= yend; y++) {
        sum1 = sum2 = 0;
        for (i = 0; i < window; i++) {
            pixGetPixel(pix6, rankx, y + i, &uval);
            sum1 += uval;
            sum2 += uval * uval;
        }
        ave = norm * sum1;
        variance = norm * sum2 - ave * ave;
        numaAddNumber(na1, variance);
        ymid = y + window / 2;
        if (variance > maxvar) {
            maxvar = variance;
            ymax = ymid;
        }
    }

        /* Plot the windowed variance as a function of the y-value
         * of the window location */
    fprintf(stderr, "maxvar = %f, ymax = %d\n", maxvar, ymax);
    gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/binding/root", NULL);
    pix7 = pixRead("/tmp/lept/binding/root.png");
    pixDisplay(pix7, 0, 800);
    pixaAddPix(pixa, pix7, L_COPY);

        /* Superimpose the variance plot over the image.
         * The variance peak is at the binding. */
    pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, w - 120, 100, 1,
                                                           0x0000ff00);
    pixDisplay(pix5, 1050, 0);
    pixaAddPix(pixa, pix5, L_COPY);

        /* Bundle the results up in a pdf */
    fprintf(stderr, "Writing pdf output file: /tmp/lept/binding/binding.pdf\n");
    pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Binding locator",
                     "/tmp/lept/binding/binding.pdf");

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixaDestroy(&pixa);
    numaDestroy(&na1);
    return 0;
}
Ejemplo n.º 10
0
/*!
 *  pixDeskewGeneral()
 *
 *      Input:  pixs  (any depth)
 *              redsweep  (for linear search: reduction factor = 1, 2 or 4;
 *                         use 0 for default)
 *              sweeprange (in degrees in each direction from 0;
 *                          use 0.0 for default)
 *              sweepdelta (in degrees; use 0.0 for default)
 *              redsearch  (for binary search: reduction factor = 1, 2 or 4;
 *                          use 0 for default;)
 *              thresh (for binarizing the image; use 0 for default)
 *              &angle   (<optional return> angle required to deskew,
 *                        in degrees; use NULL to skip)
 *              &conf    (<optional return> conf value is ratio
 *                        of max/min scores; use NULL to skip)
 *      Return: pixd (deskewed pix), or null on error
 *
 *  Notes:
 *      (1) This binarizes if necessary and finds the skew angle.  If the
 *          angle is large enough and there is sufficient confidence,
 *          it returns a deskewed image; otherwise, it returns a clone.
 */
PIX *
pixDeskewGeneral(PIX        *pixs,
                 l_int32     redsweep,
                 l_float32   sweeprange,
                 l_float32   sweepdelta,
                 l_int32     redsearch,
                 l_int32     thresh,
                 l_float32  *pangle,
                 l_float32  *pconf)
{
l_int32    ret, depth;
l_float32  angle, conf, deg2rad;
PIX       *pixb, *pixd;

    PROCNAME("pixDeskewGeneral");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (redsweep == 0)
        redsweep = DEFAULT_SWEEP_REDUCTION;
    else if (redsweep != 1 && redsweep != 2 && redsweep != 4)
        return (PIX *)ERROR_PTR("redsweep not in {1,2,4}", procName, NULL);
    if (sweeprange == 0.0)
        sweeprange = DEFAULT_SWEEP_RANGE;
    if (sweepdelta == 0.0)
        sweepdelta = DEFAULT_SWEEP_DELTA;
    if (redsearch == 0)
        redsearch = DEFAULT_BS_REDUCTION;
    else if (redsearch != 1 && redsearch != 2 && redsearch != 4)
        return (PIX *)ERROR_PTR("redsearch not in {1,2,4}", procName, NULL);
    if (thresh == 0)
        thresh = DEFAULT_BINARY_THRESHOLD;

    deg2rad = 3.1415926535 / 180.;

        /* Binarize if necessary */
    depth = pixGetDepth(pixs);
    if (depth == 1)
        pixb = pixClone(pixs);
    else
        pixb = pixConvertTo1(pixs, thresh);

        /* Use the 1 bpp image to find the skew */
    ret = pixFindSkewSweepAndSearch(pixb, &angle, &conf, redsweep, redsearch,
                                    sweeprange, sweepdelta,
                                    DEFAULT_MINBS_DELTA);
    pixDestroy(&pixb);
    if (pangle)
        *pangle = angle;
    if (pconf)
        *pconf = conf;
    if (ret)
        return pixClone(pixs);

    if (L_ABS(angle) < MIN_DESKEW_ANGLE || conf < MIN_ALLOWED_CONFIDENCE)
        return pixClone(pixs);

    if ((pixd = pixRotate(pixs, deg2rad * angle, L_ROTATE_AREA_MAP,
                          L_BRING_IN_WHITE, 0, 0)) == NULL)
        return pixClone(pixs);
    else
        return pixd;
}
Ejemplo n.º 11
0
//---------------------------------------------------------------------------
//Уменьшение в 2 раза
//Поиск угла
//Предварительное выпрямление
//Эрозия для удаления тонких линий
//Поиск box для обрезки белых полей изображения
//Обрезка предварительно выпрямленного изображения
//Получение трёх изображений:
//------------------------------------------------------------------------------
PIX* LeptPrepareFile::getClearImage(PIX *pix, l_float32 *angle, l_float32 *conf)
{
	PIX        *pixReduce2, *pixDeskew, *pixCrop, *pixErode;
	PIXA       *pixa1, *pixa2;
	l_int32	   result;
	l_float32  _angle, _conf;
	l_int32    XC_crop, YC_crop, XC_old, YC_old, XC_new, YC_new;


		LEP_LOG("enter");
	SetNULL(7, (void **)&pixReduce2, &pixDeskew, &pixCrop, &pixErode, &pixa1, &pixa2, &boxFirstCrop);
	SetNULL(2, (void **)angle, conf);
	try
	{
		LEP_STR_THROW(!pix, "Изображение не найдено");
		//Уменьшение в 2 раза для ускорения (при DPI = 600)
	if ((pix->xres == 600) && (pix->yres == 600))                 //В дальнейшем переработать потому как в текущем варианте обрабатывает корректно только DPI300 и DPI600
		pixReduce2 = pixReduceBinary2(pix, NULL);
	else
	{
		pixReduce2 = pixCreateTemplateNoInit(pix);
		LEP_STR_THROW(!pixReduce2, "Ошибка в pixReduceBinary2");

		pixCopy(pixReduce2, pix);
	}

		LEP_STR_THROW(!pixReduce2, "Ошибка в pixReduceBinary2");
		//Поиск угла наклона
	result = pixFindSkewSweepAndSearch(pixReduce2, &_angle, &_conf,
						4,    //линеное уменьшение,  DEFAULT_SWEEP_REDUCTION = 4
						2,    //бинарное уменьшение, DEFAULT_BS_REDUCTION = 2
						10,   //максимальный угол поиска
				    		0.1,  //дельта угла поиска
						0.01);//конечная дельта угла поиска, DEFAULT_MINBS_DELTA = 0.01
		LEP_STR_THROW(result != 0, "Ошибка поиска угла");
	if (angle) *angle = _angle;
	if (conf) *conf = _conf;
		//Предварительное выпрямление
	pixDeskew = pixRotate(pixReduce2, 3.1415926535 / 180. * _angle, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0);
		LEP_STR_THROW(!pixDeskew, "Ошибка при предварительном повороте изображения");
		//Эрозия для удаления тонких линий
	pixErode = pixCreateTemplateNoInit(pixDeskew);
		LEP_STR_THROW(!pixErode, "Ошибка в pixCreateTemplateNoInit");
	pixCopy(pixErode, pixDeskew);
	pixErodeBrick(pixErode, pixErode, 3, 3);
		//pixWrite("c:\\temp0_0.tif", pixErode, IFF_TIFF_ZIP);
		//Поиск box для обрезки белых полей изображения
	result = pixClipBoxToForeground(pixErode, NULL, NULL, &boxFirstCrop);
		LEP_STR_THROW(result != 0, "Ошибка при поиске обрезки изображения");
		//Получение точки вокруг которой происходило вращение, с учётом обрезки
		XC_old = pixErode->w / 2;      //точка вращения старого изображения на старом изображении
		YC_old = pixErode->h / 2;
		XC_new = boxFirstCrop->w / 2;       //точка вращения нового изображения на новом изображении
		YC_new = boxFirstCrop->h / 2;
		XC_crop = boxFirstCrop->x + XC_new; //точка вращения нового изображения на старом изображении
		YC_crop = boxFirstCrop->y + YC_new;
		centerXRotate = XC_new - (XC_crop - XC_old);   //точка вращения старого изображения на новом изображении
		centerYRotate = YC_new - (YC_crop - YC_old);
		//Обрезка предварительно выпрямленного изображения
	pixCrop = pixClipRectangle(pixDeskew, boxFirstCrop, NULL);
		LEP_STR_THROW(!pixCrop, "Ошибка при обрезке изображения");
		//pixWrite("c:\\pixCrop.tif", pixCrop, IFF_TIFF_ZIP);
	}catch (string error)
	{
		LEP_ERROR(error);
	};

	pixDestroy(&pixReduce2);
	pixDestroy(&pixDeskew);
	pixDestroy(&pixErode);
		LEP_LOG("exit");
	return pixCrop;

}
Ejemplo n.º 12
0
/*!
 *  pixRotateWithAlpha()
 *
 *      Input:  pixs (32 bpp rgb or cmapped)
 *              angle (radians; clockwise is positive)
 *              pixg (<optional> 8 bpp, can be null)
 *              fract (between 0.0 and 1.0, with 0.0 fully transparent
 *                     and 1.0 fully opaque)
 *      Return: pixd (32 bpp rgba), or null on error
 *
 *  Notes:
 *      (1) The alpha channel is transformed separately from pixs,
 *          and aligns with it, being fully transparent outside the
 *          boundary of the transformed pixs.  For pixels that are fully
 *          transparent, a blending function like pixBlendWithGrayMask()
 *          will give zero weight to corresponding pixels in pixs.
 *      (2) Rotation is about the center of the image; for very small
 *          rotations, just return a clone.  The dest is automatically
 *          expanded so that no image pixels are lost.
 *      (3) Rotation is by area mapping.  It doesn't matter what
 *          color is brought in because the alpha channel will
 *          be transparent (black) there.
 *      (4) If pixg is NULL, it is generated as an alpha layer that is
 *          partially opaque, using @fract.  Otherwise, it is cropped
 *          to pixs if required and @fract is ignored.  The alpha
 *          channel in pixs is never used.
 *      (4) Colormaps are removed to 32 bpp.
 *      (5) The default setting for the border values in the alpha channel
 *          is 0 (transparent) for the outermost ring of pixels and
 *          (0.5 * fract * 255) for the second ring.  When blended over
 *          a second image, this
 *          (a) shrinks the visible image to make a clean overlap edge
 *              with an image below, and
 *          (b) softens the edges by weakening the aliasing there.
 *          Use l_setAlphaMaskBorder() to change these values.
 *      (6) A subtle use of gamma correction is to remove gamma correction
 *          before rotation and restore it afterwards.  This is done
 *          by sandwiching this function between a gamma/inverse-gamma
 *          photometric transform:
 *              pixt = pixGammaTRCWithAlpha(NULL, pixs, 1.0 / gamma, 0, 255);
 *              pixd = pixRotateWithAlpha(pixt, angle, NULL, fract);
 *              pixGammaTRCWithAlpha(pixd, pixd, gamma, 0, 255);
 *              pixDestroy(&pixt);
 *          This has the side-effect of producing artifacts in the very
 *          dark regions.
 *
 *  *** Warning: implicit assumption about RGB component ordering ***
 */
PIX *
pixRotateWithAlpha(PIX *pixs,
                   l_float32 angle,
                   PIX *pixg,
                   l_float32 fract) {
    l_int32 ws, hs, d, spp;
    PIX *pixd, *pix32, *pixg2, *pixgr;

    PROCNAME("pixRotateWithAlpha");

    if (!pixs)
        return (PIX *) ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &ws, &hs, &d);
    if (d != 32 && pixGetColormap(pixs) == NULL)
        return (PIX *) ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
    if (pixg && pixGetDepth(pixg) != 8) {
        L_WARNING("pixg not 8 bpp; using @fract transparent alpha\n", procName);
        pixg = NULL;
    }
    if (!pixg && (fract < 0.0 || fract > 1.0)) {
        L_WARNING("invalid fract; using fully opaque\n", procName);
        fract = 1.0;
    }
    if (!pixg && fract == 0.0)
        L_WARNING("transparent alpha; image will not be blended\n", procName);

    /* Make sure input to rotation is 32 bpp rgb, and rotate it */
    if (d != 32)
        pix32 = pixConvertTo32(pixs);
    else
        pix32 = pixClone(pixs);
    spp = pixGetSpp(pix32);
    pixSetSpp(pix32, 3);  /* ignore the alpha channel for the rotation */
    pixd = pixRotate(pix32, angle, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, ws, hs);
    pixSetSpp(pix32, spp);  /* restore initial value in case it's a clone */
    pixDestroy(&pix32);

    /* Set up alpha layer with a fading border and rotate it */
    if (!pixg) {
        pixg2 = pixCreate(ws, hs, 8);
        if (fract == 1.0)
            pixSetAll(pixg2);
        else if (fract > 0.0)
            pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
    } else {
        pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
    }
    if (ws > 10 && hs > 10) {  /* see note 8 */
        pixSetBorderRingVal(pixg2, 1,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
        pixSetBorderRingVal(pixg2, 2,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));
    }
    pixgr = pixRotate(pixg2, angle, L_ROTATE_AREA_MAP,
                      L_BRING_IN_BLACK, ws, hs);

    /* Combine into a 4 spp result */
    pixSetRGBComponent(pixd, pixgr, L_ALPHA_CHANNEL);

    pixDestroy(&pixg2);
    pixDestroy(&pixgr);
    return pixd;
}