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 * graymorph1_reg.c 00018 * 00019 * (1) Tests the interpreter for grayscale morphology, as 00020 * given in morphseq.c 00021 * 00022 * (2) Tests composite operations: tophat and hdome 00023 * 00024 * (3) Tests duality for grayscale erode/dilate, open/close, 00025 * and black/white tophat 00026 * 00027 * (4) Demonstrates closing plus white tophat. Note that this 00028 * combination of operations can be quite useful. 00029 * 00030 * (5) Demonstrates a method of doing contrast enhancement 00031 * by taking 3 * pixs and subtracting from this the 00032 * closing and opening of pixs. Do this both with the 00033 * basic pix accumulation functions and with the cleaner 00034 * Pixacc wrapper. Verify the results are equivalent. 00035 * 00036 * (6) Playing around: extract the feynman diagrams from 00037 * the stamp, using the tophat. 00038 * 00039 * For input, use e.g., aneurisms8.jpg 00040 */ 00041 00042 #include "allheaders.h" 00043 00044 #define WSIZE 7 00045 #define HSIZE 7 00046 #define BUF_SIZE 512 00047 #define HORIZ_SEP 0 /* set to 50 to display each image */ 00048 00049 00050 static void pixCompare(PIX *pix, PIX *pix2, const char *msg1, const char *msg2); 00051 00052 00053 main(int argc, 00054 char **argv) 00055 { 00056 char dilateseq[BUF_SIZE], erodeseq[BUF_SIZE]; 00057 char openseq[BUF_SIZE], closeseq[BUF_SIZE]; 00058 char wtophatseq[BUF_SIZE], btophatseq[BUF_SIZE]; 00059 char *filein; 00060 l_int32 w, h, d; 00061 PIX *pixs, *pixt, *pixt2, *pixt3, *pixt3a, *pixt4; 00062 PIX *pixg, *pixd, *pixd1, *pixd2, *pixd3; 00063 PIXACC *pacc; 00064 PIXCMAP *cmap; 00065 static char mainName[] = "graymorph1_reg"; 00066 00067 if (argc != 2) 00068 exit(ERROR_INT(" Syntax: graymorph1_reg filein", mainName, 1)); 00069 00070 filein = argv[1]; 00071 if ((pixs = pixRead(filein)) == NULL) 00072 exit(ERROR_INT("pixs not made", mainName, 1)); 00073 pixGetDimensions(pixs, &w, &h, &d); 00074 if (d != 8) 00075 exit(ERROR_INT("pixs not 8 bpp", mainName, 1)); 00076 00077 /* -------- Test gray morph, including interpreter ------------ */ 00078 pixd = pixDilateGray(pixs, WSIZE, HSIZE); 00079 sprintf(dilateseq, "D%d.%d", WSIZE, HSIZE); 00080 pixg = pixGrayMorphSequence(pixs, dilateseq, HORIZ_SEP, 0); 00081 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00082 pixDestroy(&pixg); 00083 pixDestroy(&pixd); 00084 00085 pixd = pixErodeGray(pixs, WSIZE, HSIZE); 00086 sprintf(erodeseq, "E%d.%d", WSIZE, HSIZE); 00087 pixg = pixGrayMorphSequence(pixs, erodeseq, HORIZ_SEP, 100); 00088 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00089 pixDestroy(&pixg); 00090 pixDestroy(&pixd); 00091 00092 pixd = pixOpenGray(pixs, WSIZE, HSIZE); 00093 sprintf(openseq, "O%d.%d", WSIZE, HSIZE); 00094 pixg = pixGrayMorphSequence(pixs, openseq, HORIZ_SEP, 200); 00095 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00096 pixDestroy(&pixg); 00097 pixDestroy(&pixd); 00098 00099 pixd = pixCloseGray(pixs, WSIZE, HSIZE); 00100 sprintf(closeseq, "C%d.%d", WSIZE, HSIZE); 00101 pixg = pixGrayMorphSequence(pixs, closeseq, HORIZ_SEP, 300); 00102 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00103 pixDestroy(&pixg); 00104 pixDestroy(&pixd); 00105 00106 pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); 00107 sprintf(wtophatseq, "Tw%d.%d", WSIZE, HSIZE); 00108 pixg = pixGrayMorphSequence(pixs, wtophatseq, HORIZ_SEP, 400); 00109 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00110 pixDestroy(&pixg); 00111 pixDestroy(&pixd); 00112 00113 pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK); 00114 sprintf(btophatseq, "Tb%d.%d", WSIZE, HSIZE); 00115 pixg = pixGrayMorphSequence(pixs, btophatseq, HORIZ_SEP, 500); 00116 pixCompare(pixd, pixg, "results are the same", "results are different" ); 00117 pixDestroy(&pixg); 00118 00119 /* ------------- Test erode/dilate duality -------------- */ 00120 pixd = pixDilateGray(pixs, WSIZE, HSIZE); 00121 pixInvert(pixs, pixs); 00122 pixd2 = pixErodeGray(pixs, WSIZE, HSIZE); 00123 pixInvert(pixd2, pixd2); 00124 pixCompare(pixd, pixd2, "results are the same", "results are different" ); 00125 pixDestroy(&pixd); 00126 pixDestroy(&pixd2); 00127 00128 /* ------------- Test open/close duality -------------- */ 00129 pixd = pixOpenGray(pixs, WSIZE, HSIZE); 00130 pixInvert(pixs, pixs); 00131 pixd2 = pixCloseGray(pixs, WSIZE, HSIZE); 00132 pixInvert(pixd2, pixd2); 00133 pixCompare(pixd, pixd2, "results are the same", "results are different" ); 00134 pixDestroy(&pixd); 00135 pixDestroy(&pixd2); 00136 00137 /* ------------- Test tophat duality -------------- */ 00138 pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); 00139 pixInvert(pixs, pixs); 00140 pixd2 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK); 00141 pixCompare(pixd, pixd2, "Correct: images are duals", 00142 "Error: images are not duals" ); 00143 pixDestroy(&pixd); 00144 pixDestroy(&pixd2); 00145 pixInvert(pixs, pixs); 00146 00147 pixd = pixGrayMorphSequence(pixs, "Tw9.5", HORIZ_SEP, 100); 00148 pixInvert(pixs, pixs); 00149 pixd2 = pixGrayMorphSequence(pixs, "Tb9.5", HORIZ_SEP, 300); 00150 pixCompare(pixd, pixd2, "Correct: images are duals", 00151 "Error: images are not duals" ); 00152 pixDestroy(&pixd); 00153 pixDestroy(&pixd2); 00154 00155 /* ------------- Test opening/closing for large sels -------------- */ 00156 pixd = pixGrayMorphSequence(pixs, 00157 "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", HORIZ_SEP, 100); 00158 pixDestroy(&pixd); 00159 pixd = pixGrayMorphSequence(pixs, 00160 "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", HORIZ_SEP, 400); 00161 pixDestroy(&pixd); 00162 00163 /* ---------- Closing plus white tophat result ------------ * 00164 * Parameters: wsize, hsize = 9, 29 * 00165 * ---------------------------------------------------------*/ 00166 pixd = pixCloseGray(pixs, 9, 9); 00167 pixd1 = pixTophat(pixd, 9, 9, L_TOPHAT_WHITE); 00168 pixd2 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", HORIZ_SEP, 0); 00169 pixCompare(pixd1, pixd2, "correct: same", "wrong: different"); 00170 pixd3 = pixMaxDynamicRange(pixd1, L_LINEAR_SCALE); 00171 pixDisplayWrite(pixd3, 1); 00172 pixDestroy(&pixd); 00173 pixDestroy(&pixd1); 00174 pixDestroy(&pixd2); 00175 pixDestroy(&pixd3); 00176 pixd = pixCloseGray(pixs, 29, 29); 00177 pixd1 = pixTophat(pixd, 29, 29, L_TOPHAT_WHITE); 00178 pixd2 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", HORIZ_SEP, 0); 00179 pixCompare(pixd1, pixd2, "correct: same", "wrong: different"); 00180 pixd3 = pixMaxDynamicRange(pixd1, L_LINEAR_SCALE); 00181 pixDisplayWrite(pixd3, 1); 00182 pixDestroy(&pixd); 00183 pixDestroy(&pixd1); 00184 pixDestroy(&pixd2); 00185 pixDestroy(&pixd3); 00186 00187 /* --------- hdome with parameter height = 100 ------------*/ 00188 pixd = pixHDome(pixs, 100, 4); 00189 pixd2 = pixMaxDynamicRange(pixd, L_LINEAR_SCALE); 00190 pixDisplayWrite(pixd2, 1); 00191 pixDestroy(&pixd2); 00192 00193 /* ----- Contrast enhancement with morph parameters 9, 9 -------*/ 00194 pixd1 = pixInitAccumulate(w, h, 0x8000); 00195 pixAccumulate(pixd1, pixs, L_ARITH_ADD); 00196 pixMultConstAccumulate(pixd1, 3., 0x8000); 00197 pixd2 = pixOpenGray(pixs, 9, 9); 00198 pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT); 00199 pixDestroy(&pixd2); 00200 pixd2 = pixCloseGray(pixs, 9, 9); 00201 pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT); 00202 pixDestroy(&pixd2); 00203 pixd = pixFinalAccumulate(pixd1, 0x8000, 8); 00204 pixDisplayWrite(pixd, 1); 00205 pixDestroy(&pixd1); 00206 00207 /* Do the same thing with the Pixacc */ 00208 pacc = pixaccCreate(w, h, 1); 00209 pixaccAdd(pacc, pixs); 00210 pixaccMultConst(pacc, 3.); 00211 pixd1 = pixOpenGray(pixs, 9, 9); 00212 pixaccSubtract(pacc, pixd1); 00213 pixDestroy(&pixd1); 00214 pixd1 = pixCloseGray(pixs, 9, 9); 00215 pixaccSubtract(pacc, pixd1); 00216 pixDestroy(&pixd1); 00217 pixd2 = pixaccFinal(pacc, 8); 00218 pixaccDestroy(&pacc); 00219 pixDisplayWrite(pixd2, 1); 00220 00221 pixCompare(pixd, pixd2, "Correct: same", "Wrong: different"); 00222 pixDestroy(&pixd); 00223 pixDestroy(&pixd2); 00224 00225 00226 /* ---- Tophat result on feynman stamp, to extract diagrams ----- */ 00227 pixDestroy(&pixs); 00228 pixs = pixRead("feynman-stamp.jpg"); 00229 00230 /* Make output image to hold five intermediate images */ 00231 w = pixGetWidth(pixs); 00232 h = pixGetHeight(pixs); 00233 pixd = pixCreate(5 * w + 18, h + 6, 32); /* composite output image */ 00234 pixSetAllArbitrary(pixd, 0x0000ff00); /* set to blue */ 00235 00236 /* Paste in the input image */ 00237 pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); 00238 pixRasterop(pixd, 3, 3, w, h, PIX_SRC, pixt, 0, 0); /* 1st one */ 00239 /* pixWrite("/tmp/junkgray.jpg", pixt, IFF_JFIF_JPEG); */ 00240 pixDestroy(&pixt); 00241 00242 /* Paste in the grayscale version */ 00243 cmap = pixGetColormap(pixs); 00244 if (cmap) 00245 pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); 00246 else 00247 pixt = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); 00248 pixt2 = pixConvertTo32(pixt); /* 8 --> 32 bpp */ 00249 pixRasterop(pixd, w + 6, 3, w, h, PIX_SRC, pixt2, 0, 0); /* 2nd one */ 00250 pixDestroy(&pixt2); 00251 00252 /* Paste in a log dynamic range scaled version of the white tophat */ 00253 pixt2 = pixTophat(pixt, 3, 3, L_TOPHAT_WHITE); 00254 pixt3a = pixMaxDynamicRange(pixt2, L_LOG_SCALE); 00255 pixt3 = pixConvertTo32(pixt3a); 00256 pixRasterop(pixd, 2 * w + 9, 3, w, h, PIX_SRC, pixt3, 0, 0); /* 3rd */ 00257 /* pixWrite("/tmp/junktophat.jpg", pixt2, IFF_JFIF_JPEG); */ 00258 pixDestroy(&pixt3); 00259 pixDestroy(&pixt3a); 00260 pixDestroy(&pixt); 00261 00262 /* Stretch the range and threshold to binary; paste it in */ 00263 pixt3a = pixGammaTRC(NULL, pixt2, 1.0, 0, 80); 00264 pixt3 = pixThresholdToBinary(pixt3a, 70); 00265 pixt4 = pixConvertTo32(pixt3); 00266 pixRasterop(pixd, 3 * w + 12, 3, w, h, PIX_SRC, pixt4, 0, 0); /* 4th */ 00267 /* pixWrite("/tmp/junkbin.png", pixt3, IFF_PNG); */ 00268 pixDestroy(&pixt2); 00269 pixDestroy(&pixt3a); 00270 pixDestroy(&pixt4); 00271 00272 /* Invert; this is the final result */ 00273 pixInvert(pixt3, pixt3); 00274 pixt4 = pixConvertTo32(pixt3); 00275 pixRasterop(pixd, 4 * w + 15, 3, w, h, PIX_SRC, pixt4, 0, 0); /* 5th */ 00276 pixWrite("/tmp/junkbininvert.png", pixt3, IFF_PNG); 00277 pixDisplayWrite(pixd, 1); 00278 /* pixWrite("/tmp/junkall.jpg", pixd, IFF_JFIF_JPEG); */ 00279 pixDestroy(&pixt3); 00280 pixDestroy(&pixt4); 00281 pixDestroy(&pixd); 00282 00283 pixDisplayMultiple("/tmp/junk_write_display*"); 00284 pixDestroy(&pixs); 00285 return 0; 00286 } 00287 00288 00289 00290 /* simple comparison function */ 00291 static void pixCompare(PIX *pix1, 00292 PIX *pix2, 00293 const char *msg1, 00294 const char *msg2) 00295 { 00296 l_int32 same; 00297 pixEqual(pix1, pix2, &same); 00298 if (same) { 00299 fprintf(stderr, "%s\n", msg1); 00300 pixDisplayWrite(pix1, 1); 00301 } 00302 else { 00303 fprintf(stderr, "%s\n", msg2); 00304 pixDisplayWrite(pix1, 1); 00305 pixDisplayWrite(pix2, 1); 00306 } 00307 return; 00308 } 00309 00310