void RotateTest(PIX *pixs, l_float32 scale, L_REGPARAMS *rp) { l_int32 w, h, d, outformat; PIX *pixt1, *pixt2, *pixt3, *pixd; PIXA *pixa; pixGetDimensions(pixs, &w, &h, &d); outformat = (d == 8 || d == 32) ? IFF_JFIF_JPEG : IFF_PNG; pixa = pixaCreate(0); pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h); pixSaveTiled(pixt1, pixa, scale, 1, 20, 32); pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); pixSaveTiled(pixt1, pixa, scale, 1, 20, 0); pixt2 = pixRotate(pixs, ANGLE1, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, w, h); pixSaveTiled(pixt1, pixa, scale, 1, 20, 0); pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, w, h); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_WHITE, 0, 0); pixSaveTiled(pixt1, pixa, scale, 1, 20, 0); pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SHEAR, L_BRING_IN_BLACK, 0, 0); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixd = pixaDisplay(pixa, 0, 0); regTestWritePixAndCheck(rp, pixd, outformat); pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixd); pixaDestroy(&pixa); pixa = pixaCreate(0); pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, w, h); pixSaveTiled(pixt1, pixa, scale, 1, 20, 32); pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, w, h); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_WHITE, 0, 0); pixSaveTiled(pixt1, pixa, scale, 1, 20, 0); pixt2 = pixRotate(pixs, ANGLE2, L_ROTATE_SAMPLING, L_BRING_IN_BLACK, 0, 0); pixSaveTiled(pixt2, pixa, scale, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); if (pixGetDepth(pixs) == 1) pixt1 = pixScaleToGray2(pixs); else pixt1 = pixClone(pixs); pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h); pixSaveTiled(pixt2, pixa, scale, 1, 20, 0); pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, w, h); pixSaveTiled(pixt3, pixa, scale, 0, 20, 0); pixDestroy(&pixt2); pixDestroy(&pixt3); pixt2 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, 0, 0); pixSaveTiled(pixt2, pixa, scale, 1, 20, 0); pixt3 = pixRotate(pixt1, ANGLE2, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, 0, 0); pixSaveTiled(pixt3, pixa, scale, 0, 20, 0); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt1); pixd = pixaDisplay(pixa, 0, 0); regTestWritePixAndCheck(rp, pixd, outformat); pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixd); pixaDestroy(&pixa); return; }
l_int32 main(int argc, char **argv) { l_int32 size, i, rval, gval, bval, yval, uval, vval; l_float32 *a[3], b[3]; L_BMF *bmf; PIX *pixd; PIXA *pixa; /* Explore the range of rgb --> yuv transforms. All rgb * values transform to a valid value of yuv, so when transforming * back we get the same rgb values that we started with. */ pixa = pixaCreate(0); bmf = bmfCreate("fonts", 6); for (gval = 0; gval <= 255; gval += 20) AddTransformsRGB(pixa, bmf, gval); pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2); pixDisplay(pixd, 100, 0); pixWrite("/tmp/yuv1.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); /* Now start with all "valid" yuv values, not all of which are * related to a valid rgb value. Our yuv --> rgb transform * clips the rgb components to [0 ... 255], so when transforming * back we get different values whenever the initial yuv * value is out of the rgb gamut. */ pixa = pixaCreate(0); for (yval = 16; yval <= 235; yval += 16) AddTransformsYUV(pixa, bmf, yval); pixd = pixaDisplayTiledAndScaled(pixa, 32, 755, 1, 0, 20, 2); pixDisplay(pixd, 600, 0); pixWrite("/tmp/yuv2.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); bmfDestroy(&bmf); /* --------- Try out a special case by hand, and show that --------- * * ------- the transform matrices we are using are inverses ---------*/ /* First, use our functions for the transform */ fprintf(stderr, "Start with: yval = 143, uval = 79, vval = 103\n"); convertYUVToRGB(143, 79, 103, &rval, &gval, &bval); fprintf(stderr, " ==> rval = %d, gval = %d, bval = %d\n", rval, gval, bval); convertRGBToYUV(rval, gval, bval, &yval, &uval, &vval); fprintf(stderr, " ==> yval = %d, uval = %d, vval = %d\n", yval, uval, vval); /* Next, convert yuv --> rbg by solving for rgb --> yuv transform. * [ a00 a01 a02 ] r = b0 (y - 16) * [ a10 a11 a12 ] * g = b1 (u - 128) * [ a20 a21 a22 ] b = b2 (v - 128) */ b[0] = 143.0 - 16.0; /* y - 16 */ b[1] = 79.0 - 128.0; /* u - 128 */ b[2] = 103.0 - 128.0; /* v - 128 */ for (i = 0; i < 3; i++) a[i] = (l_float32 *)lept_calloc(3, sizeof(l_float32)); a[0][0] = 65.738 / 256.0; a[0][1] = 129.057 / 256.0; a[0][2] = 25.064 / 256.0; a[1][0] = -37.945 / 256.0; a[1][1] = -74.494 / 256.0; a[1][2] = 112.439 / 256.0; a[2][0] = 112.439 / 256.0; a[2][1] = -94.154 / 256.0; a[2][2] = -18.285 / 256.0; fprintf(stderr, "Here's the original matrix: yuv --> rgb:\n"); for (i = 0; i < 3; i++) fprintf(stderr, " %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], 256.0 * a[i][1], 256.0 * a[i][2]); gaussjordan(a, b, 3); fprintf(stderr, "\nInput (yuv) = (143,79,103); solve for rgb:\n" "rval = %7.3f, gval = %7.3f, bval = %7.3f\n", b[0], b[1], b[2]); fprintf(stderr, "Here's the inverse matrix: rgb --> yuv:\n"); for (i = 0; i < 3; i++) fprintf(stderr, " %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], 256.0 * a[i][1], 256.0 * a[i][2]); /* Now, convert back: rgb --> yuv; * Do this by solving for yuv --> rgb transform. * Use the b[] found previously (the rgb values), and * the a[][] which now holds the rgb --> yuv transform. */ gaussjordan(a, b, 3); fprintf(stderr, "\nInput rgb; solve for yuv:\n" "yval = %7.3f, uval = %7.3f, vval = %7.3f\n", b[0] + 16.0, b[1] + 128.0, b[2] + 128.0); fprintf(stderr, "Inverting the matrix again: yuv --> rgb:\n"); for (i = 0; i < 3; i++) fprintf(stderr, " %7.3f %7.3f %7.3f\n", 256.0 * a[i][0], 256.0 * a[i][1], 256.0 * a[i][2]); for (i = 0; i < 3; i++) lept_free(a[i]); return 0; }
/** * Auto page segmentation. Divide the page image into blocks of uniform * text linespacing and images. * * Width, height and resolution are derived from the input image. * * If the pix is non-NULL, then it is assumed to be the input, and it is * copied to the image, otherwise the image is used directly. * * The output goes in the blocks list with corresponding TO_BLOCKs in the * to_blocks list. * * If single_column is true, then no attempt is made to divide the image * into columns, but multiple blocks are still made if the text is of * non-uniform linespacing. */ int Tesseract::AutoPageSeg(int width, int height, int resolution, bool single_column, IMAGE* image, BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks) { int vertical_x = 0; int vertical_y = 1; TabVector_LIST v_lines; TabVector_LIST h_lines; ICOORD bleft(0, 0); Boxa* boxa = NULL; Pixa* pixa = NULL; // The blocks made by the ColumnFinder. Moved to blocks before return. BLOCK_LIST found_blocks; #ifdef HAVE_LIBLEPT if (pix_binary_ != NULL) { if (textord_debug_images) { Pix* grey_pix = pixCreate(width, height, 8); // Printable images are light grey on white, but for screen display // they are black on dark grey so the other colors show up well. if (textord_debug_printable) { pixSetAll(grey_pix); pixSetMasked(grey_pix, pix_binary_, 192); } else { pixSetAllArbitrary(grey_pix, 64); pixSetMasked(grey_pix, pix_binary_, 0); } AlignedBlob::IncrementDebugPix(); pixWrite(AlignedBlob::textord_debug_pix().string(), grey_pix, IFF_PNG); pixDestroy(&grey_pix); } if (tessedit_dump_pageseg_images) pixWrite("tessinput.png", pix_binary_, IFF_PNG); // Leptonica is used to find the lines and image regions in the input. LineFinder::FindVerticalLines(resolution, pix_binary_, &vertical_x, &vertical_y, &v_lines); LineFinder::FindHorizontalLines(resolution, pix_binary_, &h_lines); if (tessedit_dump_pageseg_images) pixWrite("tessnolines.png", pix_binary_, IFF_PNG); ImageFinder::FindImages(pix_binary_, &boxa, &pixa); if (tessedit_dump_pageseg_images) pixWrite("tessnoimages.png", pix_binary_, IFF_PNG); // Copy the Pix to the IMAGE. image->FromPix(pix_binary_); if (single_column) v_lines.clear(); } #endif TO_BLOCK_LIST land_blocks, port_blocks; TBOX page_box; // The rest of the algorithm uses the usual connected components. find_components(blocks, &land_blocks, &port_blocks, &page_box); TO_BLOCK_IT to_block_it(&port_blocks); ASSERT_HOST(!to_block_it.empty()); for (to_block_it.mark_cycle_pt(); !to_block_it.cycled_list(); to_block_it.forward()) { TO_BLOCK* to_block = to_block_it.data(); TBOX blkbox = to_block->block->bounding_box(); if (to_block->line_size >= 2) { // Note: if there are multiple blocks, then v_lines, boxa, and pixa // are empty on the next iteration, but in this case, we assume // that there aren't any interesting line separators or images, since // it means that we have a pre-defined unlv zone file. ColumnFinder finder(static_cast<int>(to_block->line_size), blkbox.botleft(), blkbox.topright(), &v_lines, &h_lines, vertical_x, vertical_y); if (finder.FindBlocks(height, resolution, single_column, to_block, boxa, pixa, &found_blocks, to_blocks) < 0) return -1; finder.ComputeDeskewVectors(&deskew_, &reskew_); boxa = NULL; pixa = NULL; } } #ifdef HAVE_LIBLEPT boxaDestroy(&boxa); pixaDestroy(&pixa); #endif blocks->clear(); BLOCK_IT block_it(blocks); // Move the found blocks to the input/output blocks. block_it.add_list_after(&found_blocks); if (textord_debug_images) { // The debug image is no longer needed so delete it. unlink(AlignedBlob::textord_debug_pix().string()); } return 0; }
int main(int argc, char **argv) { l_int32 i, n, binsize, binstart, nbins; l_float32 pi, val, angle, xval, yval, x0, y0, rank, startval, fbinsize; l_float32 minval, maxval, meanval, median, variance, rankval; GPLOT *gplot; NUMA *na, *nahisto, *nax, *nay, *nap, *nasx, *nasy; NUMA *nadx, *nady, *nafx, *nafy, *na1, *na2, *na3, *na4; PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pixd; PIXA *pixa; static char mainName[] = "numa1_reg"; if (argc != 1) return ERROR_INT(" Syntax: numa1_reg", mainName, 1); lept_mkdir("lept/numa1"); /* -------------------------------------------------------------------* * Histograms * * -------------------------------------------------------------------*/ #if DO_ALL pi = 3.1415926535; na = numaCreate(5000); for (i = 0; i < 500000; i++) { angle = 0.02293 * i * pi; val = (l_float32)(999. * sin(angle)); numaAddNumber(na, val); } nahisto = numaMakeHistogramClipped(na, 6, 2000); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, 1, nbins); gplot = gplotCreate("/tmp/lept/numa1/histo1", GPLOT_PNG, "example histo 1", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, &binstart); nbins = numaGetCount(nahisto); nax = numaMakeSequence(binstart, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, binstart); gplot = gplotCreate("/tmp/lept/numa1/histo2", GPLOT_PNG, "example histo 2", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, NULL); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, 0); gplot = gplotCreate("/tmp/lept/numa1/histo3", GPLOT_PNG, "example histo 3", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogramAuto(na, 1000); nbins = numaGetCount(nahisto); numaGetParameters(nahisto, &startval, &fbinsize); nax = numaMakeSequence(startval, fbinsize, nbins); fprintf(stderr, " binsize = %7.4f, binstart = %8.3f\n", fbinsize, startval); gplot = gplotCreate("/tmp/lept/numa1/histo4", GPLOT_PNG, "example histo 4", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); pixa = pixaCreate(4); pix1 = pixRead("/tmp/lept/numa1/histo1.png"); pix2 = pixRead("/tmp/lept/numa1/histo2.png"); pix3 = pixRead("/tmp/lept/numa1/histo3.png"); pix4 = pixRead("/tmp/lept/numa1/histo4.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pixd, 600, 0); pixWrite("/tmp/lept/numa1/histo.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&nax); numaDestroy(&nahisto); numaGetStatsUsingHistogram(na, 2000, &minval, &maxval, &meanval, &variance, &median, 0.80, &rankval, &nahisto); fprintf(stderr, "Sin histogram: \n" " min val = %7.2f -- should be -999.00\n" " max val = %7.2f -- should be 999.00\n" " mean val = %7.2f -- should be 0.06\n" " median = %7.2f -- should be 0.30\n" " rmsdev = %7.2f -- should be 706.41\n" " rank val = %7.2f -- should be 808.15\n", minval, maxval, meanval, median, sqrt((l_float64)variance), rankval); numaHistogramGetRankFromVal(nahisto, 808.15, &rank); fprintf(stderr, " rank = %7.3f -- should be 0.800\n", rank); numaDestroy(&nahisto); numaDestroy(&na); #endif /* -------------------------------------------------------------------* * Interpolation * * -------------------------------------------------------------------*/ #if DO_ALL /* Test numaInterpolateEqxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); /* numaWriteStream(stderr, na); */ nasy = numaGetPartialSums(na); gplotSimple1(nasy, GPLOT_PNG, "/tmp/lept/numa1/int1", "partial sums"); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/int2", "simple test"); numaInterpolateEqxInterval(0.0, 1.0, na, L_LINEAR_INTERP, 0.0, 255.0, 15, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/int3", GPLOT_PNG, "test interpolation", "pix val", "num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test numaInterpolateArbxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); /* gplotSimple1(nasy, GPLOT_PNG, "/tmp/numa/nasy", "partial sums"); */ numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, 10.0, 250.0, 23, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/int4", GPLOT_PNG, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test numaInterpolateArbxVal() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); /* gplotSimple1(nasy, GPLOT_PNG, "/tmp/numa/nasy", "partial sums"); */ nax = numaMakeSequence(15.0, (250.0 - 15.0) / 23.0, 24); n = numaGetCount(nax); nay = numaCreate(n); for (i = 0; i < n; i++) { numaGetFValue(nax, i, &xval); numaInterpolateArbxVal(nasx, nasy, L_QUADRATIC_INTERP, xval, &yval); numaAddNumber(nay, yval); } gplot = gplotCreate("/tmp/lept/numa1/int5", GPLOT_PNG, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test interpolation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); gplot = gplotCreate("/tmp/lept/numa1/int6", GPLOT_PNG, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "linear"); numaDestroy(&nax); numaDestroy(&nay); numaInterpolateArbxInterval(nasx, nasy, L_QUADRATIC_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); numaDestroy(&nax); numaDestroy(&nay); gplotMakeOutput(gplot); gplotDestroy(&gplot); gplot = gplotCreate("/tmp/lept/numa1/int7", GPLOT_PNG, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -1.2, -0.8, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaFitMax(nay, &yval, nax, &xval); fprintf(stderr, "max = %f at loc = %f\n", yval, xval); pixa = pixaCreate(7); pix1 = pixRead("/tmp/lept/numa1/int1.png"); pix2 = pixRead("/tmp/lept/numa1/int2.png"); pix3 = pixRead("/tmp/lept/numa1/int3.png"); pix4 = pixRead("/tmp/lept/numa1/int4.png"); pix5 = pixRead("/tmp/lept/numa1/int5.png"); pix6 = pixRead("/tmp/lept/numa1/int6.png"); pix7 = pixRead("/tmp/lept/numa1/int7.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); pixaAddPix(pixa, pix5, L_INSERT); pixaAddPix(pixa, pix6, L_INSERT); pixaAddPix(pixa, pix7, L_INSERT); pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pixd, 100, 900); pixWrite("/tmp/lept/numa1/int.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); #endif /* -------------------------------------------------------------------* * Integration and differentiation * * -------------------------------------------------------------------*/ #if DO_ALL /* Test integration and differentiation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); /* ---------- Plot the derivative ---------- */ numaDifferentiateInterval(nasx, nasy, -2.0, 0.0, 50, &nadx, &nady); gplot = gplotCreate("/tmp/lept/numa1/diff1", GPLOT_PNG, "derivative", "angle", "slope"); gplotAddPlot(gplot, nadx, nady, GPLOT_LINES, "derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); /* ---------- Plot the original function ----------- */ /* and the integral of the derivative; the two */ /* should be approximately the same. */ gplot = gplotCreate("/tmp/lept/numa1/diff2", GPLOT_PNG, "integ-diff", "angle", "val"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nafx, &nafy); gplotAddPlot(gplot, nafx, nafy, GPLOT_LINES, "function"); n = numaGetCount(nadx); numaGetFValue(nafx, 0, &x0); numaGetFValue(nafy, 0, &y0); nay = numaCreate(n); /* (Note: this tests robustness of the integrator: we go from * i = 0, and choose to have only 1 point in the interpolation * there, which is too small and causes the function to bomb out.) */ fprintf(stderr, "We must get a 'npts < 2' error here:\n"); for (i = 0; i < n; i++) { numaGetFValue(nadx, i, &xval); numaIntegrateInterval(nadx, nady, x0, xval, 2 * i + 1, &yval); numaAddNumber(nay, y0 + yval); } gplotAddPlot(gplot, nafx, nay, GPLOT_LINES, "anti-derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/diff1.png"); pix2 = pixRead("/tmp/lept/numa1/diff2.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pixd, 100, 450); pixWrite("/tmp/lept/numa1/diff.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nafx); numaDestroy(&nafy); numaDestroy(&nadx); numaDestroy(&nady); numaDestroy(&nay); #endif /* -------------------------------------------------------------------* * Rank extraction * * -------------------------------------------------------------------*/ #if DO_ALL /* Rank extraction with interpolation */ pixs = pixRead("test8.jpg"); nasy= pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); numaMakeRankFromHistogram(0.0, 1.0, nasy, 350, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/rank1", GPLOT_PNG, "test rank extractor", "pix val", "rank val"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Rank extraction, point by point */ pixs = pixRead("test8.jpg"); nap = numaCreate(200); pixGetRankValueMasked(pixs, NULL, 0, 0, 2, 0.0, &val, &na); for (i = 0; i < 101; i++) { rank = 0.01 * i; numaHistogramGetValFromRank(na, rank, &val); numaAddNumber(nap, val); } gplotSimple1(nap, GPLOT_PNG, "/tmp/lept/numa1/rank2", "rank value"); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/rank1.png"); pix2 = pixRead("/tmp/lept/numa1/rank2.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pixd, 100, 0); pixWrite("/tmp/lept/numa1/rank.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&nap); pixDestroy(&pixs); #endif /* -------------------------------------------------------------------* * Numa-morphology * * -------------------------------------------------------------------*/ #if DO_ALL na = numaRead("lyra.5.na"); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/lyra1", "Original"); na1 = numaErode(na, 21); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa1/lyra2", "Erosion"); na2 = numaDilate(na, 21); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa1/lyra3", "Dilation"); na3 = numaOpen(na, 21); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa1/lyra4", "Opening"); na4 = numaClose(na, 21); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa1/lyra5", "Closing"); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/lyra1.png"); pix2 = pixRead("/tmp/lept/numa1/lyra2.png"); pix3 = pixRead("/tmp/lept/numa1/lyra3.png"); pix4 = pixRead("/tmp/lept/numa1/lyra4.png"); pix5 = pixRead("/tmp/lept/numa1/lyra5.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); pixaAddPix(pixa, pix5, L_INSERT); pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pixd, 600, 450); pixWrite("/tmp/lept/numa1/morph.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); pixaDestroy(&pixa); #endif return 0; }
/*! * pixGetWordsInTextlines() * * Input: pixs (1 bpp, typ. 300 ppi) * reduction (1 for input res; 2 for 2x reduction of input res) * minwidth, minheight (of saved components; smaller are discarded) * maxwidth, maxheight (of saved components; larger are discarded) * &boxad (<return> word boxes sorted in textline line order) * &pixad (<return> word images sorted in textline line order) * &naindex (<return> index of textline for each word) * Return: 0 if OK, 1 on error * * Notes: * (1) The input should be at a resolution of about 300 ppi. * The word masks and word images can be computed at either * 150 ppi or 300 ppi. For the former, set reduction = 2. * (2) The four size constraints on saved components are all * scaled by @reduction. * (3) The result are word images (and their b.b.), extracted in * textline order, at either full res or 2x reduction, * and with a numa giving the textline index for each word. * (4) The pixa and boxa interfaces should make this type of * application simple to put together. The steps are: * - optionally reduce by 2x * - generate first estimate of word masks * - get b.b. of these, and remove the small and big ones * - extract pixa of the word images, using the b.b. * - sort actual word images in textline order (2d) * - flatten them to a pixa (1d), saving the textline index * for each pix * (5) In an actual application, it may be desirable to pre-filter * the input image to remove large components, to extract * single columns of text, and to deskew them. For example, * to remove both large components and small noisy components * that can interfere with the statistics used to estimate * parameters for segmenting by words, but still retain text lines, * the following image preprocessing can be done: * Pix *pixt = pixMorphSequence(pixs, "c40.1", 0); * Pix *pixf = pixSelectBySize(pixt, 0, 60, 8, * L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL); * pixAnd(pixf, pixf, pixs); // the filtered image * The closing turns text lines into long blobs, but does not * significantly increase their height. But if there are many * small connected components in a dense texture, this is likely * to generate tall components that will be eliminated in pixf. */ l_int32 pixGetWordsInTextlines(PIX *pixs, l_int32 reduction, l_int32 minwidth, l_int32 minheight, l_int32 maxwidth, l_int32 maxheight, BOXA **pboxad, PIXA **ppixad, NUMA **pnai) { l_int32 maxdil; BOXA *boxa1, *boxad; BOXAA *baa; NUMA *nai; NUMAA *naa; PIXA *pixa1, *pixad; PIX *pix1; PIXAA *paa; PROCNAME("pixGetWordsInTextlines"); if (!pboxad || !ppixad || !pnai) return ERROR_INT("&boxad, &pixad, &nai not all defined", procName, 1); *pboxad = NULL; *ppixad = NULL; *pnai = NULL; if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (reduction != 1 && reduction != 2) return ERROR_INT("reduction not in {1,2}", procName, 1); if (reduction == 1) { pix1 = pixClone(pixs); maxdil = 18; } else { /* reduction == 2 */ pix1 = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); maxdil = 9; } /* Get the bounding boxes of the words from the word mask. */ pixWordBoxesByDilation(pix1, maxdil, minwidth, minheight, maxwidth, maxheight, &boxa1, NULL); /* Generate a pixa of the word images */ pixa1 = pixaCreateFromBoxa(pix1, boxa1, NULL); /* mask over each word */ /* Sort the bounding boxes of these words by line. We use the * index mapping to allow identical sorting of the pixa. */ baa = boxaSort2d(boxa1, &naa, -1, -1, 4); paa = pixaSort2dByIndex(pixa1, naa, L_CLONE); /* Flatten the word paa */ pixad = pixaaFlattenToPixa(paa, &nai, L_CLONE); boxad = pixaGetBoxa(pixad, L_COPY); *pnai = nai; *pboxad = boxad; *ppixad = pixad; pixDestroy(&pix1); pixaDestroy(&pixa1); boxaDestroy(&boxa1); boxaaDestroy(&baa); pixaaDestroy(&paa); numaaDestroy(&naa); return 0; }
/*! * pixaDisplayTiledAndScaled() * * Input: pixa * outdepth (output depth: 1, 8 or 32 bpp) * tilewidth (each pix is scaled to this width) * ncols (number of tiles in each row) * background (0 for white, 1 for black; this is the color * of the spacing between the images) * spacing (between images, and on outside) * border (width of additional black border on each image; * use 0 for no border) * Return: pix of tiled images, or null on error * * Notes: * (1) This can be used to tile a number of renderings of * an image that are at different scales and depths. * (2) Each image, after scaling and optionally adding the * black border, has width 'tilewidth'. Thus, the border does * not affect the spacing between the image tiles. The * maximum allowed border width is tilewidth / 5. */ PIX * pixaDisplayTiledAndScaled(PIXA *pixa, l_int32 outdepth, l_int32 tilewidth, l_int32 ncols, l_int32 background, l_int32 spacing, l_int32 border) { l_int32 x, y, w, h, wd, hd, d; l_int32 i, n, nrows, maxht, ninrow, irow, bordval; l_int32 *rowht; l_float32 scalefact; PIX *pix, *pixn, *pixt, *pixb, *pixd; PIXA *pixan; PROCNAME("pixaDisplayTiledAndScaled"); if (!pixa) return (PIX *)ERROR_PTR("pixa not defined", procName, NULL); if (outdepth != 1 && outdepth != 8 && outdepth != 32) return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL); if (border < 0 || border > tilewidth / 5) border = 0; if ((n = pixaGetCount(pixa)) == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); /* Normalize scale and depth for each pix; optionally add border */ pixan = pixaCreate(n); bordval = (outdepth == 1) ? 1 : 0; for (i = 0; i < n; i++) { if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) continue; pixGetDimensions(pix, &w, &h, &d); scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w; if (d == 1 && outdepth > 1 && scalefact < 1.0) pixt = pixScaleToGray(pix, scalefact); else pixt = pixScale(pix, scalefact, scalefact); if (outdepth == 1) pixn = pixConvertTo1(pixt, 128); else if (outdepth == 8) pixn = pixConvertTo8(pixt, FALSE); else /* outdepth == 32 */ pixn = pixConvertTo32(pixt); pixDestroy(&pixt); if (border) pixb = pixAddBorder(pixn, border, bordval); else pixb = pixClone(pixn); pixaAddPix(pixan, pixb, L_INSERT); pixDestroy(&pix); pixDestroy(&pixn); } if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */ pixaDestroy(&pixan); return (PIX *)ERROR_PTR("no components", procName, NULL); } /* Determine the size of each row and of pixd */ wd = tilewidth * ncols + spacing * (ncols + 1); nrows = (n + ncols - 1) / ncols; if ((rowht = (l_int32 *)CALLOC(nrows, sizeof(l_int32))) == NULL) return (PIX *)ERROR_PTR("rowht array not made", procName, NULL); maxht = 0; ninrow = 0; irow = 0; for (i = 0; i < n; i++) { pix = pixaGetPix(pixan, i, L_CLONE); ninrow++; pixGetDimensions(pix, &w, &h, NULL); maxht = L_MAX(h, maxht); if (ninrow == ncols) { rowht[irow] = maxht; maxht = ninrow = 0; /* reset */ irow++; } pixDestroy(&pix); } if (ninrow > 0) { /* last fencepost */ rowht[irow] = maxht; irow++; /* total number of rows */ } nrows = irow; hd = spacing * (nrows + 1); for (i = 0; i < nrows; i++) hd += rowht[i]; pixd = pixCreate(wd, hd, outdepth); if ((background == 1 && outdepth == 1) || (background == 0 && outdepth != 1)) pixSetAll(pixd); /* Now blit images to pixd */ x = y = spacing; irow = 0; for (i = 0; i < n; i++) { pix = pixaGetPix(pixan, i, L_CLONE); pixGetDimensions(pix, &w, &h, NULL); if (i && ((i % ncols) == 0)) { /* start new row */ x = spacing; y += spacing + rowht[irow]; irow++; } pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0); x += tilewidth + spacing; pixDestroy(&pix); } pixaDestroy(&pixan); FREE(rowht); return pixd; }
/*! * pixaaDisplayByPixa() * * Input: pixaa * xspace between pix in pixa * yspace between pixa * max width of output pix * Return: pix, or null on error * * Notes: * (1) Displays each pixa on a line (or set of lines), * in order from top to bottom. Within each pixa, * the pix are displayed in order from left to right. * (2) The size of each pix in each pixa is assumed to be * approximately equal to the size of the first pix in * the pixa. If this assumption is not correct, this * function will not work properly. * (3) This ignores the boxa of the pixaa. */ PIX * pixaaDisplayByPixa(PIXAA *pixaa, l_int32 xspace, l_int32 yspace, l_int32 maxw) { l_int32 i, j, npixa, npix; l_int32 width, height, depth, nlines, lwidth; l_int32 x, y, w, h, w0, h0; PIX *pixt, *pixd; PIXA *pixa; PROCNAME("pixaaDisplayByPixa"); if (!pixaa) return (PIX *)ERROR_PTR("pixaa not defined", procName, NULL); if ((npixa = pixaaGetCount(pixaa)) == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); /* Get size of output pix. The width is the minimum of the * maxw and the largest pixa line width. The height is whatever * it needs to be to accommodate all pixa. */ height = 2 * yspace; width = 0; for (i = 0; i < npixa; i++) { pixa = pixaaGetPixa(pixaa, i, L_CLONE); npix = pixaGetCount(pixa); pixt = pixaGetPix(pixa, 0, L_CLONE); if (i == 0) depth = pixGetDepth(pixt); w = pixGetWidth(pixt); lwidth = npix * (w + xspace); nlines = (lwidth + maxw - 1) / maxw; if (nlines > 1) width = maxw; else width = L_MAX(lwidth, width); height += nlines * (pixGetHeight(pixt) + yspace); pixDestroy(&pixt); pixaDestroy(&pixa); } if ((pixd = pixCreate(width, height, depth)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); /* Now layout the pix by pixa */ y = yspace; for (i = 0; i < npixa; i++) { x = 0; pixa = pixaaGetPixa(pixaa, i, L_CLONE); npix = pixaGetCount(pixa); for (j = 0; j < npix; j++) { pixt = pixaGetPix(pixa, j, L_CLONE); if (j == 0) { w0 = pixGetWidth(pixt); h0 = pixGetHeight(pixt); } w = pixGetWidth(pixt); if (width == maxw && x + w >= maxw) { x = 0; y += h0 + yspace; } h = pixGetHeight(pixt); pixRasterop(pixd, x, y, w, h, PIX_PAINT, pixt, 0, 0); pixDestroy(&pixt); x += w0 + xspace; } y += h0 + yspace; pixaDestroy(&pixa); } return pixd; }
int main(int argc, char **argv) { l_uint8 *data1, *data2; l_int32 i, same, w, h, width, success, nba; size_t size1, size2; l_float32 diffarea, diffxor, scalefact; BOX *box; BOXA *boxa1, *boxa2, *boxa3; BOXAA *baa1, *baa2, *baa3; PIX *pix1, *pix2, *pix3, *pixdb; PIXA *pixa1, *pixa2; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; lept_mkdir("lept/boxa"); /* Make a boxa and display its contents */ boxa1 = boxaCreate(6); box = boxCreate(60, 60, 40, 20); boxaAddBox(boxa1, box, L_INSERT); box = boxCreate(120, 50, 20, 50); boxaAddBox(boxa1, box, L_INSERT); box = boxCreate(50, 140, 46, 60); boxaAddBox(boxa1, box, L_INSERT); box = boxCreate(166, 130, 64, 28); boxaAddBox(boxa1, box, L_INSERT); box = boxCreate(64, 224, 44, 34); boxaAddBox(boxa1, box, L_INSERT); box = boxCreate(117, 206, 26, 74); boxaAddBox(boxa1, box, L_INSERT); pix1 = DisplayBoxa(boxa1); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); pixDestroy(&pix1); boxaCompareRegions(boxa1, boxa1, 100, &same, &diffarea, &diffxor, NULL); regTestCompareValues(rp, 1, same, 0.0); /* 1 */ regTestCompareValues(rp, 0.0, diffarea, 0.0); /* 2 */ regTestCompareValues(rp, 0.0, diffxor, 0.0); /* 3 */ boxa2 = boxaTransform(boxa1, -13, -13, 1.0, 1.0); boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, NULL); regTestCompareValues(rp, 1, same, 0.0); /* 4 */ regTestCompareValues(rp, 0.0, diffarea, 0.0); /* 5 */ regTestCompareValues(rp, 0.0, diffxor, 0.0); /* 6 */ boxaDestroy(&boxa2); boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP_AND_BOT, 6, L_ADJUST_CHOOSE_MIN, 1.0, 0); pix1 = DisplayBoxa(boxa2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 7 */ pixDisplayWithTitle(pix1, 200, 0, NULL, rp->display); pixDestroy(&pix1); boxaCompareRegions(boxa1, boxa2, 10, &same, &diffarea, &diffxor, &pixdb); regTestCompareValues(rp, 1, same, 0.0); /* 8 */ regTestCompareValues(rp, 0.053, diffarea, 0.002); /* 9 */ regTestCompareValues(rp, 0.240, diffxor, 0.002); /* 10 */ regTestWritePixAndCheck(rp, pixdb, IFF_PNG); /* 11 */ pixDisplayWithTitle(pixdb, 400, 0, NULL, rp->display); pixDestroy(&pixdb); boxaDestroy(&boxa1); boxaDestroy(&boxa2); /* Input is a fairly clean boxa */ boxa1 = boxaRead("boxa1.ba"); boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, L_ADJUST_CHOOSE_MIN, 1.05, 1); width = 100; boxaGetExtent(boxa2, &w, &h, NULL); scalefact = (l_float32)width / (l_float32)w; boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display); pixDestroy(&pix1); boxaDestroy(&boxa1); boxaDestroy(&boxa2); boxaDestroy(&boxa3); /* Input is an unsmoothed and noisy boxa */ boxa1 = boxaRead("boxa2.ba"); boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, L_ADJUST_CHOOSE_MIN, 1.05, 1); width = 100; boxaGetExtent(boxa2, &w, &h, NULL); scalefact = (l_float32)width / (l_float32)w; boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 13 */ pixDisplayWithTitle(pix1, 800, 0, NULL, rp->display); pixDestroy(&pix1); boxaDestroy(&boxa1); boxaDestroy(&boxa2); boxaDestroy(&boxa3); /* Input is an unsmoothed and noisy boxa */ boxa1 = boxaRead("boxa2.ba"); boxa2 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_LOC_DIFF, 80, 20, 1); boxa3 = boxaSmoothSequenceMedian(boxa1, 10, L_SUB_ON_SIZE_DIFF, 80, 20, 1); boxaPlotSides(boxa1, "initial", NULL, NULL, NULL, NULL, &pix1); boxaPlotSides(boxa2, "side_smoothing", NULL, NULL, NULL, NULL, &pix2); boxaPlotSides(boxa3, "size_smoothing", NULL, NULL, NULL, NULL, &pix3); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 15 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 16 */ pixDisplayWithTitle(pix1, 1300, 0, NULL, rp->display); pixDisplayWithTitle(pix2, 1300, 500, NULL, rp->display); pixDisplayWithTitle(pix3, 1300, 1000, NULL, rp->display); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); boxaDestroy(&boxa1); boxaDestroy(&boxa2); boxaDestroy(&boxa3); /* Input is a boxa smoothed with a median window filter */ boxa1 = boxaRead("boxa3.ba"); boxa2 = boxaReconcileEvenOddHeight(boxa1, L_ADJUST_TOP, 80, L_ADJUST_CHOOSE_MIN, 1.05, 1); width = 100; boxaGetExtent(boxa2, &w, &h, NULL); scalefact = (l_float32)width / (l_float32)w; boxa3 = boxaTransform(boxa2, 0, 0, scalefact, scalefact); pix1 = boxaDisplayTiled(boxa3, NULL, 1500, 2, 1.0, 0, 3, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 17 */ pixDisplayWithTitle(pix1, 1000, 0, NULL, rp->display); pixDestroy(&pix1); boxaDestroy(&boxa1); boxaDestroy(&boxa2); boxaDestroy(&boxa3); /* Test serialized boxa I/O to and from memory */ data1 = l_binaryRead("boxa2.ba", &size1); boxa1 = boxaReadMem(data1, size1); boxaWriteMem(&data2, &size2, boxa1); boxa2 = boxaReadMem(data2, size2); boxaWrite("/tmp/lept/boxa/boxa1.ba", boxa1); boxaWrite("/tmp/lept/boxa/boxa2.ba", boxa2); filesAreIdentical("/tmp/lept/boxa/boxa1.ba", "/tmp/lept/boxa/boxa2.ba", &same); regTestCompareValues(rp, 1, same, 0.0); /* 18 */ boxaDestroy(&boxa1); boxaDestroy(&boxa2); lept_free(data1); lept_free(data2); /* ----------- Test pixaDisplayBoxaa() ------------ */ pixa1 = pixaReadBoth("showboxes.pac"); baa1 = boxaaRead("showboxes1.baa"); baa2 = boxaaTranspose(baa1); baa3 = boxaaTranspose(baa2); nba = boxaaGetCount(baa1); success = TRUE; for (i = 0; i < nba; i++) { boxa1 = boxaaGetBoxa(baa1, i, L_CLONE); boxa2 = boxaaGetBoxa(baa3, i, L_CLONE); boxaEqual(boxa1, boxa2, 0, NULL, &same); boxaDestroy(&boxa1); boxaDestroy(&boxa2); if (!same) success = FALSE; } /* Check that the transpose is reversible */ regTestCompareValues(rp, 1, success, 0.0); /* 19 */ pixa2 = pixaDisplayBoxaa(pixa1, baa2, L_DRAW_RGB, 2); pix1 = pixaDisplayTiledInRows(pixa2, 32, 1400, 1.0, 0, 10, 0); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); fprintf(stderr, "Writing to: /tmp/lept/boxa/show.pdf\n"); l_pdfSetDateAndVersion(FALSE); pixaConvertToPdf(pixa2, 75, 1.0, 0, 0, NULL, "/tmp/lept/boxa/show.pdf"); regTestCheckFile(rp, "/tmp/lept/boxa/show.pdf"); /* 21 */ pixDestroy(&pix1); pixaDestroy(&pixa1); pixaDestroy(&pixa2); boxaaDestroy(&baa1); boxaaDestroy(&baa2); boxaaDestroy(&baa3); return regTestCleanup(rp); }
l_int32 main(int argc, char **argv) { char *boxatxt; l_int32 i; BOXA *boxa1, *boxa2, *boxa3; BOXAA *baa, *baa1; NUMAA *naa1; PIX *pixdb, *pix1, *pix2, *pix3, *pix4; PIXA *pixa1, *pixa2, *pixa3, *pixat; L_RECOG *recog; L_RECOGA *recoga; SARRAY *sa1; /* ----- Example identifying samples using training data ----- */ #if 1 /* Read the training data */ pixat = pixaRead("recog/sets/train06.pa"); recog = recogCreateFromPixa(pixat, 0, 0, L_USE_ALL, 128, 1, "fonts"); recoga = recogaCreateFromRecog(recog); pixaDestroy(&pixat); /* Read the data from all samples */ pix1 = pixRead("recog/sets/samples06.png"); boxatxt = pixGetText(pix1); boxa1 = boxaReadMem((l_uint8 *)boxatxt, strlen(boxatxt)); pixa1 = pixaCreateFromBoxa(pix1, boxa1, NULL); pixDestroy(&pix1); /* destroys boxa1 */ /* Identify components in the sample data */ pixa2 = pixaCreate(0); pixa3 = pixaCreate(0); for (i = 0; i < 9; i++) { /* if (i != 4) continue; */ /* dots form separate boxa */ /* if (i != 8) continue; */ /* broken 2 in '24' */ pix1 = pixaGetPix(pixa1, i, L_CLONE); /* Show the 2d box data in the sample */ boxa2 = pixConnComp(pix1, NULL, 8); baa = boxaSort2d(boxa2, NULL, 6, 6, 5); pix2 = boxaaDisplay(baa, 3, 1, 0xff000000, 0x00ff0000, 0, 0); pixaAddPix(pixa3, pix2, L_INSERT); boxaaDestroy(&baa); boxaDestroy(&boxa2); /* Get the numbers in the sample */ recogaIdentifyMultiple(recoga, pix1, 0, 5, 3, &boxa3, NULL, &pixdb, 0); sa1 = recogaExtractNumbers(recoga, boxa3, 0.7, -1, &baa1, &naa1); sarrayWriteStream(stderr, sa1); boxaaWriteStream(stderr, baa1); numaaWriteStream(stderr, naa1); pixaAddPix(pixa2, pixdb, L_INSERT); /* pixaWrite("/tmp/pixa.pa", pixa2); */ pixDestroy(&pix1); boxaDestroy(&boxa3); boxaaDestroy(&baa1); numaaDestroy(&naa1); sarrayDestroy(&sa1); } pix3 = pixaDisplayLinearly(pixa2, L_VERT, 1.0, 0, 20, 1, NULL); pixWrite("/tmp/pix3.png", pix3, IFF_PNG); pix4 = pixaDisplayTiledInRows(pixa3, 32, 1500, 1.0, 0, 20, 2); pixDisplay(pix4, 500, 0); pixWrite("/tmp/pix4.png", pix4, IFF_PNG); pixaDestroy(&pixa2); pixaDestroy(&pixa3); pixDestroy(&pix1); pixDestroy(&pix3); pixDestroy(&pix4); pixaDestroy(&pixa1); boxaDestroy(&boxa1); recogaDestroy(&recoga); #endif return 0; }
int main(int argc, char **argv) { char textstr[256]; l_int32 i, thresh, fgval, bgval; l_float32 scorefract; L_BMF *bmf; PIX *pixs, *pixb, *pixb2, *pixb3, *pixg, *pixp, *pixt1, *pixt2; PIXA *pixa; pixs = pixRead("1555-7.jpg"); pixg = pixConvertTo8(pixs, 0); bmf = bmfCreate("fonts", 8); for (i = 0; i < 3; i++) { pixa = pixaCreate(3); scorefract = 0.1 * i; pixOtsuAdaptiveThreshold(pixg, 2000, 2000, 0, 0, scorefract, NULL, &pixb); pixSaveTiledOutline(pixb, pixa, 0.5, 1, 20, 2, 32); pixSplitDistributionFgBg(pixg, scorefract, 1, &thresh, &fgval, &bgval, 1); fprintf(stderr, "thresh = %d, fgval = %d, bgval = %d\n", thresh, fgval, bgval); /* Give gnuplot time to write out the plot */ #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixp = pixRead("/tmp/histplot.png"); pixSaveTiled(pixp, pixa, 1.0, 0, 20, 1); pixt1 = pixaDisplay(pixa, 0, 0); snprintf(textstr, sizeof(textstr), "Scorefract = %3.1f ........... Thresh = %d", scorefract, thresh); pixt2 = pixAddSingleTextblock(pixt1, bmf, textstr, 0x00ff0000, L_ADD_BELOW, NULL); pixDisplay(pixt2, 100, 100); snprintf(textstr, sizeof(textstr), "/tmp/otsu.%d.png", i); pixWrite(textstr, pixt2, IFF_PNG); pixDestroy(&pixb); pixDestroy(&pixp); pixDestroy(&pixt1); pixDestroy(&pixt2); pixaDestroy(&pixa); } pixa = pixaCreate(2); for (i = 0; i < 2; i++) { scorefract = 0.1 * i; pixOtsuAdaptiveThreshold(pixg, 300, 300, 0, 0, scorefract, NULL, &pixb); pixb2 = pixAddBlackOrWhiteBorder(pixb, 2, 2, 2, 2, L_GET_BLACK_VAL); snprintf(textstr, sizeof(textstr), "Scorefract = %3.1f", scorefract); pixb3 = pixAddSingleTextblock(pixb2, bmf, textstr, 1, L_ADD_BELOW, NULL); pixSaveTiled(pixb3, pixa, 2, (i + 1) % 1, 20, 32); pixDestroy(&pixb); pixDestroy(&pixb2); } pixb = pixaDisplay(pixa, 0, 0); pixWrite("/tmp/otsu-tiled.jpg", pixb, IFF_PNG); pixDestroy(&pixb); pixaDestroy(&pixa); bmfDestroy(&bmf); pixDestroy(&pixs); pixDestroy(&pixg); return 0; }
static PIX * shearTest(PIX *pixs, l_int32 reduction) { l_int32 w, h, d; PIX *pixt1, *pixt2, *pixd; PIXA *pixa; PROCNAME("shearTest"); pixa = pixaCreate(0); pixGetDimensions(pixs, &w, &h, &d); pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 32); pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixHShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixHShear(NULL, pixs, h / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); if (!pixGetColormap(pixs)) { pixt1 = pixCopy(NULL, pixs); pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixCopy(NULL, pixs); pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixCopy(NULL, pixs); pixHShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixCopy(NULL, pixs); pixHShearIP(pixt2, h / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32); pixDestroy(&pixt1); pixDestroy(&pixt2); } if (d == 8 || d == 32 || pixGetColormap(pixs)) { pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixHShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixHShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); } pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixVShear(NULL, pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixVShear(NULL, pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); if (!pixGetColormap(pixs)) { pixt1 = pixCopy(NULL, pixs); pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixCopy(NULL, pixs); pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixCopy(NULL, pixs); pixVShearIP(pixt1, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixCopy(NULL, pixs); pixVShearIP(pixt2, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 32); pixDestroy(&pixt1); pixDestroy(&pixt2); } if (d == 8 || d == 32 || pixGetColormap(pixs)) { pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt1, pixa, reduction, 1, 20, 0); pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_WHITE); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); pixt1 = pixVShearLI(pixs, 0, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt1, pixa, reduction, 0, 20, 0); pixt2 = pixVShearLI(pixs, w / 2, ANGLE1, L_BRING_IN_BLACK); pixSaveTiled(pixt2, pixa, reduction, 0, 20, 0); pixDestroy(&pixt1); pixDestroy(&pixt2); } pixd = pixaDisplay(pixa, 0, 0); pixaDestroy(&pixa); return pixd; }
int main(int argc, char **argv) { const char *name; l_int32 i, n; BOX *box; PIX *pix0, *pix1, *pixd; PIXA *pixa; SARRAY *sa1, *sa2, *sa3, *sa4; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; /* ---------------- Find all the jpg and tif images --------------- */ sa1 = getSortedPathnamesInDirectory(".", ".jpg", 0, 0); sa2 = getSortedPathnamesInDirectory(".", ".tif", 0, 0); sa3 = sarraySelectByRange(sa1, 0, 9); sa4 = sarraySelectByRange(sa2, 0, 9); sarrayConcatenate(sa3, sa4); n = sarrayGetCount(sa3); sarrayDestroy(&sa1); sarrayDestroy(&sa2); sarrayDestroy(&sa4); /* ---------------- Use replace to fill up a pixa -------------------*/ pixa = pixaCreate(1); pixaExtendArrayToSize(pixa, n); if ((pix0 = pixRead("marge.jpg")) == NULL) rp->success = FALSE; pix1 = pixScaleToSize(pix0, 144, 108); /* scale 0.25 */ pixDestroy(&pix0); pixaInitFull(pixa, pix1, NULL); /* fill it up */ pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixWrite("/tmp/regout/pix1.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pix1); pixDestroy(&pixd); /* ---------------- And again with jpgs and tifs -------------------*/ for (i = 0; i < n; i++) { name = sarrayGetString(sa3, i, L_NOCOPY); if ((pix0 = pixRead(name)) == NULL) rp->success = FALSE; pix1 = pixScaleToSize(pix0, 144, 108); pixaReplacePix(pixa, i, pix1, NULL); pixDestroy(&pix0); } pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); pixDisplayWithTitle(pixd, 400, 100, NULL, rp->display); pixWrite("/tmp/regout/pix2.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); /* ---------------- And again, reversing the order ------------------*/ box = boxCreate(0, 0, 0, 0); pixaInitFull(pixa, NULL, box); boxDestroy(&box); for (i = 0; i < n; i++) { name = sarrayGetString(sa3, i, L_NOCOPY); if ((pix0 = pixRead(name)) == NULL) rp->success = FALSE; pix1 = pixScaleToSize(pix0, 144, 108); pixaReplacePix(pixa, n - 1 - i, pix1, NULL); pixDestroy(&pix0); } pixd = pixaDisplayTiledInRows(pixa, 32, 1000, 1.0, 0, 25, 2); pixDisplayWithTitle(pixd, 700, 100, NULL, rp->display); pixWrite("/tmp/regout/pix3.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); sarrayDestroy(&sa3); pixaDestroy(&pixa); return regTestCleanup(rp); }
int main(int argc, char **argv) { l_int32 w, h, ystart, yend, y, ymax, ymid, i, window, sum1, sum2, rankx; l_uint32 uval; l_float32 ave, rankval, maxvar, variance, norm, conf, angle, radangle; NUMA *na1; PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7; PIXA *pixa; static char mainName[] = "findbinding"; if (argc != 1) return ERROR_INT(" Syntax: findbinding", mainName, 1); lept_mkdir("lept/binding"); pixa = pixaCreate(0); pix1 = pixRead("binding-example.45.jpg"); pix2 = pixConvertTo8(pix1, 0); /* Find the skew angle */ pix3 = pixConvertTo1(pix2, 150); pixFindSkewSweepAndSearch(pix3, &angle, &conf, 2, 2, 7.0, 1.0, 0.01); fprintf(stderr, "angle = %f, conf = %f\n", angle, conf); /* Deskew, bringing in black pixels at the edges */ if (L_ABS(angle) < 0.1 || conf < 1.5) { pix4 = pixClone(pix2); } else { radangle = 3.1416 * angle / 180.0; pix4 = pixRotate(pix2, radangle, L_ROTATE_AREA_MAP, L_BRING_IN_BLACK, 0, 0); } /* Rotate 90 degrees to make binding horizontal */ pix5 = pixRotateOrth(pix4, 1); /* Sort pixels in each row by their gray value. * Dark pixels on the left, light ones on the right. */ pix6 = pixRankRowTransform(pix5); pixDisplay(pix5, 0, 0); pixDisplay(pix6, 550, 0); pixaAddPix(pixa, pix4, L_COPY); pixaAddPix(pixa, pix5, L_COPY); pixaAddPix(pixa, pix6, L_COPY); /* Make an a priori estimate of the y-interval within which the * binding will be found. The search will be done in this interval. */ pixGetDimensions(pix6, &w, &h, NULL); ystart = 0.25 * h; yend = 0.75 * h; /* Choose a very light rank value; close to white, which * corresponds to a column in pix6 near the right side. */ rankval = 0.98; rankx = (l_int32)(w * rankval); /* Investigate variance in a small window (vertical, size = 5) * of the pixels in that column. These are the %rankval * pixels in each raster of pix6. Find the y-location of * maximum variance. */ window = 5; norm = 1.0 / window; maxvar = 0.0; na1 = numaCreate(0); numaSetParameters(na1, ystart, 1); for (y = ystart; y <= yend; y++) { sum1 = sum2 = 0; for (i = 0; i < window; i++) { pixGetPixel(pix6, rankx, y + i, &uval); sum1 += uval; sum2 += uval * uval; } ave = norm * sum1; variance = norm * sum2 - ave * ave; numaAddNumber(na1, variance); ymid = y + window / 2; if (variance > maxvar) { maxvar = variance; ymax = ymid; } } /* Plot the windowed variance as a function of the y-value * of the window location */ fprintf(stderr, "maxvar = %f, ymax = %d\n", maxvar, ymax); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/binding/root", NULL); pix7 = pixRead("/tmp/lept/binding/root.png"); pixDisplay(pix7, 0, 800); pixaAddPix(pixa, pix7, L_COPY); /* Superimpose the variance plot over the image. * The variance peak is at the binding. */ pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, w - 120, 100, 1, 0x0000ff00); pixDisplay(pix5, 1050, 0); pixaAddPix(pixa, pix5, L_COPY); /* Bundle the results up in a pdf */ fprintf(stderr, "Writing pdf output file: /tmp/lept/binding/binding.pdf\n"); pixaConvertToPdf(pixa, 45, 1.0, 0, 0, "Binding locator", "/tmp/lept/binding/binding.pdf"); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); pixDestroy(&pix7); pixaDestroy(&pixa); numaDestroy(&na1); return 0; }
main(int argc, char **argv) { char *selname; l_int32 i, j, nsels, sx, sy; l_float32 fact, time; GPLOT *gplot; NUMA *na1, *na2, *na3, *na4, *nac1, *nac2, *nac3, *nac4, *nax; PIX *pixs, *pixt; PIXA *pixa; SEL *sel; SELA *selalinear; static char mainName[] = "dwamorph2_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: dwamorph2_reg", mainName, 1)); if ((pixs = pixRead("feyn-fract.tif")) == NULL) exit(ERROR_INT("pix not made", mainName, 1)); pixt = pixCreateTemplate(pixs); selalinear = selaAddDwaLinear(NULL); nsels = selaGetCount(selalinear); fact = 1000. / (l_float32)NTIMES; /* converts to time in msec */ na1 = numaCreate(64); na2 = numaCreate(64); na3 = numaCreate(64); na4 = numaCreate(64); /* --------- dilation ----------*/ for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixDilate(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixDilateCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_DILATE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixDilateCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nax = numaMakeSequence(2, 1, nsels / 2); nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/junkdilate", GPLOT_PNG, "Dilation time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- erosion ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixErode(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixErodeCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_ERODE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixErodeCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/junkerode", GPLOT_PNG, "Erosion time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- opening ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixOpen(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixOpenCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_OPEN, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixOpenCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/junkopen", GPLOT_PNG, "Opening time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- closing ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixClose(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixCloseCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_CLOSE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixCloseCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/junkclose", GPLOT_PNG, "Closing time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); numaDestroy(&nax); selaDestroy(&selalinear); pixDestroy(&pixt); pixDestroy(&pixs); /* Display the results together */ pixa = pixaCreate(0); pixs = pixRead("/tmp/junkdilate.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/junkerode.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/junkopen.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/junkclose.png"); pixaAddPix(pixa, pixs, L_INSERT); pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 40, 3); pixWrite("/tmp/junktimings.png", pixt, IFF_PNG); pixDisplay(pixt, 100, 100); pixDestroy(&pixt); pixaDestroy(&pixa); return 0; }
/*! * pixaDisplayTiled() * * Input: pixa * maxwidth (of output image) * background (0 for white, 1 for black) * spacing * Return: pix of tiled images, or null on error * * Notes: * (1) This saves a pixa to a single image file of width not to * exceed maxwidth, with background color either white or black, * and with each subimage spaced on a regular lattice. * (2) The lattice size is determined from the largest width and height, * separately, of all pix in the pixa. * (3) All pix in the pixa must be of equal depth. * (4) If any pix has a colormap, all pix are rendered in rgb. * (5) Careful: because no components are omitted, this is * dangerous if there are thousands of small components and * one or more very large one, because the size of the * resulting pix can be huge! */ PIX * pixaDisplayTiled(PIXA *pixa, l_int32 maxwidth, l_int32 background, l_int32 spacing) { l_int32 w, h, wmax, hmax, wd, hd, d, hascmap; l_int32 i, j, n, ni, ncols, nrows; l_int32 ystart, xstart, wt, ht; PIX *pix, *pixt, *pixd; PIXA *pixat; PROCNAME("pixaDisplayTiled"); if (!pixa) return (PIX *)ERROR_PTR("pixa not defined", procName, NULL); /* If any pix have colormaps, generate rgb */ if ((n = pixaGetCount(pixa)) == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); pixaAnyColormaps(pixa, &hascmap); if (hascmap) { pixat = pixaCreate(n); for (i = 0; i < n; i++) { pixt = pixaGetPix(pixa, i, L_CLONE); pix = pixConvertTo32(pixt); pixaAddPix(pixat, pix, L_INSERT); pixDestroy(&pixt); } } else pixat = pixaCopy(pixa, L_CLONE); /* Find the largest width and height of the subimages */ wmax = hmax = 0; for (i = 0; i < n; i++) { pix = pixaGetPix(pixat, i, L_CLONE); pixGetDimensions(pix, &w, &h, NULL); if (i == 0) d = pixGetDepth(pix); else if (d != pixGetDepth(pix)) { pixDestroy(&pix); pixaDestroy(&pixat); return (PIX *)ERROR_PTR("depths not equal", procName, NULL); } if (w > wmax) wmax = w; if (h > hmax) hmax = h; pixDestroy(&pix); } /* Get the number of rows and columns and the output image size */ spacing = L_MAX(spacing, 0); ncols = (l_int32)((l_float32)(maxwidth - spacing) / (l_float32)(wmax + spacing)); nrows = (n + ncols - 1) / ncols; wd = wmax * ncols + spacing * (ncols + 1); hd = hmax * nrows + spacing * (nrows + 1); if ((pixd = pixCreate(wd, hd, d)) == NULL) { pixaDestroy(&pixat); return (PIX *)ERROR_PTR("pixd not made", procName, NULL); } #if 0 fprintf(stderr, " nrows = %d, ncols = %d, wmax = %d, hmax = %d\n", nrows, ncols, wmax, hmax); fprintf(stderr, " space = %d, wd = %d, hd = %d, n = %d\n", space, wd, hd, n); #endif /* Reset the background color if necessary */ if ((background == 1 && d == 1) || (background == 0 && d != 1)) pixSetAll(pixd); /* Blit the images to the dest */ for (i = 0, ni = 0; i < nrows; i++) { ystart = spacing + i * (hmax + spacing); for (j = 0; j < ncols && ni < n; j++, ni++) { xstart = spacing + j * (wmax + spacing); pix = pixaGetPix(pixat, ni, L_CLONE); wt = pixGetWidth(pix); ht = pixGetHeight(pix); pixRasterop(pixd, xstart, ystart, wt, ht, PIX_SRC, pix, 0, 0); pixDestroy(&pix); } } pixaDestroy(&pixat); return pixd; }
main(int argc, char **argv) { char *str; l_int32 i, j, same, ok; l_float32 sum, avediff, rmsdiff; L_KERNEL *kel1, *kel2, *kel3, *kel4, *kelx, *kely; BOX *box; PIX *pix, *pixs, *pixb, *pixg, *pixr, *pixd, *pixp, *pixt; PIX *pixt1, *pixt2, *pixt3; PIXA *pixa; SARRAY *sa; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixa = pixaCreate(0); /* Test creating from a string */ kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); pixd = kernelDisplayInPix(kel1, 41, 2); pixWrite("/tmp/pixkern.png", pixd, IFF_PNG); regTestCheckFile(rp, "/tmp/pixkern.png"); /* 0 */ pixSaveTiled(pixd, pixa, 1, 1, 20, 8); pixDestroy(&pixd); kernelDestroy(&kel1); /* Test read/write for kernel. Note that both get * compared to the same golden file, which is * overwritten with a copy of /tmp/kern2.kel */ kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); kernelWrite("/tmp/kern1.kel", kel1); regTestCheckFile(rp, "/tmp/kern1.kel"); /* 1 */ kel2 = kernelRead("/tmp/kern1.kel"); kernelWrite("/tmp/kern2.kel", kel2); regTestCheckFile(rp, "/tmp/kern2.kel"); /* 2 */ regTestCompareFiles(rp, 1, 2); /* 3 */ kernelDestroy(&kel1); kernelDestroy(&kel2); /* Test creating from a file */ sa = sarrayCreate(0); sarrayAddString(sa, (char *)"# small 3x3 kernel", L_COPY); sarrayAddString(sa, (char *)"3 5", L_COPY); sarrayAddString(sa, (char *)"1 2", L_COPY); sarrayAddString(sa, (char *)"20.5 50 80 50 20", L_COPY); sarrayAddString(sa, (char *)"82. 120 180 120 80", L_COPY); sarrayAddString(sa, (char *)"22.1 50 80 50 20", L_COPY); str = sarrayToString(sa, 1); l_binaryWrite("/tmp/kernfile.kel", "w", str, strlen(str)); kel2 = kernelCreateFromFile("/tmp/kernfile.kel"); pixd = kernelDisplayInPix(kel2, 41, 2); pixSaveTiled(pixd, pixa, 1, 1, 20, 0); pixWrite("/tmp/ker1.png", pixd, IFF_PNG); regTestCheckFile(rp, "/tmp/ker1.png"); /* 4 */ pixDestroy(&pixd); sarrayDestroy(&sa); lept_free(str); kernelDestroy(&kel2); /* Test creating from a pix */ pixt = pixCreate(5, 3, 8); pixSetPixel(pixt, 0, 0, 20); pixSetPixel(pixt, 1, 0, 50); pixSetPixel(pixt, 2, 0, 80); pixSetPixel(pixt, 3, 0, 50); pixSetPixel(pixt, 4, 0, 20); pixSetPixel(pixt, 0, 1, 80); pixSetPixel(pixt, 1, 1, 120); pixSetPixel(pixt, 2, 1, 180); pixSetPixel(pixt, 3, 1, 120); pixSetPixel(pixt, 4, 1, 80); pixSetPixel(pixt, 0, 0, 20); pixSetPixel(pixt, 1, 2, 50); pixSetPixel(pixt, 2, 2, 80); pixSetPixel(pixt, 3, 2, 50); pixSetPixel(pixt, 4, 2, 20); kel3 = kernelCreateFromPix(pixt, 1, 2); pixd = kernelDisplayInPix(kel3, 41, 2); pixSaveTiled(pixd, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker2.png", pixd, IFF_PNG); regTestCheckFile(rp, "/tmp/ker2.png"); /* 5 */ pixDestroy(&pixd); pixDestroy(&pixt); kernelDestroy(&kel3); /* Test convolution with kel1 */ pixs = pixRead("test24.jpg"); pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN); pixSaveTiled(pixg, pixa, 1, 1, 20, 0); kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr); pixd = pixConvolve(pixg, kel1, 8, 1); pixSaveTiled(pixd, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker3.png", pixd, IFF_PNG); regTestCheckFile(rp, "/tmp/ker3.png"); /* 6 */ pixDestroy(&pixs); pixDestroy(&pixg); pixDestroy(&pixd); kernelDestroy(&kel1); /* Test convolution with flat rectangular kel; also test * block convolution with tiling. */ pixs = pixRead("test24.jpg"); pixg = pixScaleRGBToGrayFast(pixs, 3, COLOR_GREEN); kel2 = makeFlatKernel(11, 11, 5, 5); pixd = pixConvolve(pixg, kel2, 8, 1); pixSaveTiled(pixd, pixa, 1, 1, 20, 0); pixWrite("/tmp/ker4.png", pixd, IFF_PNG); regTestCheckFile(rp, "/tmp/ker4.png"); /* 7 */ pixt = pixBlockconv(pixg, 5, 5); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker5.png", pixt, IFF_PNG); regTestCheckFile(rp, "/tmp/ker5.png"); /* 8 */ if (rp->display) pixCompareGray(pixd, pixt, L_COMPARE_ABS_DIFF, GPLOT_X11, NULL, NULL, NULL, NULL); pixt2 = pixBlockconvTiled(pixg, 5, 5, 3, 6); pixSaveTiled(pixt2, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker5a.png", pixt2, IFF_PNG); regTestCheckFile(rp, "/tmp/ker5a.png"); /* 9 */ pixDestroy(&pixt2); ok = TRUE; for (i = 1; i <= 7; i++) { for (j = 1; j <= 7; j++) { if (i == 1 && j == 1) continue; pixt2 = pixBlockconvTiled(pixg, 5, 5, j, i); pixEqual(pixt2, pixd, &same); if (!same) { fprintf(stderr," Error for nx = %d, ny = %d\n", j, i); ok = FALSE; } pixDestroy(&pixt2); } } if (ok) fprintf(stderr, "OK: Tiled results identical to pixConvolve()\n"); else fprintf(stderr, "ERROR: Tiled results not identical to pixConvolve()\n"); pixDestroy(&pixs); pixDestroy(&pixg); pixDestroy(&pixd); pixDestroy(&pixt); kernelDestroy(&kel2); /* Do another flat rectangular test; this time with white at edge. * About 1% of the pixels near the image edge differ by 1 between * the pixConvolve() and pixBlockconv(). For what it's worth, * pixConvolve() gives the more accurate result; namely, 255 for * pixels at the edge. */ pix = pixRead("pageseg1.tif"); box = boxCreate(100, 100, 2260, 3160); pixb = pixClipRectangle(pix, box, NULL); pixs = pixScaleToGray4(pixb); kel3 = makeFlatKernel(7, 7, 3, 3); startTimer(); pixt = pixConvolve(pixs, kel3, 8, 1); fprintf(stderr, "Generic convolution time: %5.3f sec\n", stopTimer()); pixSaveTiled(pixt, pixa, 1, 1, 20, 0); pixWrite("/tmp/conv1.png", pixt, IFF_PNG); regTestCheckFile(rp, "/tmp/conv1.png"); /* 10 */ startTimer(); pixt2 = pixBlockconv(pixs, 3, 3); fprintf(stderr, "Flat block convolution time: %5.3f sec\n", stopTimer()); pixSaveTiled(pixt2, pixa, 1, 0, 20, 0); pixWrite("/tmp/conv2.png", pixt2, IFF_PNG); /* ditto */ regTestCheckFile(rp, "/tmp/conv2.png"); /* 11 */ pixCompareGray(pixt, pixt2, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL, &avediff, &rmsdiff, NULL); #ifndef _WIN32 sleep(1); /* give gnuplot time to write out the file */ #else Sleep(1000); #endif /* _WIN32 */ pixp = pixRead("/tmp/grayroot.png"); pixSaveTiled(pixp, pixa, 1, 0, 20, 0); pixWrite("/tmp/conv3.png", pixp, IFF_PNG); regTestCheckFile(rp, "/tmp/conv3.png"); /* 12 */ fprintf(stderr, "Ave diff = %6.4f, RMS diff = %6.4f\n", avediff, rmsdiff); if (avediff <= 0.01) fprintf(stderr, "OK: avediff = %6.4f <= 0.01\n", avediff); else fprintf(stderr, "Bad?: avediff = %6.4f > 0.01\n", avediff); pixDestroy(&pixt); pixDestroy(&pixt2); pixDestroy(&pixs); pixDestroy(&pixp); pixDestroy(&pix); pixDestroy(&pixb); boxDestroy(&box); kernelDestroy(&kel3); /* Do yet another set of flat rectangular tests, this time * on an RGB image */ pixs = pixRead("test24.jpg"); kel4 = makeFlatKernel(7, 7, 3, 3); startTimer(); pixt1 = pixConvolveRGB(pixs, kel4); fprintf(stderr, "Time 7x7 non-separable: %7.3f sec\n", stopTimer()); pixWrite("/tmp/conv4.jpg", pixt1, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/conv4.jpg"); /* 13 */ kelx = makeFlatKernel(1, 7, 0, 3); kely = makeFlatKernel(7, 1, 3, 0); startTimer(); pixt2 = pixConvolveRGBSep(pixs, kelx, kely); fprintf(stderr, "Time 7x1,1x7 separable: %7.3f sec\n", stopTimer()); pixWrite("/tmp/conv5.jpg", pixt2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/conv5.jpg"); /* 14 */ startTimer(); pixt3 = pixBlockconv(pixs, 3, 3); fprintf(stderr, "Time 7x7 blockconv: %7.3f sec\n", stopTimer()); pixWrite("/tmp/conv6.jpg", pixt3, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/conv6.jpg"); /* 15 */ regTestComparePix(rp, pixt1, pixt2); /* 16 */ regTestCompareSimilarPix(rp, pixt2, pixt3, 15, 0.0005, 0); /* 17 */ pixDestroy(&pixs); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); kernelDestroy(&kel4); kernelDestroy(&kelx); kernelDestroy(&kely); /* Test generation and convolution with gaussian kernel */ pixs = pixRead("test8.jpg"); pixSaveTiled(pixs, pixa, 1, 1, 20, 0); kel1 = makeGaussianKernel(5, 5, 3.0, 5.0); kernelGetSum(kel1, &sum); fprintf(stderr, "Sum for gaussian kernel = %f\n", sum); kernelWrite("/tmp/gauss.kel", kel1); pixt = pixConvolve(pixs, kel1, 8, 1); pixt2 = pixConvolve(pixs, kel1, 16, 0); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixSaveTiled(pixt2, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker6.png", pixt, IFF_PNG); regTestCheckFile(rp, "/tmp/ker6.png"); /* 18 */ pixDestroy(&pixt); pixDestroy(&pixt2); pixt = kernelDisplayInPix(kel1, 25, 2); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixDestroy(&pixt); kernelDestroy(&kel1); pixDestroy(&pixs); /* Test generation and convolution with separable gaussian kernel */ pixs = pixRead("test8.jpg"); pixSaveTiled(pixs, pixa, 1, 1, 20, 0); makeGaussianKernelSep(5, 5, 3.0, 5.0, &kelx, &kely); kernelGetSum(kelx, &sum); fprintf(stderr, "Sum for x gaussian kernel = %f\n", sum); kernelGetSum(kely, &sum); fprintf(stderr, "Sum for y gaussian kernel = %f\n", sum); kernelWrite("/tmp/gauss.kelx", kelx); kernelWrite("/tmp/gauss.kely", kely); pixt = pixConvolveSep(pixs, kelx, kely, 8, 1); pixt2 = pixConvolveSep(pixs, kelx, kely, 16, 0); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixSaveTiled(pixt2, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker7.png", pixt, IFF_PNG); regTestCheckFile(rp, "/tmp/ker7.png"); /* 19 */ pixDestroy(&pixt); pixDestroy(&pixt2); pixt = kernelDisplayInPix(kelx, 25, 2); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixDestroy(&pixt); pixt = kernelDisplayInPix(kely, 25, 2); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixDestroy(&pixt); kernelDestroy(&kelx); kernelDestroy(&kely); pixDestroy(&pixs); /* Test generation and convolution with diff of gaussians kernel */ /* pixt = pixRead("marge.jpg"); pixs = pixConvertRGBToLuminance(pixt); pixDestroy(&pixt); */ pixs = pixRead("test8.jpg"); pixSaveTiled(pixs, pixa, 1, 1, 20, 0); kel1 = makeDoGKernel(7, 7, 1.5, 2.7); kernelGetSum(kel1, &sum); fprintf(stderr, "Sum for DoG kernel = %f\n", sum); kernelWrite("/tmp/dog.kel", kel1); pixt = pixConvolve(pixs, kel1, 8, 0); /* pixInvert(pixt, pixt); */ pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixWrite("/tmp/ker8.png", pixt, IFF_PNG); regTestCheckFile(rp, "/tmp/ker8.png"); /* 20 */ pixDestroy(&pixt); pixt = kernelDisplayInPix(kel1, 20, 2); pixSaveTiled(pixt, pixa, 1, 0, 20, 0); pixDestroy(&pixt); kernelDestroy(&kel1); pixDestroy(&pixs); pixd = pixaDisplay(pixa, 0, 0); pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixWrite("/tmp/kernel.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixaDestroy(&pixa); return regTestCleanup(rp); }
/*! * pixaDisplayTiledInRows() * * Input: pixa * outdepth (output depth: 1, 8 or 32 bpp) * maxwidth (of output image) * scalefactor (applied to every pix; use 1.0 for no scaling) * background (0 for white, 1 for black; this is the color * of the spacing between the images) * spacing (between images, and on outside) * border (width of black border added to each image; * use 0 for no border) * Return: pixd (of tiled images), or null on error * * Notes: * (1) This saves a pixa to a single image file of width not to * exceed maxwidth, with background color either white or black, * and with each row tiled such that the top of each pix is * aligned and separated by 'spacing' from the next one. * A black border can be added to each pix. * (2) All pix are converted to outdepth; existing colormaps are removed. * (3) This does a reasonably spacewise-efficient job of laying * out the individual pix images into a tiled composite. */ PIX * pixaDisplayTiledInRows(PIXA *pixa, l_int32 outdepth, l_int32 maxwidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border) { l_int32 h; /* cumulative height over all the rows */ l_int32 w; /* cumulative height in the current row */ l_int32 bordval, wtry, wt, ht; l_int32 irow; /* index of current pix in current row */ l_int32 wmaxrow; /* width of the largest row */ l_int32 maxh; /* max height in row */ l_int32 i, j, index, n, x, y, nrows, ninrow; NUMA *nainrow; /* number of pix in the row */ NUMA *namaxh; /* height of max pix in the row */ PIX *pix, *pixn, *pixt, *pixd; PIXA *pixan; PROCNAME("pixaDisplayTiledInRows"); if (!pixa) return (PIX *)ERROR_PTR("pixa not defined", procName, NULL); if (outdepth != 1 && outdepth != 8 && outdepth != 32) return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL); if (border < 0) border = 0; if (scalefactor <= 0.0) scalefactor = 1.0; if ((n = pixaGetCount(pixa)) == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); /* Normalize depths, scale, remove colormaps; optionally add border */ pixan = pixaCreate(n); bordval = (outdepth == 1) ? 1 : 0; for (i = 0; i < n; i++) { if ((pix = pixaGetPix(pixa, i, L_CLONE)) == NULL) continue; if (outdepth == 1) pixn = pixConvertTo1(pix, 128); else if (outdepth == 8) pixn = pixConvertTo8(pix, FALSE); else /* outdepth == 32 */ pixn = pixConvertTo32(pix); pixDestroy(&pix); if (scalefactor != 1.0) pixt = pixScale(pixn, scalefactor, scalefactor); else pixt = pixClone(pixn); if (border) pixd = pixAddBorder(pixt, border, bordval); else pixd = pixClone(pixt); pixDestroy(&pixn); pixDestroy(&pixt); pixaAddPix(pixan, pixd, L_INSERT); } if (pixaGetCount(pixan) != n) { n = pixaGetCount(pixan); L_WARNING_INT("only got %d components", procName, n); if (n == 0) { pixaDestroy(&pixan); return (PIX *)ERROR_PTR("no components", procName, NULL); } } /* Compute parameters for layout */ nainrow = numaCreate(0); namaxh = numaCreate(0); wmaxrow = 0; w = h = spacing; maxh = 0; /* max height in row */ for (i = 0, irow = 0; i < n; i++, irow++) { pixaGetPixDimensions(pixan, i, &wt, &ht, NULL); wtry = w + wt + spacing; if (wtry > maxwidth) { /* end the current row and start next one */ numaAddNumber(nainrow, irow); numaAddNumber(namaxh, maxh); wmaxrow = L_MAX(wmaxrow, w); h += maxh + spacing; irow = 0; w = wt + 2 * spacing; maxh = ht; } else { w = wtry; maxh = L_MAX(maxh, ht); } } /* Enter the parameters for the last row */ numaAddNumber(nainrow, irow); numaAddNumber(namaxh, maxh); wmaxrow = L_MAX(wmaxrow, w); h += maxh + spacing; if ((pixd = pixCreate(wmaxrow, h, outdepth)) == NULL) { numaDestroy(&nainrow); numaDestroy(&namaxh); pixaDestroy(&pixan); return (PIX *)ERROR_PTR("pixd not made", procName, NULL); } /* Reset the background color if necessary */ if ((background == 1 && outdepth == 1) || (background == 0 && outdepth != 1)) pixSetAll(pixd); /* Blit the images to the dest */ nrows = numaGetCount(nainrow); y = spacing; for (i = 0, index = 0; i < nrows; i++) { /* over rows */ numaGetIValue(nainrow, i, &ninrow); numaGetIValue(namaxh, i, &maxh); x = spacing; for (j = 0; j < ninrow; j++, index++) { /* over pix in row */ pix = pixaGetPix(pixan, index, L_CLONE); pixGetDimensions(pix, &wt, &ht, NULL); pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pix, 0, 0); pixDestroy(&pix); x += wt + spacing; } y += maxh + spacing; } numaDestroy(&nainrow); numaDestroy(&namaxh); pixaDestroy(&pixan); return pixd; }
main(int argc, char **argv) { l_float32 sum, sumx, sumy, diff; FPIX *fpixs, *fpixs2, *fpixs3, *fpixt1, *fpixt2, *fpixg, *fpixd; L_KERNEL *kel, *kelx, *kely; PIX *pixs, *pixs2, *pixs3, *pixt, *pixd, *pixg; PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6; PIXA *pixa; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixa = pixaCreate(0); /* Gaussian kernel */ kel = makeGaussianKernel(5, 5, 3.0, 4.0); kernelGetSum(kel, &sum); if (rp->display) fprintf(stderr, "Sum for 2d gaussian kernel = %f\n", sum); pixt = kernelDisplayInPix(kel, 41, 2); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 0 */ pixSaveTiled(pixt, pixa, 1, 1, 20, 8); pixDestroy(&pixt); /* Separable gaussian kernel */ makeGaussianKernelSep(5, 5, 3.0, 4.0, &kelx, &kely); kernelGetSum(kelx, &sumx); if (rp->display) fprintf(stderr, "Sum for x gaussian kernel = %f\n", sumx); kernelGetSum(kely, &sumy); if (rp->display) fprintf(stderr, "Sum for y gaussian kernel = %f\n", sumy); if (rp->display) fprintf(stderr, "Sum for x * y gaussian kernel = %f\n", sumx * sumy); pixt = kernelDisplayInPix(kelx, 41, 2); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 1 */ pixSaveTiled(pixt, pixa, 1, 0, 20, 8); pixDestroy(&pixt); pixt = kernelDisplayInPix(kely, 41, 2); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 2 */ pixSaveTiled(pixt, pixa, 1, 0, 20, 8); pixDestroy(&pixt); /* Use pixRasterop() to generate source image */ pixs = pixRead("test8.jpg"); pixs2 = pixRead("karen8.jpg"); pixRasterop(pixs, 150, 125, 150, 100, PIX_SRC, pixs2, 75, 100); regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG); /* 3 */ /* Convolution directly with pix */ pixt1 = pixConvolve(pixs, kel, 8, 1); regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG); /* 4 */ pixSaveTiled(pixt1, pixa, 1, 1, 20, 8); pixt2 = pixConvolveSep(pixs, kelx, kely, 8, 1); regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* 5 */ pixSaveTiled(pixt2, pixa, 1, 0, 20, 8); /* Convolution indirectly with fpix, using fpixRasterop() * to generate the source image. */ fpixs = pixConvertToFPix(pixs, 3); fpixs2 = pixConvertToFPix(pixs2, 3); fpixRasterop(fpixs, 150, 125, 150, 100, fpixs2, 75, 100); fpixt1 = fpixConvolve(fpixs, kel, 1); pixt3 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 1); regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG); /* 6 */ pixSaveTiled(pixt3, pixa, 1, 1, 20, 8); fpixt2 = fpixConvolveSep(fpixs, kelx, kely, 1); pixt4 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 1); regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG); /* 7 */ pixSaveTiled(pixt4, pixa, 1, 0, 20, 8); pixDestroy(&pixs2); fpixDestroy(&fpixs2); fpixDestroy(&fpixt1); fpixDestroy(&fpixt2); /* Comparison of results */ pixCompareGray(pixt1, pixt2, L_COMPARE_ABS_DIFF, 0, NULL, &diff, NULL, NULL); if (rp->display) fprintf(stderr, "Ave diff of pixConvolve and pixConvolveSep: %f\n", diff); pixCompareGray(pixt3, pixt4, L_COMPARE_ABS_DIFF, 0, NULL, &diff, NULL, NULL); if (rp->display) fprintf(stderr, "Ave diff of fpixConvolve and fpixConvolveSep: %f\n", diff); pixCompareGray(pixt1, pixt3, L_COMPARE_ABS_DIFF, 0, NULL, &diff, NULL, NULL); if (rp->display) fprintf(stderr, "Ave diff of pixConvolve and fpixConvolve: %f\n", diff); pixCompareGray(pixt2, pixt4, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL, &diff, NULL, NULL); if (rp->display) fprintf(stderr, "Ave diff of pixConvolveSep and fpixConvolveSep: %f\n", diff); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); /* Test arithmetic operations; add in a fraction rotated by 180 */ pixs3 = pixRotate180(NULL, pixs); regTestWritePixAndCheck(rp, pixs3, IFF_JFIF_JPEG); /* 8 */ pixSaveTiled(pixs3, pixa, 1, 1, 20, 8); fpixs3 = pixConvertToFPix(pixs3, 3); fpixd = fpixLinearCombination(NULL, fpixs, fpixs3, 20.0, 5.0); fpixAddMultConstant(fpixd, 0.0, 23.174); /* multiply up in magnitude */ pixd = fpixDisplayMaxDynamicRange(fpixd); /* bring back to 8 bpp */ regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 9 */ pixSaveTiled(pixd, pixa, 1, 0, 20, 8); pixDestroy(&pixs3); fpixDestroy(&fpixs3); fpixDestroy(&fpixd); pixDestroy(&pixd); pixDestroy(&pixs); fpixDestroy(&fpixs); /* Save the comparison graph; gnuplot should have made it by now! */ #ifndef _WIN32 sleep(2); #else Sleep(2000); #endif /* _WIN32 */ pixt5 = pixRead("/tmp/grayroot.png"); regTestWritePixAndCheck(rp, pixt5, IFF_PNG); /* 10 */ pixSaveTiled(pixt5, pixa, 1, 1, 20, 8); pixDestroy(&pixt5); /* Display results */ pixd = pixaDisplay(pixa, 0, 0); regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 11 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixd); pixaDestroy(&pixa); /* Test some more convolutions, with sampled output. First on pix */ pixa = pixaCreate(0); pixs = pixRead("1555-7.jpg"); pixg = pixConvertTo8(pixs, 0); l_setConvolveSampling(5, 5); pixt1 = pixConvolve(pixg, kel, 8, 1); regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG); /* 12 */ pixSaveTiled(pixt1, pixa, 1, 1, 20, 32); pixt2 = pixConvolveSep(pixg, kelx, kely, 8, 1); regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG); /* 13 */ pixSaveTiled(pixt2, pixa, 1, 0, 20, 32); pixt3 = pixConvolveRGB(pixs, kel); regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG); /* 14 */ pixSaveTiled(pixt3, pixa, 1, 0, 20, 32); pixt4 = pixConvolveRGBSep(pixs, kelx, kely); regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG); /* 15 */ pixSaveTiled(pixt4, pixa, 1, 0, 20, 32); /* Then on fpix */ fpixg = pixConvertToFPix(pixg, 1); fpixt1 = fpixConvolve(fpixg, kel, 1); pixt5 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 0); regTestWritePixAndCheck(rp, pixt5, IFF_JFIF_JPEG); /* 16 */ pixSaveTiled(pixt5, pixa, 1, 1, 20, 32); fpixt2 = fpixConvolveSep(fpixg, kelx, kely, 1); pixt6 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 0); regTestWritePixAndCheck(rp, pixt6, IFF_JFIF_JPEG); /* 17 */ pixSaveTiled(pixt2, pixa, 1, 0, 20, 32); regTestCompareSimilarPix(rp, pixt1, pixt5, 2, 0.00, 0); /* 18 */ regTestCompareSimilarPix(rp, pixt2, pixt6, 2, 0.00, 0); /* 19 */ pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); fpixDestroy(&fpixg); fpixDestroy(&fpixt1); fpixDestroy(&fpixt2); pixd = pixaDisplay(pixa, 0, 0); regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 20 */ pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display); pixDestroy(&pixd); pixaDestroy(&pixa); regTestCleanup(rp); pixDestroy(&pixs); pixDestroy(&pixg); kernelDestroy(&kel); kernelDestroy(&kelx); kernelDestroy(&kely); return 0; }
/*! * pixaaDisplay() * * Input: pixaa * w, h (if set to 0, determines the size from the * b.b. of the components in pixaa) * Return: pix, or null on error * * Notes: * (1) Each pix of the pixaa is displayed at the location given by * its box, translated by the box of the containing pixa * if it exists. */ PIX * pixaaDisplay(PIXAA *pixaa, l_int32 w, l_int32 h) { l_int32 i, j, n, nbox, na, d, wmax, hmax, x, y, xb, yb, wb, hb; BOXA *boxa1; /* top-level boxa */ BOXA *boxa; PIX *pixt, *pixd; PIXA *pixa; PROCNAME("pixaaDisplay"); if (!pixaa) return (PIX *)ERROR_PTR("pixaa not defined", procName, NULL); n = pixaaGetCount(pixaa); if (n == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); /* If w and h not input, determine the minimum size required * to contain the origin and all c.c. */ boxa1 = pixaaGetBoxa(pixaa, L_CLONE); nbox = boxaGetCount(boxa1); if (w == 0 || h == 0) { if (nbox == n) boxaGetExtent(boxa1, &w, &h, NULL); else { /* have to use the lower-level boxa for each pixa */ wmax = hmax = 0; for (i = 0; i < n; i++) { pixa = pixaaGetPixa(pixaa, i, L_CLONE); boxa = pixaGetBoxa(pixa, L_CLONE); boxaGetExtent(boxa, &w, &h, NULL); wmax = L_MAX(wmax, w); hmax = L_MAX(hmax, h); pixaDestroy(&pixa); boxaDestroy(&boxa); } w = wmax; h = hmax; } } /* Get depth from first pix */ pixa = pixaaGetPixa(pixaa, 0, L_CLONE); pixt = pixaGetPix(pixa, 0, L_CLONE); d = pixGetDepth(pixt); pixaDestroy(&pixa); pixDestroy(&pixt); if ((pixd = pixCreate(w, h, d)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); x = y = 0; for (i = 0; i < n; i++) { pixa = pixaaGetPixa(pixaa, i, L_CLONE); if (nbox == n) boxaGetBoxGeometry(boxa1, i, &x, &y, NULL, NULL); na = pixaGetCount(pixa); for (j = 0; j < na; j++) { pixaGetBoxGeometry(pixa, j, &xb, &yb, &wb, &hb); pixt = pixaGetPix(pixa, j, L_CLONE); pixRasterop(pixd, x + xb, y + yb, wb, hb, PIX_PAINT, pixt, 0, 0); pixDestroy(&pixt); } pixaDestroy(&pixa); } boxaDestroy(&boxa1); return pixd; }
int main(int argc, char **argv) { l_int32 index; l_uint32 val32; BOX *box, *box1, *box2, *box3, *box4, *box5; BOXA *boxa; L_KERNEL *kel; PIX *pixs, *pixg, *pixb, *pixd, *pixt, *pix1, *pix2, *pix3, *pix4; PIXA *pixa; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixa = pixaCreate(0); /* Color non-white pixels on RGB */ pixs = pixRead("lucasta-frag.jpg"); pixt = pixConvert8To32(pixs); box = boxCreate(120, 30, 200, 200); pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 0 */ pixaAddPix(pixa, pixt, L_COPY); pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 1 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Color non-white pixels on colormap */ pixt = pixThresholdTo4bpp(pixs, 6, 1); box = boxCreate(120, 30, 200, 200); pixColorGray(pixt, box, L_PAINT_DARK, 220, 0, 0, 255); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 2 */ pixaAddPix(pixa, pixt, L_COPY); pixColorGray(pixt, NULL, L_PAINT_DARK, 220, 255, 100, 100); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 3 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Color non-black pixels on RGB */ pixt = pixConvert8To32(pixs); box = boxCreate(120, 30, 200, 200); pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 4 */ pixaAddPix(pixa, pixt, L_COPY); pixColorGray(pixt, NULL, L_PAINT_LIGHT, 80, 255, 100, 100); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 5 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Color non-black pixels on colormap */ pixt = pixThresholdTo4bpp(pixs, 6, 1); box = boxCreate(120, 30, 200, 200); pixColorGray(pixt, box, L_PAINT_LIGHT, 20, 0, 0, 255); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 6 */ pixaAddPix(pixa, pixt, L_COPY); pixColorGray(pixt, NULL, L_PAINT_LIGHT, 20, 255, 100, 100); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 7 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Add highlight color to RGB */ pixt = pixConvert8To32(pixs); box = boxCreate(507, 5, 385, 45); pixg = pixClipRectangle(pixs, box, NULL); pixb = pixThresholdToBinary(pixg, 180); pixInvert(pixb, pixb); pixDisplayWrite(pixb, 1); composeRGBPixel(50, 0, 250, &val32); pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); boxDestroy(&box); pixDestroy(&pixg); pixDestroy(&pixb); box = boxCreate(236, 107, 262, 40); pixg = pixClipRectangle(pixs, box, NULL); pixb = pixThresholdToBinary(pixg, 180); pixInvert(pixb, pixb); composeRGBPixel(250, 0, 50, &val32); pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); boxDestroy(&box); pixDestroy(&pixg); pixDestroy(&pixb); box = boxCreate(222, 208, 247, 43); pixg = pixClipRectangle(pixs, box, NULL); pixb = pixThresholdToBinary(pixg, 180); pixInvert(pixb, pixb); composeRGBPixel(60, 250, 60, &val32); pixPaintThroughMask(pixt, pixb, box->x, box->y, val32); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 8 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); pixDestroy(&pixg); pixDestroy(&pixb); /* Add highlight color to colormap */ pixt = pixThresholdTo4bpp(pixs, 5, 1); cmap = pixGetColormap(pixt); pixcmapGetIndex(cmap, 255, 255, 255, &index); box = boxCreate(507, 5, 385, 45); pixSetSelectCmap(pixt, box, index, 50, 0, 250); boxDestroy(&box); box = boxCreate(236, 107, 262, 40); pixSetSelectCmap(pixt, box, index, 250, 0, 50); boxDestroy(&box); box = boxCreate(222, 208, 247, 43); pixSetSelectCmap(pixt, box, index, 60, 250, 60); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 9 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Paint lines on RGB */ pixt = pixConvert8To32(pixs); pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125); pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25); box = boxCreate(70, 80, 300, 245); pixRenderBoxArb(pixt, box, 3, 200, 200, 25); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 10 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Paint lines on colormap */ pixt = pixThresholdTo4bpp(pixs, 5, 1); pixRenderLineArb(pixt, 450, 20, 850, 320, 5, 200, 50, 125); pixRenderLineArb(pixt, 30, 40, 440, 40, 5, 100, 200, 25); box = boxCreate(70, 80, 300, 245); pixRenderBoxArb(pixt, box, 3, 200, 200, 25); regTestWritePixAndCheck(rp, pixt, IFF_PNG); /* 11 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Blend lines on RGB */ pixt = pixConvert8To32(pixs); pixRenderLineBlend(pixt, 450, 20, 850, 320, 5, 200, 50, 125, 0.35); pixRenderLineBlend(pixt, 30, 40, 440, 40, 5, 100, 200, 25, 0.35); box = boxCreate(70, 80, 300, 245); pixRenderBoxBlend(pixt, box, 3, 200, 200, 25, 0.6); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 12 */ pixaAddPix(pixa, pixt, L_INSERT); boxDestroy(&box); /* Colorize gray on cmapped image. */ pix1 = pixRead("lucasta.150.jpg"); pix2 = pixThresholdTo4bpp(pix1, 7, 1); box1 = boxCreate(73, 206, 140, 27); pixColorGrayCmap(pix2, box1, L_PAINT_LIGHT, 130, 207, 43); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 13 */ pixaAddPix(pixa, pix2, L_COPY); if (rp->display) pixPrintStreamInfo(stderr, pix2, "One box added"); box2 = boxCreate(255, 404, 197, 25); pixColorGrayCmap(pix2, box2, L_PAINT_LIGHT, 230, 67, 119); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 14 */ pixaAddPix(pixa, pix2, L_COPY); if (rp->display) pixPrintStreamInfo(stderr, pix2, "Two boxes added"); box3 = boxCreate(122, 756, 224, 22); pixColorGrayCmap(pix2, box3, L_PAINT_DARK, 230, 67, 119); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 15 */ pixaAddPix(pixa, pix2, L_COPY); if (rp->display) pixPrintStreamInfo(stderr, pix2, "Three boxes added"); box4 = boxCreate(11, 780, 147, 22); pixColorGrayCmap(pix2, box4, L_PAINT_LIGHT, 70, 137, 229); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 16 */ pixaAddPix(pixa, pix2, L_COPY); if (rp->display) pixPrintStreamInfo(stderr, pix2, "Four boxes added"); box5 = boxCreate(163, 605, 78, 22); pixColorGrayCmap(pix2, box5, L_PAINT_LIGHT, 70, 137, 229); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 17 */ pixaAddPix(pixa, pix2, L_INSERT); if (rp->display) pixPrintStreamInfo(stderr, pix2, "Five boxes added"); pixDestroy(&pix1); boxDestroy(&box1); boxDestroy(&box2); boxDestroy(&box3); boxDestroy(&box4); boxDestroy(&box5); pixDestroy(&pixs); /* Make a gray image and identify the fg pixels (val > 230) */ pixs = pixRead("feyn-fract.tif"); pix1 = pixConvertTo8(pixs, 0); kel = makeGaussianKernel(2, 2, 1.5, 1.0); pix2 = pixConvolve(pix1, kel, 8, 1); pix3 = pixThresholdToBinary(pix2, 230); boxa = pixConnComp(pix3, NULL, 8); pixDestroy(&pixs); pixDestroy(&pix1); pixDestroy(&pix3); kernelDestroy(&kel); /* Color the individual components in the gray image */ pix4 = pixColorGrayRegions(pix2, boxa, L_PAINT_DARK, 230, 255, 0, 0); regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 18 */ pixaAddPix(pixa, pix4, L_INSERT); pixDisplayWithTitle(pix4, 0, 0, NULL, rp->display); /* Threshold to 10 levels of gray */ pix3 = pixThresholdOn8bpp(pix2, 10, 1); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 19 */ pixaAddPix(pixa, pix3, L_COPY); /* Color the individual components in the cmapped image */ pix4 = pixColorGrayRegions(pix3, boxa, L_PAINT_DARK, 230, 255, 0, 0); regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 20 */ pixaAddPix(pixa, pix4, L_INSERT); pixDisplayWithTitle(pix4, 0, 100, NULL, rp->display); boxaDestroy(&boxa); /* Color the entire gray image (not component-wise) */ pixColorGray(pix2, NULL, L_PAINT_DARK, 230, 255, 0, 0); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 21 */ pixaAddPix(pixa, pix2, L_INSERT); /* Color the entire cmapped image (not component-wise) */ pixColorGray(pix3, NULL, L_PAINT_DARK, 230, 255, 0, 0); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 22 */ pixaAddPix(pixa, pix3, L_INSERT); /* Reconstruct cmapped images */ pixd = ReconstructByValue(rp, "weasel2.4c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 23 */ pixaAddPix(pixa, pixd, L_INSERT); pixd = ReconstructByValue(rp, "weasel4.11c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 24 */ pixaAddPix(pixa, pixd, L_INSERT); pixd = ReconstructByValue(rp, "weasel8.240c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 25 */ pixaAddPix(pixa, pixd, L_INSERT); /* Fake reconstruct cmapped images, with one color into a band */ pixd = FakeReconstructByBand(rp, "weasel2.4c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 26 */ pixaAddPix(pixa, pixd, L_INSERT); pixd = FakeReconstructByBand(rp, "weasel4.11c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 27 */ pixaAddPix(pixa, pixd, L_INSERT); pixd = FakeReconstructByBand(rp, "weasel8.240c.png"); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 28 */ pixaAddPix(pixa, pixd, L_INSERT); /* If in testing mode, make a pdf */ if (rp->display) { pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, "Colorize and paint", "/tmp/paint.pdf"); } pixaDestroy(&pixa); return regTestCleanup(rp); }
/*! * pixThinGeneral() * * Input: pixs (1 bpp) * type (L_THIN_FG, L_THIN_BG) * sela (of Sels for parallel composite HMTs) * maxiters (max number of iters allowed; use 0 to iterate * until completion) * Return: pixd, or null on error * * Notes: * (1) See notes in pixThin(). That function chooses among * the best of the Sels for thinning. * (2) This is a general function that takes a Sela of HMTs * that are used in parallel for thinning from each * of four directions. One iteration consists of four * such parallel thins. */ PIX * pixThinGeneral(PIX *pixs, l_int32 type, SELA *sela, l_int32 maxiters) { l_int32 i, j, r, nsels, same; PIXA *pixahmt; PIX **pixhmt; /* array owned by pixahmt; do not destroy! */ PIX *pixd, *pixt; SEL *sel, *selr; PROCNAME("pixThinGeneral"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetDepth(pixs) != 1) return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL); if (type != L_THIN_FG && type != L_THIN_BG) return (PIX *)ERROR_PTR("invalid fg/bg type", procName, NULL); if (!sela) return (PIX *)ERROR_PTR("sela not defined", procName, NULL); if (maxiters == 0) maxiters = 10000; /* Set up array of temp pix to hold hmts */ nsels = selaGetCount(sela); pixahmt = pixaCreate(nsels); for (i = 0; i < nsels; i++) { pixt = pixCreateTemplate(pixs); pixaAddPix(pixahmt, pixt, L_INSERT); } pixhmt = pixaGetPixArray(pixahmt); if (!pixhmt) return (PIX *)ERROR_PTR("pixhmt array not made", procName, NULL); #if DEBUG_SELS pixt = selaDisplayInPix(sela, 35, 3, 15, 4); pixDisplayWithTitle(pixt, 100, 100, "allsels", 1); pixDestroy(&pixt); #endif /* DEBUG_SELS */ /* Set up initial image for fg thinning */ if (type == L_THIN_FG) pixd = pixCopy(NULL, pixs); else /* bg thinning */ pixd = pixInvert(NULL, pixs); /* Thin the fg, with up to maxiters iterations */ for (i = 0; i < maxiters; i++) { pixt = pixCopy(NULL, pixd); /* test for completion */ for (r = 0; r < 4; r++) { /* over 90 degree rotations of Sels */ for (j = 0; j < nsels; j++) { /* over individual sels in sela */ sel = selaGetSel(sela, j); /* not a copy */ selr = selRotateOrth(sel, r); pixHMT(pixhmt[j], pixd, selr); selDestroy(&selr); if (j > 0) pixOr(pixhmt[0], pixhmt[0], pixhmt[j]); /* accum result */ } pixSubtract(pixd, pixd, pixhmt[0]); /* remove result */ } pixEqual(pixd, pixt, &same); pixDestroy(&pixt); if (same) { L_INFO("%d iterations to completion\n", procName, i); break; } } if (type == L_THIN_BG) pixInvert(pixd, pixd); pixaDestroy(&pixahmt); return pixd; }
int main(int argc, char **argv) { l_int32 i, j, n; l_int32 w, h, bw, bh, wpls, rval, gval, bval, same; l_uint32 pixel; l_uint32 *lines, *datas; l_float32 sum1, sum2, sum3, ave1, ave2, ave3, ave4, diff1, diff2; l_float32 var1, var2, var3; BOX *box1, *box2; NUMA *na, *na1, *na2, *na3, *na4; PIX *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd; PIXA *pixa; PTA *pta; static char mainName[] = "numa2_reg"; if (argc != 1) return ERROR_INT(" Syntax: numa2_reg", mainName, 1); /* -------------------------------------------------------------------* * Numa-windowed stats * * -------------------------------------------------------------------*/ #if DO_ALL na = numaRead("lyra-5.numa"); numaWindowedStats(na, 5, &na1, &na2, &na3, &na4); gplotSimple1(na, GPLOT_PNG, "/tmp/lyraroot6", "Original"); gplotSimple1(na1, GPLOT_PNG, "/tmp/lyraroot7", "Mean"); gplotSimple1(na2, GPLOT_PNG, "/tmp/lyraroot8", "Mean Square"); gplotSimple1(na3, GPLOT_PNG, "/tmp/lyraroot9", "Variance"); gplotSimple1(na4, GPLOT_PNG, "/tmp/lyraroot10", "RMS Difference"); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixa = pixaCreate(5); pix1 = pixRead("/tmp/lyraroot6.png"); pix2 = pixRead("/tmp/lyraroot7.png"); pix3 = pixRead("/tmp/lyraroot8.png"); pix4 = pixRead("/tmp/lyraroot9.png"); pix5 = pixRead("/tmp/lyraroot10.png"); pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix2, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix3, pixa, 1.0, 0, 25, 32); pixSaveTiled(pix4, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix5, pixa, 1.0, 0, 25, 32); pixd = pixaDisplay(pixa, 0, 0); pixDisplay(pixd, 100, 100); pixWrite("/tmp/numawindow.png", pixd, IFF_PNG); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pixd); #endif /* -------------------------------------------------------------------* * Extraction on a line * * -------------------------------------------------------------------*/ #if DO_ALL /* First, make a pretty image */ w = h = 200; pixs = pixCreate(w, h, 32); wpls = pixGetWpl(pixs); datas = pixGetData(pixs); for (i = 0; i < 200; i++) { lines = datas + i * wpls; for (j = 0; j < 200; j++) { rval = (l_int32)((255. * j) / w + (255. * i) / h); gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255; bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255; composeRGBPixel(rval, gval, bval, &pixel); lines[j] = pixel; } } pixg = pixConvertTo8(pixs, 0); /* and a grayscale version */ pixWrite("/tmp/junkpixg", pixg, IFF_PNG); pixDisplay(pixg, 450, 100); na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1); na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1); na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1); na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1); gplotSimple1(na1, GPLOT_PNG, "/tmp/extroot1", "Horizontal"); gplotSimple1(na2, GPLOT_PNG, "/tmp/extroot2", "Vertical"); gplotSimple1(na3, GPLOT_PNG, "/tmp/extroot3", "Slightly more horizontal than vertical"); gplotSimple1(na4, GPLOT_PNG, "/tmp/extroot4", "Slightly more vertical than horizontal"); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixa = pixaCreate(4); pix1 = pixRead("/tmp/extroot1.png"); pix2 = pixRead("/tmp/extroot2.png"); pix3 = pixRead("/tmp/extroot3.png"); pix4 = pixRead("/tmp/extroot4.png"); pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix2, pixa, 1.0, 0, 25, 32); pixSaveTiled(pix3, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix4, pixa, 1.0, 0, 25, 32); pixd = pixaDisplay(pixa, 0, 0); pixDisplay(pixd, 100, 500); pixWrite("/tmp/numaextract.png", pixd, IFF_PNG); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pixs); pixDestroy(&pixg); pixDestroy(&pixd); #endif /* -------------------------------------------------------------------* * Row and column pixel sums * * -------------------------------------------------------------------*/ #if DO_ALL /* Sum by columns in two halves (left and right) */ pixs = pixRead("test8.jpg"); pixGetDimensions(pixs, &w, &h, NULL); box1 = boxCreate(0, 0, w / 2, h); box2 = boxCreate(w / 2, 0, w - 2 / 2, h); na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX); na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX); numaJoin(na1, na2, 0, -1); na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX); numaSimilar(na1, na3, 0.0, &same); if (same) fprintf(stderr, "Same for columns\n"); else fprintf(stderr, "Error for columns\n"); pta = generatePlotPtaFromNuma(na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1); pix = pixConvertTo32(pixs); pixRenderPtaArb(pix, pta, 255, 0, 0); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); ptaDestroy(&pta); /* Sum by rows in two halves (top and bottom) */ box1 = boxCreate(0, 0, w, h / 2); box2 = boxCreate(0, h / 2, w, h - h / 2); na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX); na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX); numaJoin(na1, na2, 0, -1); na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX); numaSimilar(na1, na3, 0.0, &same); if (same) fprintf(stderr, "Same for rows\n"); else fprintf(stderr, "Error for rows\n"); pta = generatePlotPtaFromNuma(na3, L_VERTICAL_LINE, 3, w / 2, 80, 1); pixRenderPtaArb(pix, pta, 0, 255, 0); pixDisplay(pix, 500, 200); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); pixDestroy(&pix); ptaDestroy(&pta); /* Average left by rows; right by columns; compare totals */ box1 = boxCreate(0, 0, w / 2, h); box2 = boxCreate(w / 2, 0, w - 2 / 2, h); na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX); na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX); numaGetSum(na1, &sum1); /* sum of averages of left box */ numaGetSum(na2, &sum2); /* sum of averages of right box */ ave1 = sum1 / h; ave2 = 2.0 * sum2 / w; ave3 = 0.5 * (ave1 + ave2); /* average over both halves */ fprintf(stderr, "ave1 = %8.4f\n", sum1 / h); fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w); pixAverageInRect(pixs, NULL, &ave4); /* entire image */ diff1 = ave4 - ave3; diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2); if (diff1 < 0.001) fprintf(stderr, "Average diffs are correct\n"); else fprintf(stderr, "Average diffs are wrong: diff1 = %7.5f\n", diff1); if (diff2 < 20) /* float-to-integer roundoff */ fprintf(stderr, "Pixel sums are correct\n"); else fprintf(stderr, "Pixel sums are in error: diff = %7.0f\n", diff2); /* Variance left and right halves. Variance doesn't average * in a simple way, unlike pixel sums. */ pixVarianceInRect(pixs, box1, &var1); /* entire image */ pixVarianceInRect(pixs, box2, &var2); /* entire image */ pixVarianceInRect(pixs, NULL, &var3); /* entire image */ fprintf(stderr, "0.5 * (var1 + var2) = %7.3f, var3 = %7.3f\n", 0.5 * (var1 + var2), var3); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); #endif /* -------------------------------------------------------------------* * Row and column variances * * -------------------------------------------------------------------*/ #if DO_ALL /* Display variance by rows and columns */ box1 = boxCreate(415, 0, 130, 425); boxGetGeometry(box1, NULL, NULL, &bw, &bh); na1 = pixVarianceByRow(pixs, box1); na2 = pixVarianceByColumn(pixs, box1); pix = pixConvertTo32(pixs); pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 415, 100, 1); pixRenderPtaArb(pix, pta, 255, 0, 0); ptaDestroy(&pta); pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1); pixRenderPtaArb(pix, pta, 0, 255, 0); pixDisplay(pix, 500, 900); boxDestroy(&box1); numaDestroy(&na1); numaDestroy(&na2); ptaDestroy(&pta); pixDestroy(&pix); pixDestroy(&pixs); /* Again on a different image */ pix1 = pixRead("boxedpage.jpg"); pix2 = pixConvertTo8(pix1, 0); pixGetDimensions(pix2, &w, &h, NULL); na1 = pixVarianceByRow(pix2, NULL); pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 0, 70, 1); pix3 = pixConvertTo32(pix1); pixRenderPtaArb(pix3, pta, 255, 0, 0); ptaDestroy(&pta); na2 = pixVarianceByColumn(pix2, NULL); pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1); pixRenderPtaArb(pix3, pta, 0, 255, 0); pixDisplay(pix3, 1000, 0); numaDestroy(&na1); numaDestroy(&na2); ptaDestroy(&pta); pixDestroy(&pix3); /* Again, with an erosion */ pix3 = pixErodeGray(pix2, 3, 21); pixDisplay(pix3, 1400, 0); na1 = pixVarianceByRow(pix3, NULL); pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 30, 70, 1); pix4 = pixConvertTo32(pix1); pixRenderPtaArb(pix4, pta, 255, 0, 0); ptaDestroy(&pta); na2 = pixVarianceByColumn(pix3, NULL); pta = generatePlotPtaFromNuma(na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1); pixRenderPtaArb(pix4, pta, 0, 255, 0); pixDisplay(pix4, 1000, 550); numaDestroy(&na1); numaDestroy(&na2); ptaDestroy(&pta); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); #endif /* -------------------------------------------------------------------* * Windowed variance along a line * * -------------------------------------------------------------------*/ #if DO_ALL pix1 = pixRead("boxedpage.jpg"); pix2 = pixConvertTo8(pix1, 0); pixGetDimensions(pix2, &w, &h, NULL); /* Plot along horizontal line */ pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0, w, 5, &na1); pta = generatePlotPtaFromNuma(na1, L_HORIZONTAL_LINE, 3, h / 2 - 30, 80, 1); pixRenderPtaArb(pix1, pta, 255, 0, 0); numaDestroy(&na1); ptaDestroy(&pta); /* Plot along vertical line */ pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0, h, 5, &na1); pta = generatePlotPtaFromNuma(na1, L_VERTICAL_LINE, 3, 0.78 * w, 60, 1); pixRenderPtaArb(pix1, pta, 0, 255, 0); pixDisplay(pix1, 100, 100); pixDestroy(&pix1); pixDestroy(&pix2); numaDestroy(&na1); ptaDestroy(&pta); #endif return 0; }
/*! * jbWordsInTextlines() * * Input: dirin (directory of input pages) * reduction (1 for full res; 2 for half-res) * maxwidth (of word mask components, to be kept) * maxheight (of word mask components, to be kept) * thresh (on correlation; 0.80 is reasonable) * weight (for handling thick text; 0.6 is reasonable) * natl (<return> numa with textline index for each component) * firstpage (0-based) * npages (use 0 for all pages in dirin) * Return: classer (for the set of pages) * * Notes: * (1) This is a high-level function. See prog/jbwords for example * of usage. * (2) Typically, words can be found reasonably well at a resolution * of about 150 ppi. For highest accuracy, you should use 300 ppi. * Assuming that the input images are 300 ppi, use reduction = 1 * for finding words at full res, and reduction = 2 for finding * them at 150 ppi. */ JBCLASSER * jbWordsInTextlines(const char *dirin, l_int32 reduction, l_int32 maxwidth, l_int32 maxheight, l_float32 thresh, l_float32 weight, NUMA **pnatl, l_int32 firstpage, l_int32 npages) { char *fname; l_int32 nfiles, i, w, h; BOXA *boxa; JBCLASSER *classer; NUMA *nai, *natl; PIX *pix; PIXA *pixa; SARRAY *safiles; PROCNAME("jbWordsInTextlines"); if (!pnatl) return (JBCLASSER *)ERROR_PTR("&natl not defined", procName, NULL); *pnatl = NULL; if (!dirin) return (JBCLASSER *)ERROR_PTR("dirin not defined", procName, NULL); if (reduction != 1 && reduction != 2) return (JBCLASSER *)ERROR_PTR("reduction not in {1,2}", procName, NULL); safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages); nfiles = sarrayGetCount(safiles); /* Classify components */ classer = jbCorrelationInit(JB_WORDS, maxwidth, maxheight, thresh, weight); classer->safiles = sarrayCopy(safiles); natl = numaCreate(0); *pnatl = natl; for (i = 0; i < nfiles; i++) { fname = sarrayGetString(safiles, i, 0); if ((pix = pixRead(fname)) == NULL) { L_WARNING("image file %d not read\n", procName, i); continue; } pixGetDimensions(pix, &w, &h, NULL); if (reduction == 1) { classer->w = w; classer->h = h; } else { /* reduction == 2 */ classer->w = w / 2; classer->h = h / 2; } pixGetWordsInTextlines(pix, reduction, JB_WORDS_MIN_WIDTH, JB_WORDS_MIN_HEIGHT, maxwidth, maxheight, &boxa, &pixa, &nai); jbAddPageComponents(classer, pix, boxa, pixa); numaJoin(natl, nai, 0, -1); pixDestroy(&pix); numaDestroy(&nai); boxaDestroy(&boxa); pixaDestroy(&pixa); } sarrayDestroy(&safiles); return classer; }
int main(int argc, char **argv) { char seq[512]; l_int32 w, h; PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5; PIXA *pixa; PIXACC *pacc; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixs = pixRead("aneurisms8.jpg"); pixa = pixaCreate(0); /* =========================================================== */ /* -------- Test gray morph, including interpreter ------------ */ pix1 = pixDilateGray(pixs, WSIZE, HSIZE); snprintf(seq, sizeof(seq), "D%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 0); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ regTestComparePix(rp, pix1, pix2); /* 1 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pix1 = pixErodeGray(pixs, WSIZE, HSIZE); snprintf(seq, sizeof(seq), "E%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 100); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 2 */ regTestComparePix(rp, pix1, pix2); /* 3 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pix1 = pixOpenGray(pixs, WSIZE, HSIZE); snprintf(seq, sizeof(seq), "O%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 200); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 4 */ regTestComparePix(rp, pix1, pix2); /* 5 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pix1 = pixCloseGray(pixs, WSIZE, HSIZE); snprintf(seq, sizeof(seq), "C%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 300); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ regTestComparePix(rp, pix1, pix2); /* 7 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); snprintf(seq, sizeof(seq), "Tw%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 400); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ regTestComparePix(rp, pix1, pix2); /* 9 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK); snprintf(seq, sizeof(seq), "Tb%d.%d", WSIZE, HSIZE); pix2 = pixGrayMorphSequence(pixs, seq, 0, 500); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 10 */ regTestComparePix(rp, pix1, pix2); /* 11 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); /* ------------- Test erode/dilate duality -------------- */ pix1 = pixDilateGray(pixs, WSIZE, HSIZE); pix2 = pixInvert(NULL, pixs); pix3 = pixErodeGray(pix2, WSIZE, HSIZE); pixInvert(pix3, pix3); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ regTestComparePix(rp, pix1, pix3); /* 13 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); /* ------------- Test open/close duality -------------- */ pix1 = pixOpenGray(pixs, WSIZE, HSIZE); pix2 = pixInvert(NULL, pixs); pix3 = pixCloseGray(pix2, WSIZE, HSIZE); pixInvert(pix3, pix3); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 14 */ regTestComparePix(rp, pix1, pix3); /* 15 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); /* ------------- Test tophat duality -------------- */ pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE); pix2 = pixInvert(NULL, pixs); pix3 = pixTophat(pix2, WSIZE, HSIZE, L_TOPHAT_BLACK); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 16 */ regTestComparePix(rp, pix1, pix3); /* 17 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); pix1 = pixGrayMorphSequence(pixs, "Tw9.5", 0, 100); pix2 = pixInvert(NULL, pixs); pix3 = pixGrayMorphSequence(pix2, "Tb9.5", 0, 300); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ regTestComparePix(rp, pix1, pix3); /* 19 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); /* ------------- Test opening/closing for large sels -------------- */ pix1 = pixGrayMorphSequence(pixs, "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", 0, 100); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = pixGrayMorphSequence(pixs, "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", 0, 400); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 21 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 22 */ pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display); pixaDestroy(&pixa); pixDestroy(&pix1); /* =========================================================== */ pixa = pixaCreate(0); /* ---------- Closing plus white tophat result ------------ * * Parameters: wsize, hsize = 9, 29 * * ---------------------------------------------------------*/ pix1 = pixCloseGray(pixs, 9, 9); pix2 = pixTophat(pix1, 9, 9, L_TOPHAT_WHITE); pix3 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", 0, 0); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ regTestComparePix(rp, pix2, pix3); /* 24 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 25 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); pix1 = pixCloseGray(pixs, 29, 29); pix2 = pixTophat(pix1, 29, 29, L_TOPHAT_WHITE); pix3 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", 0, 0); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 26 */ regTestComparePix(rp, pix2, pix3); /* 27 */ pixaAddPix(pixa, pix1, L_INSERT); pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 28 */ pixaAddPix(pixa, pix1, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); /* --------- hdome with parameter height = 100 ------------*/ pix1 = pixHDome(pixs, 100, 4); pix2 = pixMaxDynamicRange(pix1, L_LINEAR_SCALE); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 29 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 30 */ pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); /* ----- Contrast enhancement with morph parameters 9, 9 -------*/ pixGetDimensions(pixs, &w, &h, NULL); pix1 = pixInitAccumulate(w, h, 0x8000); pixAccumulate(pix1, pixs, L_ARITH_ADD); pixMultConstAccumulate(pix1, 3., 0x8000); pix2 = pixOpenGray(pixs, 9, 9); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 31 */ pixaAddPix(pixa, pix2, L_INSERT); pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT); pix2 = pixCloseGray(pixs, 9, 9); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 32 */ pixaAddPix(pixa, pix2, L_INSERT); pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT); pix2 = pixFinalAccumulate(pix1, 0x8000, 8); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 33 */ pixaAddPix(pixa, pix2, L_INSERT); pixDestroy(&pix1); /* Do the same thing with the Pixacc */ pacc = pixaccCreate(w, h, 1); pixaccAdd(pacc, pixs); pixaccMultConst(pacc, 3.); pix1 = pixOpenGray(pixs, 9, 9); pixaccSubtract(pacc, pix1); pixDestroy(&pix1); pix1 = pixCloseGray(pixs, 9, 9); pixaccSubtract(pacc, pix1); pixDestroy(&pix1); pix1 = pixaccFinal(pacc, 8); pixaccDestroy(&pacc); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 34 */ pixaAddPix(pixa, pix1, L_INSERT); regTestComparePix(rp, pix1, pix2); /* 35 */ pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 36 */ pixDisplayWithTitle(pix1, 1100, 0, NULL, rp->display); pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pixs); /* =========================================================== */ pixa = pixaCreate(0); /* ---- Tophat result on feynman stamp, to extract diagrams ----- */ pixs = pixRead("feynman-stamp.jpg"); pixGetDimensions(pixs, &w, &h, NULL); /* Make output image to hold five intermediate images */ pix1 = pixCreate(5 * w + 18, h + 6, 32); /* composite output image */ pixSetAllArbitrary(pix1, 0x0000ff00); /* set to blue */ /* Paste in the input image */ pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR); pixRasterop(pix1, 3, 3, w, h, PIX_SRC, pix2, 0, 0); /* 1st one */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 37 */ pixaAddPix(pixa, pix2, L_INSERT); /* Paste in the grayscale version */ cmap = pixGetColormap(pixs); if (cmap) pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE); else pix2 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); pix3 = pixConvertTo32(pix2); /* 8 --> 32 bpp */ pixRasterop(pix1, w + 6, 3, w, h, PIX_SRC, pix3, 0, 0); /* 2nd one */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 38 */ pixaAddPix(pixa, pix3, L_INSERT); /* Paste in a log dynamic range scaled version of the white tophat */ pix3 = pixTophat(pix2, 3, 3, L_TOPHAT_WHITE); pix4 = pixMaxDynamicRange(pix3, L_LOG_SCALE); pix5 = pixConvertTo32(pix4); pixRasterop(pix1, 2 * w + 9, 3, w, h, PIX_SRC, pix5, 0, 0); /* 3rd */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 39 */ pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix4); /* Stretch the range and threshold to binary; paste it in */ pix2 = pixGammaTRC(NULL, pix3, 1.0, 0, 80); pix4 = pixThresholdToBinary(pix2, 70); pix5 = pixConvertTo32(pix4); pixRasterop(pix1, 3 * w + 12, 3, w, h, PIX_SRC, pix5, 0, 0); /* 4th */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 40 */ pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix2); pixDestroy(&pix3); /* Invert; this is the final result */ pixInvert(pix4, pix4); pix5 = pixConvertTo32(pix4); pixRasterop(pix1, 4 * w + 15, 3, w, h, PIX_SRC, pix5, 0, 0); /* 5th */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 41 */ pixaAddPix(pixa, pix5, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix4); pix1 = pixaDisplayTiledInRows(pixa, 32, 1700, 1.0, 0, 20, 2); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 42 */ pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display); pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pixs); return regTestCleanup(rp); }
/*! * jbCorrelation() * * Input: dirin (directory of input images) * thresh (typically ~0.8) * weight (typically ~0.6) * components (JB_CONN_COMPS, JB_CHARACTERS, JB_WORDS) * rootname (for output files) * firstpage (0-based) * npages (use 0 for all pages in dirin) * renderflag (1 to render from templates; 0 to skip) * Return: 0 if OK, 1 on error * * Notes: * (1) The images must be 1 bpp. If they are not, you can convert * them using convertFilesTo1bpp(). * (2) See prog/jbcorrelation for generating more output (e.g., * for debugging) */ l_int32 jbCorrelation(const char *dirin, l_float32 thresh, l_float32 weight, l_int32 components, const char *rootname, l_int32 firstpage, l_int32 npages, l_int32 renderflag) { char filename[L_BUF_SIZE]; l_int32 nfiles, i, numpages; JBDATA *data; JBCLASSER *classer; PIX *pix; PIXA *pixa; SARRAY *safiles; PROCNAME("jbCorrelation"); if (!dirin) return ERROR_INT("dirin not defined", procName, 1); if (!rootname) return ERROR_INT("rootname not defined", procName, 1); if (components != JB_CONN_COMPS && components != JB_CHARACTERS && components != JB_WORDS) return ERROR_INT("components invalid", procName, 1); safiles = getSortedPathnamesInDirectory(dirin, NULL, firstpage, npages); nfiles = sarrayGetCount(safiles); /* Classify components */ classer = jbCorrelationInit(components, 0, 0, thresh, weight); jbAddPages(classer, safiles); /* Save data */ data = jbDataSave(classer); jbDataWrite(rootname, data); /* Optionally, render pages using class templates */ if (renderflag) { pixa = jbDataRender(data, FALSE); numpages = pixaGetCount(pixa); if (numpages != nfiles) fprintf(stderr, "numpages = %d, nfiles = %d, not equal!\n", numpages, nfiles); for (i = 0; i < numpages; i++) { pix = pixaGetPix(pixa, i, L_CLONE); snprintf(filename, L_BUF_SIZE, "%s.%05d", rootname, i); fprintf(stderr, "filename: %s\n", filename); pixWrite(filename, pix, IFF_PNG); pixDestroy(&pix); } pixaDestroy(&pixa); } sarrayDestroy(&safiles); jbClasserDestroy(&classer); jbDataDestroy(&data); return 0; }
l_int32 GeneratePattern(l_int32 patno, l_int32 red, L_REGPARAMS *rp) { l_int32 width, cx, cy; PIX *pixs, *pixt, *pix, *pixr, *pixp, *pixsel, *pixhmt; PIX *pixc1, *pixc2, *pixc3, *pixd; PIXA *pixa; SEL *selhm; PROCNAME("GeneratePattern"); if ((pixs = pixRead(patname[patno])) == NULL) { rp->success = FALSE; return ERROR_INT("pixs not made", procName, 1); } /* Make a hit-miss sel at specified reduction factor */ if (red == 4) { pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 0, 0); selhm = pixGenerateSelBoundary(pixt, 2, 2, 20, 30, 1, 1, 0, 0, &pixp); } else if (red == 8) { pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 0); selhm = pixGenerateSelBoundary(pixt, 1, 2, 6, 12, 1, 1, 0, 0, &pixp); } else { /* red == 16 */ pixt = pixReduceRankBinaryCascade(pixs, 4, 4, 2, 2); selhm = pixGenerateSelBoundary(pixt, 1, 1, 4, 8, 0, 0, 0, 0, &pixp); } pixDestroy(&pixt); /* Display the sel */ pixsel = pixDisplayHitMissSel(pixp, selhm, 7, HitColor, MissColor); pixa = pixaCreate(2); pixaAddPix(pixa, pixs, L_CLONE); pixaAddPix(pixa, pixsel, L_CLONE); width = (patno == 0) ? 1200 : 400; pixd = pixaDisplayTiledAndScaled(pixa, 32, width, 2, 0, 30, 2); regTestWritePixAndCheck(rp, pixd, IFF_PNG); pixDisplayWithTitle(pixd, 100, 100 + 100 * (3 * patno + red / 4), NULL, rp->display); pixaDestroy(&pixa); pixDestroy(&pixd); /* Use the sel to find all instances in the page */ pix = pixRead("tribune-page-4x.png"); /* 4x reduced */ if (red == 4) pixr = pixClone(pix); else if (red == 8) pixr = pixReduceRankBinaryCascade(pix, 2, 0, 0, 0); else if (red == 16) pixr = pixReduceRankBinaryCascade(pix, 2, 2, 0, 0); pixDestroy(&pix); startTimer(); pixhmt = pixHMT(NULL, pixr, selhm); fprintf(stderr, "Time to find patterns = %7.3f\n", stopTimer()); /* Color each instance at full res */ selGetParameters(selhm, NULL, NULL, &cy, &cx); pixc1 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, cx, cy, 0x0000ff00, 1.0, 5); regTestWritePixAndCheck(rp, pixc1, IFF_PNG); pixDisplayWithTitle(pixc1, 500, 100, NULL, rp->display); /* Color each instance at 0.5 scale */ pixc2 = pixDisplayMatchedPattern(pixr, pixp, pixhmt, cx, cy, 0x0000ff00, 0.5, 5); regTestWritePixAndCheck(rp, pixc2, IFF_PNG); /* Remove each instance from the input image */ pixc3 = pixCopy(NULL, pixr); pixRemoveMatchedPattern(pixc3, pixp, pixhmt, cx, cy, 1); regTestWritePixAndCheck(rp, pixc3, IFF_PNG); selDestroy(&selhm); pixDestroy(&pixp); pixDestroy(&pixsel); pixDestroy(&pixhmt); pixDestroy(&pixc1); pixDestroy(&pixc2); pixDestroy(&pixc3); pixDestroy(&pixd); pixDestroy(&pixr); pixDestroy(&pixs); return 0; }
main(int argc, char **argv) { BOX *box; PIX *pix, *pixs, *pixd, *pixt; PIXA *pixa; SEL *sel, *sel1, *sel2, *sel3; SELA *sela4, *sela8, *sela48; static char mainName[] = "ccthin1_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: ccthin1_reg", mainName, 1)); /* Generate and display all of the 4-cc sels */ sela4 = selaCreate(9); sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_4, 3, 3, "sel_4_4"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_5, 3, 3, "sel_4_5"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_6, 3, 3, "sel_4_6"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_7, 3, 3, "sel_4_7"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_8, 3, 3, "sel_4_8"); selaAddSel(sela4, sel, NULL, 0); sel = selCreateFromString(sel_4_9, 3, 3, "sel_4_9"); selaAddSel(sela4, sel, NULL, 0); pixt = selaDisplayInPix(sela4, 35, 3, 15, 3); pixWrite("/tmp/junkallsel4.png", pixt, IFF_PNG); pixDestroy(&pixt); selaDestroy(&sela4); /* Generate and display all of the 8-cc sels */ sela8 = selaCreate(9); sel = selCreateFromString(sel_8_1, 3, 3, "sel_8_1"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_4, 3, 3, "sel_8_4"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_7, 3, 3, "sel_8_7"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_8, 3, 3, "sel_8_8"); selaAddSel(sela8, sel, NULL, 0); sel = selCreateFromString(sel_8_9, 3, 3, "sel_8_9"); selaAddSel(sela8, sel, NULL, 0); pixt = selaDisplayInPix(sela8, 35, 3, 15, 3); pixWrite("/tmp/junkallsel8.png", pixt, IFF_PNG); pixDestroy(&pixt); selaDestroy(&sela8); /* Generate and display all of the 4 and 8-cc preserving sels */ sela48 = selaCreate(3); sel = selCreateFromString(sel_48_1, 3, 3, "sel_48_1"); selaAddSel(sela48, sel, NULL, 0); sel = selCreateFromString(sel_48_2, 3, 3, "sel_48_2"); selaAddSel(sela48, sel, NULL, 0); pixt = selaDisplayInPix(sela48, 35, 3, 15, 4); pixWrite("/tmp/junkallsel48.png", pixt, IFF_PNG); pixDestroy(&pixt); selaDestroy(&sela48); /* Generate and display three of the 4-cc sels and their rotations */ sela4 = selaCreate(3); sel = selCreateFromString(sel_4_1, 3, 3, "sel_4_1"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela4, sel, NULL, 0); selaAddSel(sela4, sel1, "sel_4_1_90", 0); selaAddSel(sela4, sel2, "sel_4_1_180", 0); selaAddSel(sela4, sel3, "sel_4_1_270", 0); sel = selCreateFromString(sel_4_2, 3, 3, "sel_4_2"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela4, sel, NULL, 0); selaAddSel(sela4, sel1, "sel_4_2_90", 0); selaAddSel(sela4, sel2, "sel_4_2_180", 0); selaAddSel(sela4, sel3, "sel_4_2_270", 0); sel = selCreateFromString(sel_4_3, 3, 3, "sel_4_3"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela4, sel, NULL, 0); selaAddSel(sela4, sel1, "sel_4_3_90", 0); selaAddSel(sela4, sel2, "sel_4_3_180", 0); selaAddSel(sela4, sel3, "sel_4_3_270", 0); pixt = selaDisplayInPix(sela4, 35, 3, 15, 4); pixWrite("/tmp/junksel4.png", pixt, IFF_PNG); pixDestroy(&pixt); selaDestroy(&sela4); /* Generate and display four of the 8-cc sels and their rotations */ sela8 = selaCreate(4); sel = selCreateFromString(sel_8_2, 3, 3, "sel_8_2"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela8, sel, NULL, 0); selaAddSel(sela8, sel1, "sel_8_2_90", 0); selaAddSel(sela8, sel2, "sel_8_2_180", 0); selaAddSel(sela8, sel3, "sel_8_2_270", 0); sel = selCreateFromString(sel_8_3, 3, 3, "sel_8_3"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela8, sel, NULL, 0); selaAddSel(sela8, sel1, "sel_8_3_90", 0); selaAddSel(sela8, sel2, "sel_8_3_180", 0); selaAddSel(sela8, sel3, "sel_8_3_270", 0); sel = selCreateFromString(sel_8_5, 3, 3, "sel_8_5"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela8, sel, NULL, 0); selaAddSel(sela8, sel1, "sel_8_5_90", 0); selaAddSel(sela8, sel2, "sel_8_5_180", 0); selaAddSel(sela8, sel3, "sel_8_5_270", 0); sel = selCreateFromString(sel_8_6, 3, 3, "sel_8_6"); sel1 = selRotateOrth(sel, 1); sel2 = selRotateOrth(sel, 2); sel3 = selRotateOrth(sel, 3); selaAddSel(sela8, sel, NULL, 0); selaAddSel(sela8, sel1, "sel_8_6_90", 0); selaAddSel(sela8, sel2, "sel_8_6_180", 0); selaAddSel(sela8, sel3, "sel_8_6_270", 0); pixt = selaDisplayInPix(sela8, 35, 3, 15, 4); pixWrite("/tmp/junksel8.png", pixt, IFF_PNG); pixDestroy(&pixt); selaDestroy(&sela8); /* Test the best 4 and 8 cc thinning */ pixDisplayWrite(NULL, 0); if ((pix = pixRead("feyn.tif")) == NULL) exit(ERROR_INT("pix not made", mainName, 1)); box = boxCreate(683, 799, 970, 479); pixs = pixClipRectangle(pix, box, NULL); pixDisplayWrite(pixs, 1); pixt = pixThin(pixs, L_THIN_FG, 4, 0); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); pixt = pixThin(pixs, L_THIN_BG, 4, 0); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); pixt = pixThin(pixs, L_THIN_FG, 8, 0); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); pixt = pixThin(pixs, L_THIN_BG, 8, 0); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); /* Display tiled */ pixa = pixaReadFiles("/tmp", "junk_write_display"); pixd = pixaDisplayTiledAndScaled(pixa, 8, 500, 1, 0, 25, 2); pixWrite("/tmp/junktiles.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixaDestroy(&pixa); pixDestroy(&pix); pixDestroy(&pixs); boxDestroy(&box); pixDisplayMultiple("/tmp/junk_write_display*"); return 0; }
/*! * pixaDisplayOnLattice() * * Input: pixa * xspace * yspace * Return: pix of composite images, or null on error * * Notes: * (1) This places each pix on sequentially on a regular lattice * in the rendered composite. If a pix is too large to fit in the * allocated lattice space, it is not rendered. * (2) If any pix has a colormap, all pix are rendered in rgb. * (3) This is useful when putting bitmaps of components, * such as characters, into a single image. */ PIX * pixaDisplayOnLattice(PIXA *pixa, l_int32 xspace, l_int32 yspace) { l_int32 n, nw, nh, w, h, d, wt, ht; l_int32 index, i, j, hascmap; PIX *pix, *pixt, *pixd; PIXA *pixat; PROCNAME("pixaDisplayOnLattice"); if (!pixa) return (PIX *)ERROR_PTR("pixa not defined", procName, NULL); /* If any pix have colormaps, generate rgb */ if ((n = pixaGetCount(pixa)) == 0) return (PIX *)ERROR_PTR("no components", procName, NULL); pixaAnyColormaps(pixa, &hascmap); if (hascmap) { pixat = pixaCreate(n); for (i = 0; i < n; i++) { pixt = pixaGetPix(pixa, i, L_CLONE); pix = pixConvertTo32(pixt); pixaAddPix(pixat, pix, L_INSERT); pixDestroy(&pixt); } } else pixat = pixaCopy(pixa, L_CLONE); nw = (l_int32)sqrt((l_float64)n); nh = (n + nw - 1) / nw; w = xspace * nw; h = yspace * nh; /* Use the first pix in pixa to determine the depth. */ pixaGetPixDimensions(pixat, 0, NULL, NULL, &d); if ((pixd = pixCreate(w, h, d)) == NULL) { pixaDestroy(&pixat); return (PIX *)ERROR_PTR("pixd not made", procName, NULL); } index = 0; for (i = 0; i < nh; i++) { for (j = 0; j < nw && index < n; j++, index++) { pixt = pixaGetPix(pixat, index, L_CLONE); pixGetDimensions(pixt, &wt, &ht, NULL); if (wt > xspace || ht > yspace) { fprintf(stderr, "pix(%d) omitted; size %dx%d\n", index, wt, ht); pixDestroy(&pixt); continue; } pixRasterop(pixd, j * xspace, i * yspace, wt, ht, PIX_PAINT, pixt, 0, 0); pixDestroy(&pixt); } } pixaDestroy(&pixat); return pixd; }
int main(int argc, char **argv) { l_int32 w, h, n, i, sum, sumi, empty; BOX *box1, *box2, *box3, *box4; BOXA *boxa, *boxat; NUMA *na1, *na2, *na3, *na4, *na5; NUMA *na2i, *na3i, *na4i, *nat, *naw, *nah; PIX *pixs, *pixc, *pixt, *pixt2, *pixd, *pixcount; PIXA *pixas, *pixad, *pixac; pixDisplayWrite(NULL, -1); /* Draw 4 filled boxes of different sizes */ pixs = pixCreate(200, 200, 1); box1 = boxCreate(10, 10, 20, 30); box2 = boxCreate(50, 10, 40, 20); box3 = boxCreate(110, 10, 35, 5); box4 = boxCreate(160, 10, 5, 15); boxa = boxaCreate(4); boxaAddBox(boxa, box1, L_INSERT); boxaAddBox(boxa, box2, L_INSERT); boxaAddBox(boxa, box3, L_INSERT); boxaAddBox(boxa, box4, L_INSERT); pixRenderBox(pixs, box1, 1, L_SET_PIXELS); pixRenderBox(pixs, box2, 1, L_SET_PIXELS); pixRenderBox(pixs, box3, 1, L_SET_PIXELS); pixRenderBox(pixs, box4, 1, L_SET_PIXELS); pixt = pixFillClosedBorders(pixs, 4); pixDisplayWrite(pixt, 1); pixt2 = pixCreateTemplate(pixs); pixRenderHashBox(pixt2, box1, 6, 4, L_POS_SLOPE_LINE, 1, L_SET_PIXELS); pixRenderHashBox(pixt2, box2, 7, 2, L_POS_SLOPE_LINE, 1, L_SET_PIXELS); pixRenderHashBox(pixt2, box3, 4, 2, L_VERTICAL_LINE, 1, L_SET_PIXELS); pixRenderHashBox(pixt2, box4, 3, 1, L_HORIZONTAL_LINE, 1, L_SET_PIXELS); pixDisplayWrite(pixt2, 1); /* Exercise the parameters */ pixd = pixSelectBySize(pixt, 0, 22, 8, L_SELECT_HEIGHT, L_SELECT_IF_GT, NULL); count_pieces(pixd, 1); pixd = pixSelectBySize(pixt, 0, 30, 8, L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL); count_pieces(pixd, 3); pixd = pixSelectBySize(pixt, 0, 5, 8, L_SELECT_HEIGHT, L_SELECT_IF_GT, NULL); count_pieces(pixd, 3); pixd = pixSelectBySize(pixt, 0, 6, 8, L_SELECT_HEIGHT, L_SELECT_IF_LT, NULL); count_pieces(pixd, 1); pixd = pixSelectBySize(pixt, 20, 0, 8, L_SELECT_WIDTH, L_SELECT_IF_GT, NULL); count_pieces(pixd, 2); pixd = pixSelectBySize(pixt, 31, 0, 8, L_SELECT_WIDTH, L_SELECT_IF_LT, NULL); count_pieces(pixd, 2); pixd = pixSelectBySize(pixt, 21, 10, 8, L_SELECT_IF_EITHER, L_SELECT_IF_LT, NULL); count_pieces(pixd, 3); pixd = pixSelectBySize(pixt, 20, 30, 8, L_SELECT_IF_EITHER, L_SELECT_IF_GT, NULL); count_pieces(pixd, 2); pixd = pixSelectBySize(pixt, 22, 32, 8, L_SELECT_IF_BOTH, L_SELECT_IF_LT, NULL); count_pieces(pixd, 2); pixd = pixSelectBySize(pixt, 6, 32, 8, L_SELECT_IF_BOTH, L_SELECT_IF_LT, NULL); count_pieces(pixd, 1); pixd = pixSelectBySize(pixt, 5, 25, 8, L_SELECT_IF_BOTH, L_SELECT_IF_GT, NULL); count_pieces(pixd, 1); pixd = pixSelectBySize(pixt, 25, 5, 8, L_SELECT_IF_BOTH, L_SELECT_IF_GT, NULL); count_pieces(pixd, 1); pixd = pixSelectByPerimToAreaRatio(pixt, 0.3, 8, L_SELECT_IF_GT, NULL); count_pieces(pixd, 2); pixd = pixSelectByPerimToAreaRatio(pixt, 0.15, 8, L_SELECT_IF_GT, NULL); count_pieces(pixd, 3); pixd = pixSelectByPerimToAreaRatio(pixt, 0.4, 8, L_SELECT_IF_LTE, NULL); count_pieces(pixd, 2); pixd = pixSelectByPerimToAreaRatio(pixt, 0.45, 8, L_SELECT_IF_LT, NULL); count_pieces(pixd, 3); pixd = pixSelectByPerimSizeRatio(pixt2, 2.3, 8, L_SELECT_IF_GT, NULL); count_pieces(pixd, 2); pixd = pixSelectByPerimSizeRatio(pixt2, 1.2, 8, L_SELECT_IF_GT, NULL); count_pieces(pixd, 3); pixd = pixSelectByPerimSizeRatio(pixt2, 1.7, 8, L_SELECT_IF_LTE, NULL); count_pieces(pixd, 1); pixd = pixSelectByPerimSizeRatio(pixt2, 2.9, 8, L_SELECT_IF_LT, NULL); count_pieces(pixd, 3); pixd = pixSelectByAreaFraction(pixt2, 0.3, 8, L_SELECT_IF_LT, NULL); count_pieces(pixd, 0); pixd = pixSelectByAreaFraction(pixt2, 0.9, 8, L_SELECT_IF_LT, NULL); count_pieces(pixd, 4); pixd = pixSelectByAreaFraction(pixt2, 0.5, 8, L_SELECT_IF_GTE, NULL); count_pieces(pixd, 3); pixd = pixSelectByAreaFraction(pixt2, 0.7, 8, L_SELECT_IF_GT, NULL); count_pieces(pixd, 2); boxat = boxaSelectBySize(boxa, 21, 10, L_SELECT_IF_EITHER, L_SELECT_IF_LT, NULL); count_pieces2(boxat, 3); boxat = boxaSelectBySize(boxa, 22, 32, L_SELECT_IF_BOTH, L_SELECT_IF_LT, NULL); count_pieces2(boxat, 2); boxaDestroy(&boxa); pixDestroy(&pixt); pixDestroy(&pixt2); pixDestroy(&pixs); /* Here's the most general method for selecting components. * We do it for area fraction, but any combination of * size, area/perimeter ratio and area fraction can be used. */ pixs = pixRead("feyn.tif"); /* pixs = pixRead("rabi.png"); */ pixc = pixCopy(NULL, pixs); /* subtract bands from this */ pixt = pixCreateTemplate(pixs); /* add bands to this */ pixGetDimensions(pixs, &w, &h, NULL); boxa = pixConnComp(pixs, &pixas, 8); n = boxaGetCount(boxa); fprintf(stderr, "total: %d\n", n); na1 = pixaFindAreaFraction(pixas); nat = numaCreate(0); numaSetCount(nat, n); /* initialize to all 0 */ sum = sumi = 0; pixac = pixaCreate(0); for (i = 0; i < 12; i++) { /* Compute within the intervals using an intersection. */ na2 = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_GTE); if (i != 11) na3 = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_LT); else na3 = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_LTE); na4 = numaLogicalOp(NULL, na2, na3, L_INTERSECTION); sum += count_ones(na4, 0, 0, NULL); /* Compute outside the intervals using a union, and invert */ na2i = numaMakeThresholdIndicator(na1, edges[i], L_SELECT_IF_LT); if (i != 11) na3i = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_GTE); else na3i = numaMakeThresholdIndicator(na1, edges[i + 1], L_SELECT_IF_GT); na4i = numaLogicalOp(NULL, na3i, na2i, L_UNION); numaInvert(na4i, na4i); sumi += count_ones(na4i, 0, 0, NULL); /* Compare the two methods */ if (sum == sumi) fprintf(stderr, "\nCorrect: sum = sumi = %d\n", sum); else fprintf(stderr, "\nWRONG: sum = %d, sumi = %d\n", sum, sumi); /* Reconstruct the image, band by band. */ numaLogicalOp(nat, nat, na4, L_UNION); pixad = pixaSelectWithIndicator(pixas, na4, NULL); pixd = pixaDisplay(pixad, w, h); pixOr(pixt, pixt, pixd); /* add them in */ pixcount = pixCopy(NULL, pixt); /* destroyed by count_pieces */ count_ones(na4, band[i], i, "band"); count_pieces(pixd, band[i]); count_ones(nat, total[i], i, "total"); count_pieces(pixcount, total[i]); pixaDestroy(&pixad); /* Remove band successively from full image */ pixRemoveWithIndicator(pixc, pixas, na4); pixSaveTiled(pixc, pixac, 0.25, 1 - i % 2, 25, 8); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); numaDestroy(&na2i); numaDestroy(&na3i); numaDestroy(&na4i); } /* Did we remove all components from pixc? */ pixZero(pixc, &empty); if (!empty) fprintf(stderr, "\nWRONG: not all pixels removed from pixc\n"); pixDestroy(&pixs); pixDestroy(&pixc); pixDestroy(&pixt); boxaDestroy(&boxa); pixaDestroy(&pixas); numaDestroy(&na1); numaDestroy(&nat); /* One last extraction. Get all components that have either * a height of at least 50 or a width of between 30 and 35, * and also have a relatively large perimeter/area ratio. */ pixs = pixRead("feyn.tif"); boxa = pixConnComp(pixs, &pixas, 8); n = boxaGetCount(boxa); pixaFindDimensions(pixas, &naw, &nah); na1 = pixaFindPerimToAreaRatio(pixas); na2 = numaMakeThresholdIndicator(nah, 50, L_SELECT_IF_GTE); na3 = numaMakeThresholdIndicator(naw, 30, L_SELECT_IF_GTE); na4 = numaMakeThresholdIndicator(naw, 35, L_SELECT_IF_LTE); na5 = numaMakeThresholdIndicator(na1, 0.4, L_SELECT_IF_GTE); numaLogicalOp(na3, na3, na4, L_INTERSECTION); numaLogicalOp(na2, na2, na3, L_UNION); numaLogicalOp(na2, na2, na5, L_INTERSECTION); numaInvert(na2, na2); /* get components to be removed */ pixRemoveWithIndicator(pixs, pixas, na2); pixSaveTiled(pixs, pixac, 0.25, 1, 25, 8); pixDestroy(&pixs); boxaDestroy(&boxa); pixaDestroy(&pixas); numaDestroy(&naw); numaDestroy(&nah); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); numaDestroy(&na5); pixDisplayMultiple("/tmp/display/file*"); pixd = pixaDisplay(pixac, 0, 0); pixDisplay(pixd, 100, 100); pixWrite("/tmp/comp.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixaDestroy(&pixac); return 0; }
main(int argc, char **argv) { char outname[256]; l_int32 loc, display, success; L_BMF *bmf, *bmftop; FILE *fp; PIX *pixs, *pixt, *pixd; PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8; PIXA *pixa; if (regTestSetup(argc, argv, &fp, &display, &success, NULL)) return 1; bmf = bmfCreate("./fonts", 6); bmftop = bmfCreate("./fonts", 10); pixs = pixRead("lucasta-47.jpg"); pix1 = pixScale(pixs, 0.4, 0.4); /* 8 bpp grayscale */ pix2 = pixConvertTo32(pix1); /* 32 bpp rgb */ pix3 = pixThresholdOn8bpp(pix1, 12, 1); /* 8 bpp cmapped */ pix4 = pixThresholdTo4bpp(pix1, 10, 1); /* 4 bpp cmapped */ pix5 = pixThresholdTo4bpp(pix1, 10, 0); /* 4 bpp not cmapped */ pix6 = pixThresholdTo2bpp(pix1, 3, 1); /* 2 bpp cmapped */ pix7 = pixThresholdTo2bpp(pix1, 3, 0); /* 2 bpp not cmapped */ pix8 = pixThresholdToBinary(pix1, 160); /* 1 bpp */ for (loc = 1; loc < 5; loc++) { pixa = pixaCreate(0); AddTextAndSave(pixa, pix1, bmf, textstr[0], loc, 190); AddTextAndSave(pixa, pix2, bmf, textstr[1], loc, 0xff000000); AddTextAndSave(pixa, pix3, bmf, textstr[2], loc, 0x00ff0000); AddTextAndSave(pixa, pix4, bmf, textstr[3], loc, 0x0000ff00); AddTextAndSave(pixa, pix5, bmf, textstr[4], loc, 11); AddTextAndSave(pixa, pix6, bmf, textstr[5], loc, 0xff000000); AddTextAndSave(pixa, pix7, bmf, textstr[6], loc, 2); AddTextAndSave(pixa, pix8, bmf, textstr[7], loc, 1); pixt = pixaDisplay(pixa, 0, 0); pixd = pixAddSingleTextblock(pixt, bmftop, topstr[loc - 1], 0xff00ff00, L_ADD_ABOVE, NULL); snprintf(outname, 240, "/tmp/writetext.%d.png", loc - 1); pixWrite(outname, pixd, IFF_PNG); regTestCheckFile(fp, argv, outname, loc - 1, &success); pixDisplayWithTitle(pixd, 50 * loc, 50, NULL, display); pixDestroy(&pixt); pixDestroy(&pixd); pixaDestroy(&pixa); } pixDestroy(&pixs); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); pixDestroy(&pix7); pixDestroy(&pix8); bmfDestroy(&bmf); bmfDestroy(&bmftop); regTestCleanup(argc, argv, fp, success, NULL); return 0; }