Skip to content

Commit

Permalink
New findpattern2_reg.c demonstrates generation of sels and their use.
Browse files Browse the repository at this point in the history
* also rename findpattern_reg.c ==> findpattern1_reg.c
  • Loading branch information
DanBloomberg committed Mar 27, 2024
1 parent 32af1df commit ca62606
Show file tree
Hide file tree
Showing 13 changed files with 419 additions and 168 deletions.
3 changes: 2 additions & 1 deletion prog/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ add_prog_target(falsecolor_reg falsecolor_reg.c)
add_prog_target(fhmtauto_reg fhmtauto_reg.c)
add_prog_target(files_reg files_reg.c)
add_prog_target(findcorners_reg findcorners_reg.c)
add_prog_target(findpattern_reg findpattern_reg.c)
add_prog_target(findpattern1_reg findpattern1_reg.c)
add_prog_target(findpattern2_reg findpattern2_reg.c)
add_prog_target(flipdetect_reg flipdetect_reg.c)
add_prog_target(fmorphauto_reg fmorphauto_reg.c)
add_prog_target(fpix1_reg fpix1_reg.c)
Expand Down
2 changes: 1 addition & 1 deletion prog/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ AUTO_REG_PROGS = adaptmap_reg adaptnorm_reg affine_reg alphaops_reg \
dither_reg dna_reg dwamorph1_reg edge_reg encoding_reg \
enhance_reg equal_reg expand_reg extrema_reg \
falsecolor_reg fhmtauto_reg \
findcorners_reg findpattern_reg flipdetect_reg \
findcorners_reg findpattern1_reg findpattern2_reg flipdetect_reg \
fpix1_reg fpix2_reg genfonts_reg \
grayfill_reg graymorph1_reg graymorph2_reg \
grayquant_reg hardlight_reg hash_reg heap_reg \
Expand Down
3 changes: 2 additions & 1 deletion prog/alltests_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ static const char *tests[] = {
"fhmtauto_reg",
/* "files_reg", */
"findcorners_reg",
"findpattern_reg",
"findpattern1_reg",
"findpattern2_reg",
"flipdetect_reg",
"fpix1_reg",
"fpix2_reg",
Expand Down
Binary file added prog/asterisk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion prog/findpattern_reg.c → prog/findpattern1_reg.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*====================================================================*/

/*
* findpattern_reg.c
* findpattern1_reg.c
*
* This uses pixGenerateSelBoundary() to generate hit-miss Sels
* that are a good fit for two 1 bpp patterns:
Expand Down
236 changes: 236 additions & 0 deletions prog/findpattern2_reg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/

/*
* findpattern2_reg.c
*
* This demonstrates three methods for generating hit-miss SELs from
* a 1 bpp image of a pattern. Of the three, only the boundary
* method should be used. The other methods are retained for comparison.
*
* The SELs that are effective for each of the three methods are
* displayed. For each method, one SEL is chosen and used to extract
* the "asterisk" patterns in the input image.
*
* The removal of matched patterns by brute-force dilation is shown
* as a set of steps. Not recommended because it is too expensive.
*/

#ifdef HAVE_CONFIG_H
#include <config_auto.h>
#endif /* HAVE_CONFIG_H */

#include "allheaders.h"

/* for pixDisplayHitMissSel() */
static const l_uint32 HitColor = 0x33aa4400;
static const l_uint32 MissColor = 0xaa44bb00;

l_int32 DoPatternMatch(PIX *pixs, PIX *pixt, SEL *sel,
const char *fname, L_REGPARAMS *rp);


int main(int argc,
char **argv)
{
l_int32 i, cx, cy;
PIX *pixs, *pixt, *pixsel, *pix1, *pix2, *pix3, *pix4;
PIXA *pixa1;
SEL *sel_ast, *sel1, *sel2;
L_REGPARAMS *rp;

if (regTestSetup(argc, argv, &rp))
return 1;

lept_mkdir("lept/pattern");

pixs = pixRead("asterisk.png");
pixt = pixRead("one-asterisk.png");

/********************************************************************
* Generate hit-miss SELs that work effectively to identify *
* the pattern in the image. Do this for the three methods: *
* - located a given distance from the boundary: this is *
* the best method; always use it. *
* - located on a set of horizontal and vertical lines: this *
* works over a range of parameters, but is less robust *
* - random locations: the least reliable method *
********************************************************************/

/* Boundary method is quite robust. With boundary distance of 2
* for both hits and misses, hitskip and missskip can be
* anything from 0 to 6. */
pixa1 = pixaCreate(7);
for (i = 0; i <= 6; i++) {
sel_ast = pixGenerateSelBoundary(pixt, 2, 2, i, i, 1, 0, 1, 1, &pix1);
pixsel = pixDisplayHitMissSel(pix1, sel_ast, 7, HitColor, MissColor);
pixaAddPix(pixa1, pixsel, L_INSERT);
pixDestroy(&pix1);
}
pix2 = pixaDisplayTiledInColumns(pixa1, 7, 1.0, 25, 2);
regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 0 */
pixDisplayWithTitle(pix2, 0, 700, NULL, rp->display);
pixaDestroy(&pixa1);
pixDestroy(&pix2);

/* Run method is less robust. With default min distance and
* min runlength, the number of horizontal and vertical lines
* can be chosen between 9 and 16. */
pixa1 = pixaCreate(7);
for (i = 9; i <= 16; i++) {
sel_ast = pixGenerateSelWithRuns(pixt, i, i, 1, 3, 0, 0, 0, 0, &pix1);
pixsel = pixDisplayHitMissSel(pix1, sel_ast, 7, HitColor, MissColor);
pixaAddPix(pixa1, pixsel, L_INSERT);
pixDestroy(&pix1);
}
pix2 = pixaDisplayTiledInColumns(pixa1, 8, 1.0, 25, 2);
regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */
pixDisplayWithTitle(pix2, 0, 850, NULL, rp->display);
pixaDestroy(&pixa1);
pixDestroy(&pix2);

/* The random method is the least robust. For this template,
* the hit fraction must be near 0.15 and the miss fraction
* near 0.10 */
sel_ast = pixGenerateSelRandom(pixt, 0.15, 0.10, 1, 3, 0, 3, 3, &pix1);
pixsel = pixDisplayHitMissSel(pix1, sel_ast, 7, HitColor, MissColor);
regTestWritePixAndCheck(rp, pixsel, IFF_PNG); /* 2 */
pixDisplayWithTitle(pixsel, 0, 950, NULL, rp->display);
pixDestroy(&pix1);
pixDestroy(&pixsel);
selDestroy(&sel_ast);

/********************************************************************
* For each of the three methods, choose a workable sel and show *
* the action on the input image. *
********************************************************************/

l_pdfSetDateAndVersion(0); /* can't have date in a regression test */

/* Choose some working skip distance for the boundary method */
sel1 = pixGenerateSelBoundary(pixt, 2, 2, 5, 5, 1, 0, 1, 1, &pix1);
DoPatternMatch(pixs, pix1, sel1, "/tmp/lept/pattern/match1.pdf",
rp); /* 3 */
lept_stderr("Boundary output written to /tmp/lept/pattern/match1.pdf\n");
regTestCheckFile(rp, "/tmp/lept/pattern/match1.pdf"); /* 4 */
selDestroy(&sel1);
pixDestroy(&pix1);

/* Choose some working number of horizontal and vertical lines for
* the method of generating a HMT sel with runs */
sel1 = pixGenerateSelWithRuns(pixt, 11, 11, 1, 3, 0, 0, 0, 0, &pix1);
DoPatternMatch(pixs, pix1, sel1, "/tmp/lept/pattern/match2.pdf",
rp); /* 5 */
lept_stderr("Run output written to /tmp/lept/pattern/match2.pdf\n");
regTestCheckFile(rp, "/tmp/lept/pattern/match2.pdf"); /* 6 */
selDestroy(&sel1);
pixDestroy(&pix1);

/* Choose a working number for the hit and miss fractions. */
sel1 = pixGenerateSelRandom(pixt, 0.15, 0.12, 1, 0, 0, 0, 0, &pix1);
DoPatternMatch(pixs, pix1, sel1, "/tmp/lept/pattern/match3.pdf",
rp); /* 7 */
lept_stderr("Random output written to /tmp/lept/pattern/match3.pdf\n");
regTestCheckFile(rp, "/tmp/lept/pattern/match3.pdf"); /* 8 */
selDestroy(&sel1);
pixDestroy(&pix1);

/********************************************************************
* Brute-force method for removing all instances of a pattern: *
* (1) Create a hit-miss SEL from an input pattern *
* (2) Do pixHMT() to find all locations that are matched *
* (3) Dilate the result by the original input pattern *
* (4) Dilate a little more to compensate for alignment issues *
* (5) Subtract the dilated result from the input image *
* Note: step (3) is very expensive for a pattern with many fg *
* pixels. If nfg is the number of fg pixels in the template, *
* this dilation is doing nfg rasterops of the input image! *
* To remove matching pixels efficiently, use *
* pixRemoveMatchedPattern()] *
********************************************************************/

sel1 = pixGenerateSelBoundary(pixt, 2, 2, 5, 5, 1, 0, 1, 1, &pix1);
pix2 = pixHMT(NULL, pixs, sel1);
selGetParameters(sel1, NULL, NULL, &cy, &cx);
sel2 = selCreateFromPix(pix1, cy, cx, NULL);
pix3 = pixDilate(NULL, pix2, sel2);
pixDilateBrick(pix3, pix3, 4, 4);
regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 9 */
pixDisplayWithTitle(pix3, 850, 450, NULL, rp->display);
pix4 = pixSubtract(NULL, pixs, pix3);
regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 10 */
pixDisplayWithTitle(pix4, 1150, 850, NULL, rp->display);
selDestroy(&sel1);
selDestroy(&sel2);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);

return regTestCleanup(rp);
}


l_int32
DoPatternMatch(PIX *pixs,
PIX *pixt,
SEL *sel,
const char *fname,
L_REGPARAMS *rp)
{
l_int32 cx, cy;
PIX *pixsel, *pixt1, *pix1, *pix2, *pix3, *pix4;
PIXA *pixa1;

pixa1 = pixaCreate(7);
pixaAddPix(pixa1, pixs, L_COPY);
pixt1 = pixScale(pixt, 8, 8);
pixaAddPix(pixa1, pixt1, L_INSERT);
pixsel = pixDisplayHitMissSel(pixt, sel, 7, HitColor, MissColor);
pixaAddPix(pixa1, pixsel, L_INSERT);

/* Perform the HMT and show patterns that were matched */
pix1 = pixHMT(NULL, pixs, sel);
pixaAddPix(pixa1, pix1, L_INSERT);
selGetParameters(sel, NULL, NULL, &cy, &cx);
pix2 = pixDisplayMatchedPattern(pixs, pixt, pix1, cx, cy, 0x0000ff00,
1.0, 5);
pixaAddPix(pixa1, pix2, L_INSERT);

/* Remove the matched patterns */
pix3 = pixCopy(NULL, pixs);
pixRemoveMatchedPattern(pix3, pixt, pix1, cx, cy, 2);
pixaAddPix(pixa1, pix3, L_INSERT);

/* Generate outputs */
pix4 = pixaDisplayTiledInColumns(pixa1, 7, 1.0, 15, 2);
pixaAddPix(pixa1, pix4, L_INSERT);
regTestWritePixAndCheck(rp, pix4, IFF_PNG);
pixaConvertToPdf(pixa1, 100, 1.0, L_FLATE_ENCODE, 50, NULL, fname);
pixaDestroy(&pixa1);
return 0;
}

9 changes: 6 additions & 3 deletions prog/makefile.static
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ SRC = adaptmap_reg.c adaptnorm_reg.c affine_reg.c \
edge_reg.c encoding_reg.c enhance_reg.c equal_reg.c \
expand_reg.c extrema_reg.c falsecolor_reg.c \
fhmtauto_reg.c files_reg.c \
findcorners_reg.c findpattern_reg.c \
findcorners_reg.c findpattern1_reg.c findpattern2_reg.c \
flipdetect_reg.c fmorphauto_reg.c \
fpix1_reg.c fpix2_reg.c \
genfonts_reg.c gifio_reg.c \
Expand Down Expand Up @@ -515,8 +515,11 @@ files_reg: files_reg.o $(LEPTLIB)
findcorners_reg: findcorners_reg.o $(LEPTLIB)
$(CC) -o findcorners_reg findcorners_reg.o $(ALL_LIBS) $(EXTRALIBS)

findpattern_reg: findpattern_reg.o $(LEPTLIB)
$(CC) -o findpattern_reg findpattern_reg.o $(ALL_LIBS) $(EXTRALIBS)
findpattern1_reg: findpattern1_reg.o $(LEPTLIB)
$(CC) -o findpattern_reg findpattern1_reg.o $(ALL_LIBS) $(EXTRALIBS)

findpattern2_reg: findpattern2_reg.o $(LEPTLIB)
$(CC) -o findpattern_reg findpattern2_reg.o $(ALL_LIBS) $(EXTRALIBS)

flipdetect_reg: flipdetect_reg.o $(LEPTLIB)
$(CC) -o flipdetect_reg flipdetect_reg.o $(ALL_LIBS) $(EXTRALIBS)
Expand Down
Binary file added prog/one-asterisk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/allheaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -2532,9 +2532,9 @@ LEPT_DLL extern SELA * sela4ccThin ( SELA *sela );
LEPT_DLL extern SELA * sela8ccThin ( SELA *sela );
LEPT_DLL extern SELA * sela4and8ccThin ( SELA *sela );
LEPT_DLL extern SEL * selMakePlusSign ( l_int32 size, l_int32 linewidth );
LEPT_DLL extern SEL * pixGenerateSelBoundary ( PIX *pixs, l_int32 hitdist, l_int32 missdist, l_int32 hitskip, l_int32 missskip, l_int32 topflag, l_int32 botflag, l_int32 leftflag, l_int32 rightflag, PIX **ppixe );
LEPT_DLL extern SEL * pixGenerateSelWithRuns ( PIX *pixs, l_int32 nhlines, l_int32 nvlines, l_int32 distance, l_int32 minlength, l_int32 toppix, l_int32 botpix, l_int32 leftpix, l_int32 rightpix, PIX **ppixe );
LEPT_DLL extern SEL * pixGenerateSelRandom ( PIX *pixs, l_float32 hitfract, l_float32 missfract, l_int32 distance, l_int32 toppix, l_int32 botpix, l_int32 leftpix, l_int32 rightpix, PIX **ppixe );
LEPT_DLL extern SEL * pixGenerateSelBoundary ( PIX *pixs, l_int32 hitdist, l_int32 missdist, l_int32 hitskip, l_int32 missskip, l_int32 topflag, l_int32 botflag, l_int32 leftflag, l_int32 rightflag, PIX **ppixe );
LEPT_DLL extern NUMA * pixGetRunCentersOnLine ( PIX *pixs, l_int32 x, l_int32 y, l_int32 minlength );
LEPT_DLL extern NUMA * pixGetRunsOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2 );
LEPT_DLL extern PTA * pixSubsampleBoundaryPixels ( PIX *pixs, l_int32 skip );
Expand Down
Loading

0 comments on commit ca62606

Please sign in to comment.