Leptonica 1.68
C Image Processing Library

compfilter_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  *  compfilter_reg.c
00018  *
00019  *     Tests filters that select components based on size, etc.
00020  */
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include "allheaders.h"
00025 
00026 static void count_pieces(PIX  *pix, l_int32 nexp);
00027 static void count_pieces2(BOXA *boxa, l_int32 nexp);
00028 static l_int32 count_ones(NUMA  *na, l_int32 nexp, l_int32 index,
00029                           const char *name);
00030 
00031 static const l_float32 edges[13] = {0.0, 0.2, 0.3, 0.35, 0.4, 0.45, 0.5,
00032                                     0.55, 0.6, 0.7, 0.8, 0.9, 1.0};
00033 
00034 #if 1   /* for feyn.tif */
00035 static const l_int32 band[12] = {1, 11, 48, 264, 574, 704, 908, 786, 466,
00036                                  157, 156, 230};
00037 static const l_int32 total[12] = {1, 12, 60, 324, 898, 1602, 2510, 3296,
00038                                   3762, 3919, 4075, 4305};
00039 #else   /* for rabi.png */
00040 static const l_int32 band[12] = {24, 295, 490, 817, 1768, 962, 8171,
00041                                  63, 81, 51, 137, 8619};
00042 static const l_int32 total[12] = {24, 319, 809, 1626, 3394, 4356, 12527,
00043                                   12590, 12671, 12722, 12859, 21478};
00044 #endif
00045 
00046 
00047 main(int    argc,
00048      char **argv)
00049 {
00050 l_int32      w, h, n, i, sum, sumi, empty;
00051 BOX         *box1, *box2, *box3, *box4;
00052 BOXA        *boxa, *boxat;
00053 NUMA        *na1, *na2, *na3, *na4, *na5;
00054 NUMA        *na2i, *na3i, *na4i, *nat, *naw, *nah;
00055 PIX         *pixs, *pixc, *pixt, *pixt2, *pixd, *pixcount;
00056 PIXA        *pixas, *pixad, *pixac;
00057 static char  mainName[] = "compfilter_reg";
00058 
00059     pixDisplayWrite(NULL, -1);
00060 
00061         /* Draw 4 filled boxes of different sizes */
00062     pixs = pixCreate(200, 200, 1);
00063     box1 = boxCreate(10, 10, 20, 30);
00064     box2 = boxCreate(50, 10, 40, 20);
00065     box3 = boxCreate(110, 10, 35, 5);
00066     box4 = boxCreate(160, 10, 5, 15);
00067     boxa = boxaCreate(4);
00068     boxaAddBox(boxa, box1, L_INSERT);
00069     boxaAddBox(boxa, box2, L_INSERT);
00070     boxaAddBox(boxa, box3, L_INSERT);
00071     boxaAddBox(boxa, box4, L_INSERT);
00072     pixRenderBox(pixs, box1, 1, L_SET_PIXELS);
00073     pixRenderBox(pixs, box2, 1, L_SET_PIXELS);
00074     pixRenderBox(pixs, box3, 1, L_SET_PIXELS);
00075     pixRenderBox(pixs, box4, 1, L_SET_PIXELS);
00076     pixt = pixFillClosedBorders(pixs, 4);
00077     pixDisplayWrite(pixt, 1);
00078     pixt2 = pixCreateTemplate(pixs);
00079     pixRenderHashBox(pixt2, box1, 6, 4, L_POS_SLOPE_LINE, 1, L_SET_PIXELS);
00080     pixRenderHashBox(pixt2, box2, 7, 2, L_POS_SLOPE_LINE, 1, L_SET_PIXELS);
00081     pixRenderHashBox(pixt2, box3, 4, 2, L_VERTICAL_LINE, 1, L_SET_PIXELS);
00082     pixRenderHashBox(pixt2, box4, 3, 1, L_HORIZONTAL_LINE, 1, L_SET_PIXELS);
00083     pixDisplayWrite(pixt2, 1);
00084 
00085         /* Exercise the parameters */
00086     pixd = pixSelectBySize(pixt, 0, 22, 8, L_SELECT_HEIGHT,
00087                            L_SELECT_IF_GT, NULL);
00088     count_pieces(pixd, 1);
00089     pixd = pixSelectBySize(pixt, 0, 30, 8, L_SELECT_HEIGHT,
00090                            L_SELECT_IF_LT, NULL);
00091     count_pieces(pixd, 3);
00092     pixd = pixSelectBySize(pixt, 0, 5, 8, L_SELECT_HEIGHT,
00093                            L_SELECT_IF_GT, NULL);
00094     count_pieces(pixd, 3);
00095     pixd = pixSelectBySize(pixt, 0, 6, 8, L_SELECT_HEIGHT,
00096                            L_SELECT_IF_LT, NULL);
00097     count_pieces(pixd, 1);
00098     pixd = pixSelectBySize(pixt, 20, 0, 8, L_SELECT_WIDTH,
00099                            L_SELECT_IF_GT, NULL);
00100     count_pieces(pixd, 2);
00101     pixd = pixSelectBySize(pixt, 31, 0, 8, L_SELECT_WIDTH,
00102                            L_SELECT_IF_LT, NULL);
00103     count_pieces(pixd, 2);
00104     pixd = pixSelectBySize(pixt, 21, 10, 8, L_SELECT_IF_EITHER,
00105                            L_SELECT_IF_LT, NULL);
00106     count_pieces(pixd, 3);
00107     pixd = pixSelectBySize(pixt, 20, 30, 8, L_SELECT_IF_EITHER,
00108                            L_SELECT_IF_GT, NULL);
00109     count_pieces(pixd, 2);
00110     pixd = pixSelectBySize(pixt, 22, 32, 8, L_SELECT_IF_BOTH,
00111                            L_SELECT_IF_LT, NULL);
00112     count_pieces(pixd, 2);
00113     pixd = pixSelectBySize(pixt, 6, 32, 8, L_SELECT_IF_BOTH,
00114                            L_SELECT_IF_LT, NULL);
00115     count_pieces(pixd, 1);
00116     pixd = pixSelectBySize(pixt, 5, 25, 8, L_SELECT_IF_BOTH,
00117                            L_SELECT_IF_GT, NULL);
00118     count_pieces(pixd, 1);
00119     pixd = pixSelectBySize(pixt, 25, 5, 8, L_SELECT_IF_BOTH,
00120                            L_SELECT_IF_GT, NULL);
00121     count_pieces(pixd, 1);
00122 
00123     pixd = pixSelectByAreaPerimRatio(pixt, 1.7, 8, L_SELECT_IF_LT, NULL);
00124     count_pieces(pixd, 2);
00125     pixd = pixSelectByAreaPerimRatio(pixt, 5.5, 8, L_SELECT_IF_LT, NULL);
00126     count_pieces(pixd, 3);
00127     pixd = pixSelectByAreaPerimRatio(pixt, 1.5, 8, L_SELECT_IF_GTE, NULL);
00128     count_pieces(pixd, 2);
00129     pixd = pixSelectByAreaPerimRatio(pixt, 13.0/12.0, 8, L_SELECT_IF_GT, NULL);
00130     count_pieces(pixd, 3);
00131 
00132     pixd = pixSelectByAreaFraction(pixt2, 0.3, 8, L_SELECT_IF_LT, NULL);
00133     count_pieces(pixd, 0);
00134     pixd = pixSelectByAreaFraction(pixt2, 0.9, 8, L_SELECT_IF_LT, NULL);
00135     count_pieces(pixd, 4);
00136     pixd = pixSelectByAreaFraction(pixt2, 0.5, 8, L_SELECT_IF_GTE, NULL);
00137     count_pieces(pixd, 3);
00138     pixd = pixSelectByAreaFraction(pixt2, 0.7, 8, L_SELECT_IF_GT, NULL);
00139     count_pieces(pixd, 2);
00140 
00141     boxat = boxaSelectBySize(boxa, 21, 10, L_SELECT_IF_EITHER,
00142                              L_SELECT_IF_LT, NULL);
00143     count_pieces2(boxat, 3);
00144     boxat = boxaSelectBySize(boxa, 22, 32, L_SELECT_IF_BOTH,
00145                              L_SELECT_IF_LT, NULL);
00146     count_pieces2(boxat, 2);
00147 
00148     boxaDestroy(&boxa);
00149     pixDestroy(&pixt);
00150     pixDestroy(&pixt2);
00151     pixDestroy(&pixs);
00152 
00153         /* Here's the most general method for selecting components.
00154          * We do it for area fraction, but any combination of
00155          * size, area/perimeter ratio and area fraction can be used. */
00156     pixs = pixRead("feyn.tif");
00157 /*    pixs = pixRead("rabi.png"); */
00158     pixc = pixCopy(NULL, pixs);  /* subtract bands from this */
00159     pixt = pixCreateTemplate(pixs);  /* add bands to this */
00160     pixGetDimensions(pixs, &w, &h, NULL);
00161     boxa = pixConnComp(pixs, &pixas, 8);
00162     n = boxaGetCount(boxa);
00163     fprintf(stderr, "total: %d\n", n);
00164     na1 = pixaFindAreaFraction(pixas);
00165     nat = numaCreate(0);
00166     numaSetCount(nat, n);  /* initialize to all 0 */
00167     sum = sumi = 0;
00168     pixac = pixaCreate(0);
00169     for (i = 0; i < 12; i++) {
00170             /* Compute within the intervals using an intersection. */
00171         na2 = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_GTE);
00172         if (i != 11)
00173             na3 = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_LT);
00174         else
00175             na3 = numaMakeThresholdIndicator(na1, edges[i + 1],
00176                                              L_SELECT_IF_LTE);
00177         na4 = numaLogicalOp(NULL, na2, na3, L_INTERSECTION);
00178         sum += count_ones(na4, 0, 0, NULL);
00179 
00180             /* Compute outside the intervals using a union, and invert */
00181         na2i = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_LT);
00182         if (i != 11)
00183             na3i = numaMakeThresholdIndicator(na1, edges[i + 1],
00184                                               L_SELECT_IF_GTE);
00185         else
00186             na3i = numaMakeThresholdIndicator(na1, edges[i + 1],
00187                                               L_SELECT_IF_GT);
00188         na4i = numaLogicalOp(NULL, na3i, na2i, L_UNION);
00189         numaInvert(na4i, na4i);
00190         sumi += count_ones(na4i, 0, 0, NULL);
00191 
00192             /* Compare the two methods */
00193         if (sum == sumi)
00194             fprintf(stderr, "\nCorrect: sum = sumi = %d\n", sum);
00195         else
00196             fprintf(stderr, "\nWRONG: sum = %d, sumi = %d\n", sum, sumi);
00197 
00198             /* Reconstruct the image, band by band. */
00199         numaLogicalOp(nat, nat, na4, L_UNION);
00200         pixad = pixaSelectWithIndicator(pixas, na4, NULL);
00201         pixd = pixaDisplay(pixad, w, h);
00202         pixOr(pixt, pixt, pixd);  /* add them in */
00203         pixcount = pixCopy(NULL, pixt);  /* destroyed by count_pieces */
00204         count_ones(na4, band[i], i, "band");
00205         count_pieces(pixd, band[i]);
00206         count_ones(nat, total[i], i, "total");
00207         count_pieces(pixcount, total[i]);
00208         pixaDestroy(&pixad);
00209 
00210             /* Remove band successively from full image */
00211         pixRemoveWithIndicator(pixc, pixas, na4);
00212         pixSaveTiled(pixc, pixac, 4, 1 - i % 2, 25, 8);
00213 
00214         numaDestroy(&na2);
00215         numaDestroy(&na3);
00216         numaDestroy(&na4);
00217         numaDestroy(&na2i);
00218         numaDestroy(&na3i);
00219         numaDestroy(&na4i);
00220     }
00221 
00222         /* Did we remove all components from pixc? */
00223     pixZero(pixc, &empty);
00224     if (!empty)
00225         fprintf(stderr, "\nWRONG: not all pixels removed from pixc\n");
00226 
00227     pixDestroy(&pixs);
00228     pixDestroy(&pixc);
00229     pixDestroy(&pixt);
00230     boxaDestroy(&boxa);
00231     pixaDestroy(&pixas);
00232     numaDestroy(&na1);
00233     numaDestroy(&nat);
00234 
00235         /* One last extraction.  Get all components that have either
00236          * a height of at least 50 or a width of between 30 and 35,
00237          * and also do not have a large area/perimeter ratio. */
00238     pixs = pixRead("feyn.tif"); 
00239     boxa = pixConnComp(pixs, &pixas, 8);
00240     n = boxaGetCount(boxa);
00241     pixaFindDimensions(pixas, &naw, &nah);
00242     na1 = pixaFindAreaPerimRatio(pixas);
00243     na2 = numaMakeThresholdIndicator(nah, 50, L_SELECT_IF_GTE);
00244     na3 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_GTE);
00245     na4 = numaMakeThresholdIndicator(naw, 35, L_SELECT_IF_LTE);
00246     na5 = numaMakeThresholdIndicator(na1, 2.5, L_SELECT_IF_LTE);
00247     numaLogicalOp(na3, na3, na4, L_INTERSECTION);
00248     numaLogicalOp(na2, na2, na3, L_UNION);
00249     numaLogicalOp(na2, na2, na5, L_INTERSECTION);
00250     numaInvert(na2, na2);  /* get components to be removed */
00251     pixRemoveWithIndicator(pixs, pixas, na2);
00252     pixSaveTiled(pixs, pixac, 4, 1, 25, 8);
00253     pixDestroy(&pixs);
00254     boxaDestroy(&boxa);
00255     pixaDestroy(&pixas);
00256     numaDestroy(&naw);
00257     numaDestroy(&nah);
00258     numaDestroy(&na1);
00259     numaDestroy(&na2);
00260     numaDestroy(&na3);
00261     numaDestroy(&na4);
00262     numaDestroy(&na5);
00263 
00264 
00265     pixDisplayMultiple("/tmp/junk_write_display*");
00266 
00267     pixd = pixaDisplay(pixac, 0, 0);
00268     pixDisplay(pixd, 100, 100);
00269     pixWrite("/tmp/junkcomp.jpg", pixd, IFF_JFIF_JPEG);
00270     pixDestroy(&pixd);
00271     pixaDestroy(&pixac);
00272 
00273     return 0;
00274 }
00275 
00276 
00277 void count_pieces(PIX  *pix, l_int32 nexp)
00278 {
00279 l_int32  n;
00280 BOXA    *boxa;
00281 
00282     pixDisplayWrite(pix, 1);
00283     boxa = pixConnComp(pix, NULL, 8);
00284     n = boxaGetCount(boxa);
00285     if (n == nexp)
00286         fprintf(stderr, "Correct: Num. comps: %d\n", n);
00287     else
00288         fprintf(stderr, "WRONG!: Num. comps: %d\n", n);
00289     boxaDestroy(&boxa);
00290     pixDestroy(&pix);
00291 }
00292 
00293 void count_pieces2(BOXA  *boxa, l_int32 nexp)
00294 {
00295 l_int32  n;
00296 
00297     n = boxaGetCount(boxa);
00298     if (n == nexp)
00299         fprintf(stderr, "Correct: Num. boxes: %d\n", n);
00300     else
00301         fprintf(stderr, "WRONG!: Num. boxes: %d\n", n);
00302     boxaDestroy(&boxa);
00303 }
00304 
00305 l_int32 count_ones(NUMA  *na, l_int32 nexp, l_int32 index, const char *name)
00306 {
00307 l_int32  i, n, val, sum;
00308 
00309     n = numaGetCount(na);
00310     sum = 0;
00311     for (i = 0; i < n; i++) {
00312         numaGetIValue(na, i, &val);
00313         if (val == 1) sum++;
00314     }
00315     if (!name) return sum;
00316     if (nexp == sum)
00317         fprintf(stderr, "Correct: %s[%d]: num. ones: %d\n", name, index, sum);
00318     else
00319         fprintf(stderr, "WRONG!: %s[%d]: num. ones: %d\n", name, index, sum);
00320     return 0;
00321 }
00322 
00323 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines