// Distorts anything that has a non-null pointer with the same pseudo-random // perspective distortion. Width and height only need to be set if there // is no pix. If there is a pix, then they will be taken from there. void GeneratePerspectiveDistortion(int width, int height, TRand* randomizer, Pix** pix, GenericVector<TBOX>* boxes) { if (pix != nullptr && *pix != nullptr) { width = pixGetWidth(*pix); height = pixGetHeight(*pix); } float* im_coeffs = nullptr; float* box_coeffs = nullptr; l_int32 incolor = ProjectiveCoeffs(width, height, randomizer, &im_coeffs, &box_coeffs); if (pix != nullptr && *pix != nullptr) { // Transform the image. Pix* transformed = pixProjective(*pix, im_coeffs, incolor); if (transformed == nullptr) { tprintf("Projective transformation failed!!\n"); return; } pixDestroy(pix); *pix = transformed; } if (boxes != nullptr) { // Transform the boxes. for (int b = 0; b < boxes->size(); ++b) { int x1, y1, x2, y2; const TBOX& box = (*boxes)[b]; projectiveXformSampledPt(box_coeffs, box.left(), height - box.top(), &x1, &y1); projectiveXformSampledPt(box_coeffs, box.right(), height - box.bottom(), &x2, &y2); TBOX new_box1(x1, height - y2, x2, height - y1); projectiveXformSampledPt(box_coeffs, box.left(), height - box.bottom(), &x1, &y1); projectiveXformSampledPt(box_coeffs, box.right(), height - box.top(), &x2, &y2); TBOX new_box2(x1, height - y1, x2, height - y2); (*boxes)[b] = new_box1.bounding_union(new_box2); } } free(im_coeffs); free(box_coeffs); }
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); }