l_int32 main(int argc, char **argv) { l_int32 irval, igval, ibval; l_float32 rval, gval, bval, fract, fgfract; L_BMF *bmf; BOX *box; BOXA *boxa; FPIX *fpix; PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; PIX *pix8, *pix9, *pix10, *pix11, *pix12, *pix13, *pix14, *pix15; PIXA *pixa; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixa = pixaCreate(0); pixs = pixRead("breviar38.150.jpg"); /* pixs = pixRead("breviar32.150.jpg"); */ pixaAddPix(pixa, pixs, L_CLONE); regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 0 */ pixDisplayWithTitle(pixs, 0, 0, "Input image", rp->display); /* Extract the blue component, which is small in all the text * regions, including in the highlight color region */ pix1 = pixGetRGBComponent(pixs, COLOR_BLUE); pixaAddPix(pixa, pix1, L_CLONE); regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 1 */ pixDisplayWithTitle(pix1, 200, 0, "Blue component", rp->display); /* Do a background normalization, with the background set to * approximately 200 */ pix2 = pixBackgroundNormSimple(pix1, NULL, NULL); pixaAddPix(pixa, pix2, L_COPY); regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 2 */ pixDisplayWithTitle(pix2, 400, 0, "BG normalized to 200", rp->display); /* Do a linear transform on the gray pixels, with 50 going to * black and 160 going to white. 50 is sufficiently low to * make both the red and black print quite dark. Quantize * to a few equally spaced gray levels. This is the image * to which highlight color will be applied. */ pixGammaTRC(pix2, pix2, 1.0, 50, 160); pix3 = pixThresholdOn8bpp(pix2, 7, 1); pixaAddPix(pixa, pix3, L_CLONE); regTestWritePixAndCheck(rp, pix3, IFF_JFIF_JPEG); /* 3 */ pixDisplayWithTitle(pix3, 600, 0, "Basic quantized with white bg", rp->display); /* Identify the regions of red text. First, make a mask * consisting of all pixels such that (R-B)/B is larger * than 2.0. This will have all the red, plus a lot of * the dark pixels. */ fpix = pixComponentFunction(pixs, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0); pix4 = fpixThresholdToPix(fpix, 2.0); pixInvert(pix4, pix4); /* red plus some dark text */ pixaAddPix(pixa, pix4, L_CLONE); regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ pixDisplayWithTitle(pix4, 800, 0, "Red plus dark pixels", rp->display); /* Make a mask consisting of all the red and background pixels */ pix5 = pixGetRGBComponent(pixs, COLOR_RED); pix6 = pixThresholdToBinary(pix5, 128); pixInvert(pix6, pix6); /* red plus background (white) */ /* Intersect the two masks to get a mask consisting of pixels * that are almost certainly red. This is the seed. */ pix7 = pixAnd(NULL, pix4, pix6); /* red only (seed) */ pixaAddPix(pixa, pix7, L_COPY); regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 5 */ pixDisplayWithTitle(pix7, 0, 600, "Seed for red color", rp->display); /* Make the clipping mask by thresholding the image with * the background cleaned to white. */ pix8 = pixThresholdToBinary(pix2, 230); /* mask */ pixaAddPix(pixa, pix8, L_CLONE); regTestWritePixAndCheck(rp, pix8, IFF_PNG); /* 6 */ pixDisplayWithTitle(pix8, 200, 600, "Clipping mask for red components", rp->display); /* Fill into the mask from the seed */ pixSeedfillBinary(pix7, pix7, pix8, 8); /* filled: red plus touching */ regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 7 */ pixDisplayWithTitle(pix7, 400, 600, "Red component mask filled", rp->display); /* Remove long horizontal and vertical lines from the filled result */ pix9 = pixMorphSequence(pix7, "o40.1", 0); pixSubtract(pix7, pix7, pix9); /* remove long horizontal lines */ pixDestroy(&pix9); pix9 = pixMorphSequence(pix7, "o1.40", 0); pixSubtract(pix7, pix7, pix9); /* remove long vertical lines */ /* Close the regions to be colored */ pix10 = pixMorphSequence(pix7, "c5.1", 0); pixaAddPix(pixa, pix10, L_CLONE); regTestWritePixAndCheck(rp, pix10, IFF_PNG); /* 8 */ pixDisplayWithTitle(pix10, 600, 600, "Components defining regions allowing coloring", rp->display); /* Sanity check on amount to be colored. Only accept images * with less than 10% of all the pixels with highlight color */ pixForegroundFraction(pix10, &fgfract); if (fgfract >= 0.10) { L_INFO("too much highlighting: fract = %6.3f; removing it\n", rp->testname, fgfract); pixClearAll(pix10); pixSetPixel(pix10, 0, 0, 1); } /* Get the bounding boxes of the regions to be colored */ boxa = pixConnCompBB(pix10, 8); /* Get a color to paint that is representative of the * actual highlight color in the image. Scale each * color component up from the average by an amount necessary * to saturate the red. Then divide the green and * blue components by 2.0. */ pixGetAverageMaskedRGB(pixs, pix7, 0, 0, 1, L_MEAN_ABSVAL, &rval, &gval, &bval); fract = 255.0 / rval; irval = lept_roundftoi(fract * rval); igval = lept_roundftoi(fract * gval / 2.0); ibval = lept_roundftoi(fract * bval / 2.0); fprintf(stderr, "(r,g,b) = (%d,%d,%d)\n", irval, igval, ibval); /* Color the quantized gray version in the selected regions */ pix11 = pixColorGrayRegions(pix3, boxa, L_PAINT_DARK, 220, irval, igval, ibval); pixaAddPix(pixa, pix11, L_CLONE); regTestWritePixAndCheck(rp, pix11, IFF_PNG); /* 9 */ pixDisplayWithTitle(pix11, 800, 600, "Final colored result", rp->display); pixaAddPix(pixa, pixs, L_CLONE); /* Test colorization on gray and cmapped gray */ pix12 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 220, 0, 255, 0); pixaAddPix(pixa, pix12, L_CLONE); regTestWritePixAndCheck(rp, pix12, IFF_PNG); /* 10 */ pixDisplayWithTitle(pix12, 900, 600, "Colorizing boxa gray", rp->display); box = boxCreate(200, 200, 250, 350); pix13 = pixCopy(NULL, pix2); pixColorGray(pix13, box, L_PAINT_DARK, 220, 0, 0, 255); pixaAddPix(pixa, pix13, L_CLONE); regTestWritePixAndCheck(rp, pix13, IFF_PNG); /* 11 */ pixDisplayWithTitle(pix13, 1000, 600, "Colorizing box gray", rp->display); pix14 = pixThresholdTo4bpp(pix2, 6, 1); pix15 = pixColorGrayRegions(pix14, boxa, L_PAINT_DARK, 220, 0, 0, 255); pixaAddPix(pixa, pix15, L_CLONE); regTestWritePixAndCheck(rp, pix15, IFF_PNG); /* 12 */ pixDisplayWithTitle(pix15, 1100, 600, "Colorizing boxa cmap", rp->display); pixColorGrayCmap(pix14, box, L_PAINT_DARK, 0, 255, 255); pixaAddPix(pixa, pix14, L_CLONE); regTestWritePixAndCheck(rp, pix14, IFF_PNG); /* 13 */ pixDisplayWithTitle(pix14, 1200, 600, "Colorizing box cmap", rp->display); boxDestroy(&box); /* Generate a pdf of the intermediate results */ lept_mkdir("lept"); L_INFO("Writing to /tmp/lept/colorize.pdf\n", rp->testname); pixaConvertToPdf(pixa, 90, 1.0, 0, 0, "Colorizing highlighted text", "/tmp/lept/colorize.pdf"); pixaDestroy(&pixa); fpixDestroy(&fpix); boxDestroy(&box); boxaDestroy(&boxa); pixDestroy(&pixs); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); pixDestroy(&pix7); pixDestroy(&pix8); pixDestroy(&pix9); pixDestroy(&pix10); pixDestroy(&pix11); pixDestroy(&pix12); pixDestroy(&pix13); pixDestroy(&pix14); pixDestroy(&pix15); /* Test the color detector */ pixa = pixaCreate(7); bmf = bmfCreate("./fonts", 4); pix1 = TestForRedColor(rp, "brev06.75.jpg", 1, bmf); /* 14 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev10.75.jpg", 0, bmf); /* 15 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev14.75.jpg", 1, bmf); /* 16 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev20.75.jpg", 1, bmf); /* 17 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev36.75.jpg", 0, bmf); /* 18 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev53.75.jpg", 1, bmf); /* 19 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = TestForRedColor(rp, "brev56.75.jpg", 1, bmf); /* 20 */ pixaAddPix(pixa, pix1, L_INSERT); /* Generate a pdf of the color detector results */ L_INFO("Writing to /tmp/lept/colordetect.pdf\n", rp->testname); pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Color detection", "/tmp/lept/colordetect.pdf"); pixaDestroy(&pixa); bmfDestroy(&bmf); return regTestCleanup(rp); }
main(int argc, char **argv) { l_int32 i, j, x, y, rval, gval, bval; l_uint32 pixel; l_float32 frval, fgval, fbval; NUMA *nahue, *nasat, *napk; PIX *pixs, *pixhsv, *pixh, *pixg, *pixf, *pixd; PIX *pixr, *pixt1, *pixt2, *pixt3; PIXA *pixa, *pixapk; PTA *ptapk; L_REGPARAMS *rp; l_chooseDisplayProg(L_DISPLAY_WITH_XV); if (regTestSetup(argc, argv, &rp)) return 1; /* Make a graded frame color */ pixs = pixCreate(650, 900, 32); for (i = 0; i < 900; i++) { rval = 40 + i / 30; for (j = 0; j < 650; j++) { gval = 255 - j / 30; bval = 70 + j / 30; composeRGBPixel(rval, gval, bval, &pixel); pixSetPixel(pixs, j, i, pixel); } } /* Place an image inside the frame and convert to HSV */ pixt1 = pixRead("1555-3.jpg"); pixt2 = pixScale(pixt1, 0.5, 0.5); pixRasterop(pixs, 100, 100, 2000, 2000, PIX_SRC, pixt2, 0, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDisplayWithTitle(pixs, 400, 0, "Input image", rp->display); pixa = pixaCreate(0); pixhsv = pixConvertRGBToHSV(NULL, pixs); /* Work in the HS projection of HSV */ pixh = pixMakeHistoHS(pixhsv, 5, &nahue, &nasat); pixg = pixMaxDynamicRange(pixh, L_LOG_SCALE); pixf = pixConvertGrayToFalseColor(pixg, 1.0); regTestWritePixAndCheck(rp, pixf, IFF_PNG); /* 0 */ pixDisplayWithTitle(pixf, 100, 0, "False color HS histo", rp->display); pixaAddPix(pixa, pixs, L_COPY); pixaAddPix(pixa, pixhsv, L_INSERT); pixaAddPix(pixa, pixg, L_INSERT); pixaAddPix(pixa, pixf, L_INSERT); gplotSimple1(nahue, GPLOT_PNG, "/tmp/junkhue", "Histogram of hue values"); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixt3 = pixRead("/tmp/junkhue.png"); regTestWritePixAndCheck(rp, pixt3, IFF_PNG); /* 1 */ pixDisplayWithTitle(pixt3, 100, 300, "Histo of hue", rp->display); pixaAddPix(pixa, pixt3, L_INSERT); gplotSimple1(nasat, GPLOT_PNG, "/tmp/junksat", "Histogram of saturation values"); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixt3 = pixRead("/tmp/junksat.png"); regTestWritePixAndCheck(rp, pixt3, IFF_PNG); /* 2 */ pixDisplayWithTitle(pixt3, 100, 800, "Histo of saturation", rp->display); pixaAddPix(pixa, pixt3, L_INSERT); pixd = pixaDisplayTiledAndScaled(pixa, 32, 270, 7, 0, 30, 3); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ pixDisplayWithTitle(pixd, 0, 400, "Hue and Saturation Mosaic", rp->display); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&nahue); numaDestroy(&nasat); /* Find all the peaks */ pixFindHistoPeaksHSV(pixh, L_HS_HISTO, 20, 20, 6, 2.0, &ptapk, &napk, &pixapk); numaWriteStream(stderr, napk); ptaWriteStream(stderr, ptapk, 1); pixd = pixaDisplayTiledInRows(pixapk, 32, 1400, 1.0, 0, 30, 2); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 4 */ pixDisplayWithTitle(pixd, 0, 550, "Peaks in HS", rp->display); pixDestroy(&pixh); pixDestroy(&pixd); pixaDestroy(&pixapk); /* Make masks for each of the peaks */ pixa = pixaCreate(0); pixr = pixScaleBySampling(pixs, 0.4, 0.4); for (i = 0; i < 6; i++) { ptaGetIPt(ptapk, i, &x, &y); pixt1 = pixMakeRangeMaskHS(pixr, y, 20, x, 20, L_INCLUDE_REGION); pixaAddPix(pixa, pixt1, L_INSERT); pixGetAverageMaskedRGB(pixr, pixt1, 0, 0, 1, L_MEAN_ABSVAL, &frval, &fgval, &fbval); composeRGBPixel((l_int32)frval, (l_int32)fgval, (l_int32)fbval, &pixel); pixt2 = pixCreateTemplate(pixr); pixSetAll(pixt2); pixPaintThroughMask(pixt2, pixt1, 0, 0, pixel); pixaAddPix(pixa, pixt2, L_INSERT); pixt3 = pixCreateTemplate(pixr); pixSetAllArbitrary(pixt3, pixel); pixaAddPix(pixa, pixt3, L_INSERT); } pixd = pixaDisplayTiledAndScaled(pixa, 32, 225, 3, 0, 30, 3); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ pixDisplayWithTitle(pixd, 600, 0, "Masks over peaks", rp->display); pixDestroy(&pixs); pixDestroy(&pixr); pixDestroy(&pixd); pixaDestroy(&pixa); ptaDestroy(&ptapk); numaDestroy(&napk); regTestCleanup(rp); return 0; }