/*! * \brief pmsCreate() * * \param[in] minsize of data chunk that can be supplied by pms * \param[in] smallest bytes of the smallest pre-allocated data chunk. * \param[in] numalloc array with the number of data chunks for each * size that are in the memory store * \param[in] logfile use for debugging; null otherwise * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) This computes the size of the block of memory required * and allocates it. Each chunk starts on a 32-bit word boundary. * The chunk sizes are in powers of 2, starting at %smallest, * and the number of levels and chunks at each level is * specified by %numalloc. * (2) This is intended to manage the image data for a small number * of relatively large pix. The system malloc is expected to * handle very large numbers of small chunks efficiently. * (3) Important: set the allocators and call this function * before any pix have been allocated. Destroy all the pix * in the normal way before calling pmsDestroy(). * (4) The pms struct is stored in a static global, so this function * is not thread-safe. When used, there must be only one thread * per process. * </pre> */ l_ok pmsCreate(size_t minsize, size_t smallest, NUMA *numalloc, const char *logfile) { l_int32 nlevels, i, j, nbytes; l_int32 *alloca; l_float32 nchunks; l_uint32 *baseptr, *data; l_uint32 **firstptr; size_t *sizes; L_PIX_MEM_STORE *pms; L_PTRA *pa; L_PTRAA *paa; PROCNAME("createPMS"); if (!numalloc) return ERROR_INT("numalloc not defined", procName, 1); numaGetSum(numalloc, &nchunks); if (nchunks > 1000.0) L_WARNING("There are %.0f chunks\n", procName, nchunks); if ((pms = (L_PIX_MEM_STORE *)LEPT_CALLOC(1, sizeof(L_PIX_MEM_STORE))) == NULL) return ERROR_INT("pms not made", procName, 1); CustomPMS = pms; /* Make sure that minsize and smallest are multiples of 32 bit words */ if (minsize % 4 != 0) minsize -= minsize % 4; pms->minsize = minsize; nlevels = numaGetCount(numalloc); pms->nlevels = nlevels; if ((sizes = (size_t *)LEPT_CALLOC(nlevels, sizeof(size_t))) == NULL) return ERROR_INT("sizes not made", procName, 1); pms->sizes = sizes; if (smallest % 4 != 0) smallest += 4 - (smallest % 4); pms->smallest = smallest; for (i = 0; i < nlevels; i++) sizes[i] = smallest * (1 << i); pms->largest = sizes[nlevels - 1]; alloca = numaGetIArray(numalloc); pms->allocarray = alloca; if ((paa = ptraaCreate(nlevels)) == NULL) return ERROR_INT("paa not made", procName, 1); pms->paa = paa; for (i = 0, nbytes = 0; i < nlevels; i++) nbytes += alloca[i] * sizes[i]; pms->nbytes = nbytes; if ((baseptr = (l_uint32 *)LEPT_CALLOC(nbytes / 4, sizeof(l_uint32))) == NULL) return ERROR_INT("calloc fail for baseptr", procName, 1); pms->baseptr = baseptr; pms->maxptr = baseptr + nbytes / 4; /* just beyond the memory store */ if ((firstptr = (l_uint32 **)LEPT_CALLOC(nlevels, sizeof(l_uint32 *))) == NULL) return ERROR_INT("calloc fail for firstptr", procName, 1); pms->firstptr = firstptr; data = baseptr; for (i = 0; i < nlevels; i++) { if ((pa = ptraCreate(alloca[i])) == NULL) return ERROR_INT("pa not made", procName, 1); ptraaInsertPtra(paa, i, pa); firstptr[i] = data; for (j = 0; j < alloca[i]; j++) { ptraAdd(pa, data); data += sizes[i] / 4; } } if (logfile) { pms->memused = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); pms->meminuse = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); pms->memmax = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); pms->memempty = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); pms->logfile = stringNew(logfile); } return 0; }
/*! * pixFindNormalizedSquareSum() * * Input: pixs * &hratio (<optional return> ratio of normalized horiz square sum * to result if the pixel distribution were uniform) * &vratio (<optional return> ratio of normalized vert square sum * to result if the pixel distribution were uniform) * &fract (<optional return> ratio of fg pixels to total pixels) * Return: 0 if OK, 1 on error or if there are no fg pixels * * Notes: * (1) Let the image have h scanlines and N fg pixels. * If the pixels were uniformly distributed on scanlines, * the sum of squares of fg pixels on each scanline would be * h * (N / h)^2. However, if the pixels are not uniformly * distributed (e.g., for text), the sum of squares of fg * pixels will be larger. We return in hratio and vratio the * ratio of these two values. * (2) If there are no fg pixels, hratio and vratio are returned as 0.0. */ l_int32 pixFindNormalizedSquareSum(PIX *pixs, l_float32 *phratio, l_float32 *pvratio, l_float32 *pfract) { l_int32 i, w, h, empty; l_float32 sum, sumsq, uniform, val; NUMA *na; PIX *pixt; PROCNAME("pixFindNormalizedSquareSum"); if (!pixs || pixGetDepth(pixs) != 1) return ERROR_INT("pixs not defined or not 1 bpp", procName, 1); pixGetDimensions(pixs, &w, &h, NULL); if (!phratio && !pvratio) return ERROR_INT("nothing to do", procName, 1); if (phratio) *phratio = 0.0; if (pvratio) *pvratio = 0.0; empty = 0; if (phratio) { na = pixCountPixelsByRow(pixs, NULL); numaGetSum(na, &sum); /* fg pixels */ if (pfract) *pfract = sum / (l_float32)(w * h); if (sum != 0.0) { uniform = sum * sum / h; /* h*(sum / h)^2 */ sumsq = 0.0; for (i = 0; i < h; i++) { numaGetFValue(na, i, &val); sumsq += val * val; } *phratio = sumsq / uniform; } else { empty = 1; } numaDestroy(&na); } if (pvratio) { if (empty == 1) return 1; pixt = pixRotateOrth(pixs, 1); na = pixCountPixelsByRow(pixt, NULL); numaGetSum(na, &sum); if (pfract) *pfract = sum / (l_float32)(w * h); if (sum != 0.0) { uniform = sum * sum / w; sumsq = 0.0; for (i = 0; i < w; i++) { numaGetFValue(na, i, &val); sumsq += val * val; } *pvratio = sumsq / uniform; } else { empty = 1; } pixDestroy(&pixt); numaDestroy(&na); } return empty; }
int main(int argc, char **argv) { l_int32 i, j; l_int32 w, h, bw, bh, wpls, rval, gval, bval, same; l_uint32 pixel; l_uint32 *lines, *datas; l_float32 sum1, sum2, 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; static char mainName[] = "numa2_reg"; if (argc != 1) return ERROR_INT(" Syntax: numa2_reg", mainName, 1); lept_mkdir("lept/numa2"); /* -------------------------------------------------------------------* * Numa-windowed stats * * -------------------------------------------------------------------*/ #if DO_ALL na = numaRead("lyra.5.na"); numaWindowedStats(na, 5, &na1, &na2, &na3, &na4); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra6", "Original"); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra7", "Mean"); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra8", "Mean Square"); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra9", "Variance"); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra10", "RMS Difference"); pixa = pixaCreate(5); pix1 = pixRead("/tmp/lept/numa2/lyra6.png"); pix2 = pixRead("/tmp/lept/numa2/lyra7.png"); pix3 = pixRead("/tmp/lept/numa2/lyra8.png"); pix4 = pixRead("/tmp/lept/numa2/lyra9.png"); pix5 = pixRead("/tmp/lept/numa2/lyra10.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, 100, 0); pixWrite("/tmp/lept/numa2/window.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); #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/lept/numa_pixg.png", 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/lept/numa2/ext1", "Horizontal"); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical"); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3", "Slightly more horizontal than vertical"); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4", "Slightly more vertical than horizontal"); pixa = pixaCreate(4); pix1 = pixRead("/tmp/lept/numa2/ext1.png"); pix2 = pixRead("/tmp/lept/numa2/ext2.png"); pix3 = pixRead("/tmp/lept/numa2/ext3.png"); pix4 = pixRead("/tmp/lept/numa2/ext4.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, 100, 450); pixWrite("/tmp/lept/numa2/extract.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixa); pixDestroy(&pixg); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); #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"); pix = pixConvertTo32(pixs); pixRenderPlotFromNumaGen(&pix, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1, 0xff000000); pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); /* 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"); pixRenderPlotFromNumaGen(&pix, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000); pixDisplay(pix, 500, 200); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); pixDestroy(&pix); /* 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); pix1 = pixCopy(NULL, pix); pixRenderPlotFromNumaGen(&pix, na1, L_VERTICAL_LINE, 3, 415, 100, 1, 0xff000000); pixRenderPlotFromNumaGen(&pix, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000); pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00); pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00); pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000); pixDisplay(pix, 500, 900); pixDisplay(pix1, 500, 1000); boxDestroy(&box1); numaDestroy(&na1); numaDestroy(&na2); pixDestroy(&pix); pixDestroy(&pix1); pixDestroy(&pixs); /* Again on a different image */ pix1 = pixRead("boxedpage.jpg"); pix2 = pixConvertTo8(pix1, 0); pixGetDimensions(pix2, &w, &h, NULL); na1 = pixVarianceByRow(pix2, NULL); pix3 = pixConvertTo32(pix1); pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1, 0xff000000); na2 = pixVarianceByColumn(pix2, NULL); pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, 0x00ff0000); pixDisplay(pix3, 1000, 0); numaDestroy(&na1); numaDestroy(&na2); pixDestroy(&pix3); /* Again, with an erosion */ pix3 = pixErodeGray(pix2, 3, 21); pixDisplay(pix3, 1400, 0); na1 = pixVarianceByRow(pix3, NULL); pix4 = pixConvertTo32(pix1); pixRenderPlotFromNumaGen(&pix4, na1, L_VERTICAL_LINE, 3, 30, 70, 1, 0xff000000); na2 = pixVarianceByColumn(pix3, NULL); pixRenderPlotFromNumaGen(&pix4, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, 0x00ff0000); pixDisplay(pix4, 1000, 550); numaDestroy(&na1); numaDestroy(&na2); 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); pix3 = pixCopy(NULL, pix1); /* Plot along horizontal line */ pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0, w, 5, &na1); pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30, 80, 1, 0xff000000); pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000); pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00); /* Plot along vertical line */ pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0, h, 5, &na2); pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000); pixDisplay(pix1, 1000, 1000); pixDisplay(pix3, 1500, 1000); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); numaDestroy(&na1); numaDestroy(&na2); #endif return 0; }
int main(int argc, char **argv) { l_int32 i, j; l_int32 w, h, bw, bh, wpls, rval, gval, bval, same; l_uint32 pixel; l_uint32 *lines, *datas; l_float32 sum1, sum2, 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; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; lept_mkdir("lept/numa2"); /* -------------------------------------------------------------------* * Numa-windowed stats * * -------------------------------------------------------------------*/ na = numaRead("lyra.5.na"); numaWindowedStats(na, 5, &na1, &na2, &na3, &na4); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa2/lyra1", "Original"); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa2/lyra2", "Mean"); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/lyra3", "Mean Square"); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/lyra4", "Variance"); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/lyra5", "RMS Difference"); pix1 = pixRead("/tmp/lept/numa2/lyra1.png"); pix2 = pixRead("/tmp/lept/numa2/lyra2.png"); pix3 = pixRead("/tmp/lept/numa2/lyra3.png"); pix4 = pixRead("/tmp/lept/numa2/lyra4.png"); pix5 = pixRead("/tmp/lept/numa2/lyra5.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 4 */ pixa = pixaCreate(5); 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); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 0, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); /* -------------------------------------------------------------------* * Extraction on a line * * -------------------------------------------------------------------*/ /* 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 */ regTestWritePixAndCheck(rp, pixg, IFF_PNG); /* 5 */ pixDisplayWithTitle(pixg, 0, 300, NULL, rp->display); 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/lept/numa2/ext1", "Horizontal"); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa2/ext2", "Vertical"); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa2/ext3", "Slightly more horizontal than vertical"); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa2/ext4", "Slightly more vertical than horizontal"); pix1 = pixRead("/tmp/lept/numa2/ext1.png"); pix2 = pixRead("/tmp/lept/numa2/ext2.png"); pix3 = pixRead("/tmp/lept/numa2/ext3.png"); pix4 = pixRead("/tmp/lept/numa2/ext4.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 6 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 7 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 8 */ regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 9 */ pixa = pixaCreate(4); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 300, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); pixDestroy(&pixg); pixDestroy(&pixs); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); /* -------------------------------------------------------------------* * Row and column pixel sums * * -------------------------------------------------------------------*/ /* 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); /* for columns */ regTestCompareValues(rp, 1, same, 0); /* 10 */ pix1 = pixConvertTo32(pixs); pixRenderPlotFromNumaGen(&pix1, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1, 0xff000000); pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); /* 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); /* for rows */ regTestCompareValues(rp, 1, same, 0); /* 11 */ pixRenderPlotFromNumaGen(&pix1, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix1, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 12 */ pixDisplayWithTitle(pix1, 0, 600, NULL, rp->display); pixDestroy(&pix1); boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); /* 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 */ regTestCompareValues(rp, 189.59, ave1, 0.01); /* 13 */ regTestCompareValues(rp, 207.89, ave2, 0.01); /* 14 */ if (rp->display) { 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); regTestCompareValues(rp, 0.0, diff1, 0.001); /* 15 */ regTestCompareValues(rp, 10.0, diff2, 10.0); /* 16 */ /* 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 */ regTestCompareValues(rp, 82.06, 0.5 * (var1 + var2), 0.01); /* 17 */ regTestCompareValues(rp, 82.66, var3, 0.01); /* 18 */ boxDestroy(&box1); boxDestroy(&box2); numaDestroy(&na1); numaDestroy(&na2); /* -------------------------------------------------------------------* * Row and column variances * * -------------------------------------------------------------------*/ /* 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); pix1 = pixConvertTo32(pixs); pix2 = pixCopy(NULL, pix1); pixRenderPlotFromNumaGen(&pix1, na1, L_VERTICAL_LINE, 3, 415, 100, 1, 0xff000000); pixRenderPlotFromNumaGen(&pix1, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000); pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00); pixRenderPlotFromNuma(&pix2, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00); pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix2, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 19 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 20 */ pixa = pixaCreate(2); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 400, 600, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); boxDestroy(&box1); numaDestroy(&na1); numaDestroy(&na2); pixDestroy(&pixs); /* Again on a different image */ pix1 = pixRead("boxedpage.jpg"); pix2 = pixConvertTo8(pix1, 0); pixGetDimensions(pix2, &w, &h, NULL); na1 = pixVarianceByRow(pix2, NULL); pix3 = pixConvertTo32(pix1); pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1, 0xff000000); na2 = pixVarianceByColumn(pix2, NULL); pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, 0x00ff0000); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 21 */ numaDestroy(&na1); numaDestroy(&na2); /* Again, with an erosion */ pix4 = pixErodeGray(pix2, 3, 21); na1 = pixVarianceByRow(pix4, NULL); pix5 = pixConvertTo32(pix1); pixRenderPlotFromNumaGen(&pix5, na1, L_VERTICAL_LINE, 3, 30, 70, 1, 0xff000000); na2 = pixVarianceByColumn(pix4, NULL); pixRenderPlotFromNumaGen(&pix5, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1, 0x00ff0000); regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 22 */ pixa = pixaCreate(2); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix5, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 800, 600, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix4); numaDestroy(&na1); numaDestroy(&na2); /* -------------------------------------------------------------------* * Windowed variance along a line * * -------------------------------------------------------------------*/ pix1 = pixRead("boxedpage.jpg"); pix2 = pixConvertTo8(pix1, 0); pixGetDimensions(pix2, &w, &h, NULL); pix3 = pixCopy(NULL, pix1); /* Plot along horizontal line */ pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0, w, 5, &na1); pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30, 80, 1, 0xff000000); pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000); pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00); /* Plot along vertical line */ pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0, h, 5, &na2); pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60, 1, 0x00ff0000); pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000); pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 23 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 24 */ pixa = pixaCreate(2); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 1200, 600, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); pixDestroy(&pix2); numaDestroy(&na1); numaDestroy(&na2); return regTestCleanup(rp);; }