/*! * pixaSelectBySize() * * Input: pixas * width, height (threshold dimensions) * type (L_SELECT_WIDTH, L_SELECT_HEIGHT, * L_SELECT_IF_EITHER, L_SELECT_IF_BOTH) * relation (L_SELECT_IF_LT, L_SELECT_IF_GT, * L_SELECT_IF_LTE, L_SELECT_IF_GTE) * &changed (<optional return> 1 if changed; 0 otherwise) * Return: pixad, or null on error * * Notes: * (1) The args specify constraints on the size of the * components that are kept. * (2) Uses pix and box clones in the new pixa. * (3) If the selection type is L_SELECT_WIDTH, the input * height is ignored, and v.v. * (4) To keep small components, use relation = L_SELECT_IF_LT or * L_SELECT_IF_LTE. * To keep large components, use relation = L_SELECT_IF_GT or * L_SELECT_IF_GTE. */ PIXA * pixaSelectBySize(PIXA *pixas, l_int32 width, l_int32 height, l_int32 type, l_int32 relation, l_int32 *pchanged) { BOXA *boxa; NUMA *na; PIXA *pixad; PROCNAME("pixaSelectBySize"); if (!pixas) return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL); if (type != L_SELECT_WIDTH && type != L_SELECT_HEIGHT && type != L_SELECT_IF_EITHER && type != L_SELECT_IF_BOTH) return (PIXA *)ERROR_PTR("invalid type", procName, NULL); if (relation != L_SELECT_IF_LT && relation != L_SELECT_IF_GT && relation != L_SELECT_IF_LTE && relation != L_SELECT_IF_GTE) return (PIXA *)ERROR_PTR("invalid relation", procName, NULL); /* Compute the indicator array for saving components */ boxa = pixaGetBoxa(pixas, L_CLONE); na = boxaMakeSizeIndicator(boxa, width, height, type, relation); boxaDestroy(&boxa); /* Filter to get output */ pixad = pixaSelectWithIndicator(pixas, na, pchanged); numaDestroy(&na); return pixad; }
/*! * pixaSelectByWidthHeightRatio() * * Input: pixas * thresh (threshold ratio of width/height) * type (L_SELECT_IF_LT, L_SELECT_IF_GT, * L_SELECT_IF_LTE, L_SELECT_IF_GTE) * &changed (<optional return> 1 if changed; 0 if clone returned) * Return: pixad, or null on error * * Notes: * (1) Returns a pixa clone if no components are removed. * (2) Uses pix and box clones in the new pixa. * (3) This filters components based on the width-to-height ratio * of each pix. * (4) Use L_SELECT_IF_LT or L_SELECT_IF_LTE to save components * with less than the threshold ratio, and * L_SELECT_IF_GT or L_SELECT_IF_GTE to remove them. */ PIXA * pixaSelectByWidthHeightRatio(PIXA *pixas, l_float32 thresh, l_int32 type, l_int32 *pchanged) { NUMA *na, *nai; PIXA *pixad; PROCNAME("pixaSelectByWidthHeightRatio"); if (!pixas) return (PIXA *)ERROR_PTR("pixas not defined", procName, NULL); if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT && type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE) return (PIXA *)ERROR_PTR("invalid type", procName, NULL); /* Compute component ratios. */ na = pixaFindWidthHeightRatio(pixas); /* Generate indicator array for elements to be saved. */ nai = numaMakeThresholdIndicator(na, thresh, type); numaDestroy(&na); /* Filter to get output */ pixad = pixaSelectWithIndicator(pixas, nai, pchanged); numaDestroy(&nai); return pixad; }
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; }