Leptonica 1.68
C Image Processing Library
|
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