Leptonica 1.68
C Image Processing Library

graymorph1_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  * 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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines