Leptonica 1.68
C Image Processing Library

affine_reg.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  * affine_reg.c
00018  *
00019  */
00020 
00021 #include "allheaders.h"
00022 
00023 static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad);
00024 l_int32 RenderHashedBoxa(PIX *pixt, BOXA *boxa, l_int32 i);
00025 
00026 
00027     /* Sample values.
00028      *    1-3: invertability tests
00029      *    4: comparison between sampling and sequential
00030      *    5: test with large distortion
00031      */
00032 static const l_int32  x1[] =  { 300,  300,  300,  95,    32};
00033 static const l_int32  y1[] =  {1200, 1200, 1250, 2821,  934};
00034 static const l_int32  x2[] =  {1200, 1200, 1125, 1432,  487};
00035 static const l_int32  y2[] =  {1100, 1100, 1100, 2682,  934};
00036 static const l_int32  x3[] =  { 200,  200,  200,  232,   32};
00037 static const l_int32  y3[] =  { 200,  200,  200,  657,   67};
00038 
00039 static const l_int32  xp1[] = { 500,  300,  350,  117,   32};
00040 static const l_int32  yp1[] = {1700, 1400, 1400, 2629,  934};
00041 static const l_int32  xp2[] = {850, 1400, 1400, 1464,  487};
00042 static const l_int32  yp2[] = {850, 1500, 1500, 2432,  804};
00043 static const l_int32  xp3[] = { 450,  200,  400,  183,   61};
00044 static const l_int32  yp3[] = { 300,  300,  400,  490,   83};
00045 
00046 static const l_int32  SHIFTX = 44;
00047 static const l_int32  SHIFTY = 39;
00048 static const l_float32  SCALEX = 0.83;
00049 static const l_float32  SCALEY = 0.78;
00050 static const l_float32  ROTATION = 0.11;   /* radian */
00051 
00052 #define   ADDED_BORDER_PIXELS       1000
00053 #define   ALL     0
00054 
00055 
00056 main(int    argc,
00057      char **argv)
00058 {
00059 char         bufname[256];
00060 l_int32      i, j, w, h, d, x, y, wpls;
00061 l_uint32    *datas, *lines;
00062 l_float32   *vc;
00063 l_float32   *mat1, *mat2, *mat3, *mat1i, *mat2i, *mat3i, *matdinv;
00064 l_float32    matd[9], matdi[9];
00065 BOXA        *boxa, *boxa2;
00066 PIX         *pix, *pixs, *pixb, *pixg, *pixc, *pixcs;
00067 PIX         *pixd, *pixt1, *pixt2, *pixt3;
00068 PIXA        *pixa;
00069 PTA         *ptas, *ptad;
00070 static char  mainName[] = "affine_reg";
00071 
00072     if (argc != 1)
00073         exit(ERROR_INT(" Syntax:  affine_reg", mainName, 1));
00074 
00075     if ((pixs = pixRead("feyn.tif")) == NULL)
00076         exit(ERROR_INT("pixs not made", mainName, 1));
00077 
00078 #if ALL
00079         /* Test invertability of sequential. */
00080     pixa = pixaCreate(0);
00081     for (i = 0; i < 3; i++) {
00082         pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0);
00083         MakePtas(i, &ptas, &ptad);
00084         pixt1 = pixAffineSequential(pixb, ptad, ptas, 0, 0);
00085         pixSaveTiled(pixt1, pixa, 3, 1, 20, 8);
00086         pixt2 = pixAffineSequential(pixt1, ptas, ptad, 0, 0);
00087         pixSaveTiled(pixt2, pixa, 3, 0, 20, 0);
00088         pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
00089         pixXor(pixd, pixd, pixs);
00090         pixSaveTiled(pixd, pixa, 3, 0, 20, 0);
00091         sprintf(bufname, "/tmp/junkseq%d.png", i);
00092         pixWrite(bufname, pixd, IFF_PNG);
00093         pixDestroy(&pixb);
00094         pixDestroy(&pixt1);
00095         pixDestroy(&pixt2);
00096         pixDestroy(&pixd);
00097         ptaDestroy(&ptas);
00098         ptaDestroy(&ptad);
00099     }
00100 
00101     pixt1 = pixaDisplay(pixa, 0, 0);
00102     pixWrite("/tmp/junkaffine1.png", pixt1, IFF_PNG);
00103     pixDisplay(pixt1, 100, 100);
00104     pixDestroy(&pixt1);
00105     pixaDestroy(&pixa);
00106 #endif
00107 
00108 #if ALL 
00109         /* Test invertability of sampling */
00110     pixa = pixaCreate(0);
00111     for (i = 0; i < 3; i++) {
00112         pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0);
00113         MakePtas(i, &ptas, &ptad);
00114         pixt1 = pixAffineSampledPta(pixb, ptad, ptas, L_BRING_IN_WHITE);
00115         pixSaveTiled(pixt1, pixa, 3, 1, 20, 8);
00116         pixt2 = pixAffineSampledPta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
00117         pixSaveTiled(pixt2, pixa, 3, 0, 20, 0);
00118         pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
00119         pixXor(pixd, pixd, pixs);
00120         pixSaveTiled(pixd, pixa, 3, 0, 20, 0);
00121         if (i == 0) pixWrite("/tmp/junksamp.png", pixt1, IFF_PNG);
00122         pixDestroy(&pixb);
00123         pixDestroy(&pixt1);
00124         pixDestroy(&pixt2);
00125         pixDestroy(&pixd);
00126         ptaDestroy(&ptas);
00127         ptaDestroy(&ptad);
00128     }
00129 
00130     pixt1 = pixaDisplay(pixa, 0, 0);
00131     pixWrite("/tmp/junkaffine2.png", pixt1, IFF_PNG);
00132     pixDisplay(pixt1, 100, 300);
00133     pixDestroy(&pixt1);
00134     pixaDestroy(&pixa);
00135 #endif
00136 
00137 #if ALL
00138         /* Test invertability of interpolation on grayscale */
00139     pixa = pixaCreate(0);
00140     pixg = pixScaleToGray3(pixs);
00141     for (i = 0; i < 3; i++) {
00142         pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS / 3, 255);
00143         MakePtas(i, &ptas, &ptad);
00144         pixt1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE);
00145         pixSaveTiled(pixt1, pixa, 1, 1, 20, 8);
00146         pixt2 = pixAffinePta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
00147         pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
00148         pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS / 3);
00149         pixXor(pixd, pixd, pixg);
00150         pixSaveTiled(pixd, pixa, 1, 0, 20, 0);
00151         if (i == 0) pixWrite("/tmp/junkinterp.png", pixt1, IFF_PNG);
00152         pixDestroy(&pixb);
00153         pixDestroy(&pixt1);
00154         pixDestroy(&pixt2);
00155         pixDestroy(&pixd);
00156         ptaDestroy(&ptas);
00157         ptaDestroy(&ptad);
00158     }
00159 
00160     pixt1 = pixaDisplay(pixa, 0, 0);
00161     pixWrite("/tmp/junkaffine3.png", pixt1, IFF_PNG);
00162     pixDisplay(pixt1, 100, 500);
00163     pixDestroy(&pixt1);
00164     pixaDestroy(&pixa);
00165     pixDestroy(&pixg);
00166 #endif
00167 
00168 #if ALL
00169         /* Test invertability of interpolation on color */
00170     pixa = pixaCreate(0);
00171     pixc = pixRead("test24.jpg");
00172     pixcs = pixScale(pixc, 0.3, 0.3);
00173     for (i = 0; i < 3; i++) {
00174         pixb = pixAddBorder(pixcs, ADDED_BORDER_PIXELS / 4, 0xffffff00);
00175         MakePtas(i, &ptas, &ptad);
00176         pixt1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE);
00177         pixSaveTiled(pixt1, pixa, 1, 1, 20, 32);
00178         pixt2 = pixAffinePta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
00179         pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
00180         pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS / 4);
00181         pixXor(pixd, pixd, pixcs);
00182         pixSaveTiled(pixd, pixa, 1, 0, 20, 0);
00183         pixDestroy(&pixb);
00184         pixDestroy(&pixt1);
00185         pixDestroy(&pixt2);
00186         pixDestroy(&pixd);
00187         ptaDestroy(&ptas);
00188         ptaDestroy(&ptad);
00189     }
00190 
00191     pixt1 = pixaDisplay(pixa, 0, 0);
00192     pixWrite("/tmp/junkaffine4.png", pixt1, IFF_PNG);
00193     pixDisplay(pixt1, 100, 500);
00194     pixDestroy(&pixt1);
00195     pixaDestroy(&pixa);
00196     pixDestroy(&pixc);
00197     pixDestroy(&pixcs);
00198 #endif
00199 
00200 #if ALL 
00201        /* Comparison between sequential and sampling */
00202     MakePtas(3, &ptas, &ptad);
00203     pixa = pixaCreate(0);
00204 
00205         /* Use sequential transforms */
00206     pixt1 = pixAffineSequential(pixs, ptas, ptad,
00207                      ADDED_BORDER_PIXELS, ADDED_BORDER_PIXELS);
00208     pixSaveTiled(pixt1, pixa, 2, 0, 20, 8);
00209 
00210         /* Use sampled transform */
00211     pixt2 = pixAffineSampledPta(pixs, ptas, ptad, L_BRING_IN_WHITE);
00212     pixSaveTiled(pixt2, pixa, 2, 0, 20, 8);
00213 
00214         /* Compare the results */
00215     pixXor(pixt2, pixt2, pixt1);
00216     pixSaveTiled(pixt2, pixa, 2, 0, 20, 8);
00217 
00218     pixd = pixaDisplay(pixa, 0, 0);
00219     pixWrite("/tmp/junkaffine5.png", pixd, IFF_PNG);
00220     pixDisplay(pixd, 100, 700);
00221     pixDestroy(&pixt1);
00222     pixDestroy(&pixt2);
00223     pixDestroy(&pixd);
00224     pixaDestroy(&pixa);
00225     ptaDestroy(&ptas);
00226     ptaDestroy(&ptad);
00227 #endif
00228 
00229 #if ALL 
00230        /* Get timings and test with large distortion */
00231     MakePtas(4, &ptas, &ptad);
00232     pixa = pixaCreate(0);
00233     pixg = pixScaleToGray3(pixs);
00234 
00235     startTimer();
00236     pixt1 = pixAffineSequential(pixg, ptas, ptad, 0, 0);
00237     fprintf(stderr, " Time for pixAffineSequentialPta(): %6.2f sec\n",
00238             stopTimer());
00239     pixSaveTiled(pixt1, pixa, 1, 1, 20, 8);
00240 
00241     startTimer();
00242     pixt2 = pixAffineSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE);
00243     fprintf(stderr, " Time for pixAffineSampledPta(): %6.2f sec\n", stopTimer());
00244     pixSaveTiled(pixt2, pixa, 1, 0, 20, 8);
00245 
00246     startTimer();
00247     pixt3 = pixAffinePta(pixg, ptas, ptad, L_BRING_IN_WHITE);
00248     fprintf(stderr, " Time for pixAffinePta(): %6.2f sec\n", stopTimer());
00249     pixSaveTiled(pixt3, pixa, 1, 0, 20, 8);
00250 
00251     pixXor(pixt1, pixt1, pixt2);
00252     pixSaveTiled(pixt1, pixa, 1, 1, 20, 8);
00253     pixXor(pixt2, pixt2, pixt3);
00254     pixSaveTiled(pixt2, pixa, 1, 0, 20, 8);
00255     pixDestroy(&pixt1);
00256     pixDestroy(&pixt2);
00257     pixDestroy(&pixt3);
00258 
00259     pixd = pixaDisplay(pixa, 0, 0);
00260     pixWrite("/tmp/junkaffine6.png", pixd, IFF_PNG);
00261     pixDisplay(pixd, 100, 900);
00262     pixDestroy(&pixd);
00263     pixDestroy(&pixg);
00264     pixaDestroy(&pixa);
00265     ptaDestroy(&ptas);
00266     ptaDestroy(&ptad);
00267 #endif
00268 
00269     pixDestroy(&pixs);
00270 
00271 #if 1
00272         /* Set up pix and boxa */
00273     pixa = pixaCreate(0);
00274     pix = pixRead("lucasta.1.300.tif");
00275     pixTranslate(pix, pix, 70, 0, L_BRING_IN_WHITE);
00276     pixt1 = pixCloseBrick(NULL, pix, 14, 5);
00277     pixOpenBrick(pixt1, pixt1, 1, 2);
00278     boxa = pixConnComp(pixt1, NULL, 8);
00279     pixs = pixConvertTo32(pix);
00280     pixGetDimensions(pixs, &w, &h, NULL);
00281     pixc = pixCopy(NULL, pixs);
00282     RenderHashedBoxa(pixc, boxa, 113);
00283     pixSaveTiled(pixc, pixa, 2, 1, 30, 32);
00284     pixDestroy(&pix);
00285     pixDestroy(&pixc);
00286     pixDestroy(&pixt1);
00287 
00288         /* Set up an affine transform in matd, and apply it to boxa */
00289     mat1 = createMatrix2dTranslate(SHIFTX, SHIFTY);
00290     mat2 = createMatrix2dScale(SCALEX, SCALEY);
00291     mat3 = createMatrix2dRotate(w / 2, h / 2, ROTATION);
00292     l_productMat3(mat3, mat2, mat1, matd, 3);
00293     boxa2 = boxaAffineTransform(boxa, matd);
00294 
00295         /* Set up the inverse transform in matdi */
00296     mat1i = createMatrix2dTranslate(-SHIFTX, -SHIFTY);
00297     mat2i = createMatrix2dScale(1.0/ SCALEX, 1.0 / SCALEY);
00298     mat3i = createMatrix2dRotate(w / 2, h / 2, -ROTATION);
00299     l_productMat3(mat1i, mat2i, mat3i, matdi, 3);
00300 
00301         /* Invert the original affine transform in matdinv */
00302     affineInvertXform(matd, &matdinv);
00303     fprintf(stderr, "Affine transform, applied to boxa\n");
00304     for (i = 0; i < 9; i++) {
00305         if (i && (i % 3 == 0))  fprintf(stderr, "\n");
00306         fprintf(stderr, " %7.3f ", matd[i]);
00307     }
00308     fprintf(stderr, "\nInverse transform, made by composing inverse parts");
00309     for (i = 0; i < 9; i++) {
00310         if (i % 3 == 0)  fprintf(stderr, "\n");
00311         fprintf(stderr, " %7.3f ", matdi[i]);
00312     }
00313     fprintf(stderr, "\nInverse transform, made by inverting the affine xform");
00314     for (i = 0; i < 6; i++) {
00315         if (i % 3 == 0)  fprintf(stderr, "\n");
00316         fprintf(stderr, " %7.3f ", matdinv[i]);
00317     }
00318     fprintf(stderr, "\n");
00319 
00320         /* Apply the inverted affine transform pixs */
00321     pixd = pixAffine(pixs, matdinv, L_BRING_IN_WHITE);
00322     RenderHashedBoxa(pixd, boxa2, 513);
00323     pixSaveTiled(pixd, pixa, 2, 0, 30, 32);
00324     pixDestroy(&pixd);
00325 
00326     pixd = pixaDisplay(pixa, 0, 0);
00327     pixWrite("/tmp/junkaffine7.png", pixd, IFF_PNG);
00328     pixDisplay(pixd, 100, 900);
00329     pixDestroy(&pixd);
00330     pixDestroy(&pixs);
00331     pixaDestroy(&pixa);
00332     boxaDestroy(&boxa);
00333     boxaDestroy(&boxa2);
00334     lept_free(mat1);
00335     lept_free(mat2);
00336     lept_free(mat3);
00337     lept_free(mat1i);
00338     lept_free(mat2i);
00339     lept_free(mat3i);
00340 #endif
00341 
00342     return 0;
00343 }
00344 
00345 static void
00346 MakePtas(l_int32  i,
00347          PTA    **pptas,
00348          PTA    **pptad)
00349 {
00350 
00351     *pptas = ptaCreate(3);
00352     ptaAddPt(*pptas, x1[i], y1[i]);
00353     ptaAddPt(*pptas, x2[i], y2[i]);
00354     ptaAddPt(*pptas, x3[i], y3[i]);
00355     *pptad = ptaCreate(3);
00356     ptaAddPt(*pptad, xp1[i], yp1[i]);
00357     ptaAddPt(*pptad, xp2[i], yp2[i]);
00358     ptaAddPt(*pptad, xp3[i], yp3[i]);
00359     return;
00360 }
00361 
00362 
00363 l_int32
00364 RenderHashedBoxa(PIX    *pixt,
00365                  BOXA   *boxa,
00366                  l_int32 i)
00367 {
00368 l_int32  j, n, rval, gval, bval;
00369 BOX     *box;
00370 
00371     n = boxaGetCount(boxa);
00372     rval = (1413 * i) % 256;
00373     gval = (4917 * i) % 256;
00374     bval = (7341 * i) % 256;
00375     for (j = 0; j < n; j++) {
00376         box = boxaGetBox(boxa, j, L_CLONE);
00377         pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval);
00378         boxDestroy(&box);
00379     }
00380     return 0;
00381 }
00382 
00383 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines