/*! * \brief pixConnCompIncrInit() * * \param[in] pixs 1 bpp * \param[in] conn connectivity: 4 or 8 * \param[out] ppixd 32 bpp, with c.c. labelled * \param[out] pptaa with pixel locations indexed by c.c. * \param[out] pncc initial number of c.c. * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) This labels the connected components in a 1 bpp pix, and * additionally sets up a ptaa that lists the locations of pixels * in each of the components. * (2) It can be used to initialize the output image and arrays for * an application that maintains information about connected * components incrementally as pixels are added. * (3) pixs can be empty or have some foreground pixels. * (4) The connectivity is stored in pixd->special. * (5) Always initialize with the first pta in ptaa being empty * and representing the background value (index 0) in the pix. * </pre> */ l_int32 pixConnCompIncrInit(PIX *pixs, l_int32 conn, PIX **ppixd, PTAA **pptaa, l_int32 *pncc) { l_int32 empty, w, h, ncc; PIX *pixd; PTA *pta; PTAA *ptaa; PROCNAME("pixConnCompIncrInit"); if (ppixd) *ppixd = NULL; if (pptaa) *pptaa = NULL; if (pncc) *pncc = 0; if (!ppixd || !pptaa || !pncc) return ERROR_INT("&pixd, &ptaa, &ncc not all defined", procName, 1); if (!pixs || pixGetDepth(pixs) != 1) return ERROR_INT("pixs undefined or not 1 bpp", procName, 1); if (conn != 4 && conn != 8) return ERROR_INT("connectivity must be 4 or 8", procName, 1); pixGetDimensions(pixs, &w, &h, NULL); pixZero(pixs, &empty); if (empty) { *ppixd = pixCreate(w, h, 32); pixSetSpp(*ppixd, 1); pixSetSpecial(*ppixd, conn); *pptaa = ptaaCreate(0); pta = ptaCreate(1); ptaaAddPta(*pptaa, pta, L_INSERT); /* reserve index 0 for background */ return 0; } /* Set up the initial labeled image and indexed pixel arrays */ if ((pixd = pixConnCompTransform(pixs, conn, 32)) == NULL) return ERROR_INT("pixd not made", procName, 1); pixSetSpecial(pixd, conn); *ppixd = pixd; if ((ptaa = ptaaIndexLabeledPixels(pixd, &ncc)) == NULL) return ERROR_INT("ptaa not made", procName, 1); *pptaa = ptaa; *pncc = ncc; return 0; }
l_int32 main(int argc, char **argv) { l_float32 dist, distr, distg, distb; NUMA *na1, *na2; PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; /* Test earthmover distance: extreme DC */ fprintf(stderr, "Test earthmover distance\n"); na1 = numaMakeConstant(0, 201); na2 = numaMakeConstant(0, 201); numaSetValue(na1, 0, 100); numaSetValue(na2, 200, 100); numaEarthMoverDistance(na1, na2, &dist); regTestCompareValues(rp, 200.0, dist, 0.0001); /* 0 */ numaDestroy(&na1); numaDestroy(&na2); /* Test connected component labelling */ fprintf(stderr, "Test c.c. labelling\n"); pix1 = pixRead("feyn-fract.tif"); pix2 = pixConnCompTransform(pix1, 8, 8); regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); pix3 = pixConnCompTransform(pix1, 8, 16); pix4 = pixConvert16To8(pix3, L_LS_BYTE); regTestCompareSimilarPix(rp, pix2, pix4, 3, 0.001, 0); /* 2 */ pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); /* Test connected component area labelling */ fprintf(stderr, "Test c.c. area labelling\n"); pix2 = pixConnCompAreaTransform(pix1, 8); pix3 = pixConvert16To8(pix2, L_CLIP_TO_255); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3 */ pixDisplayWithTitle(pix3, 0, 350, NULL, rp->display); pixMultConstantGray(pix2, 0.3); pix4 = pixConvert16To8(pix2, L_LS_BYTE); regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */ pixDisplayWithTitle(pix4, 0, 700, NULL, rp->display); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); /* Test color transform: 4-fold symmetry */ fprintf(stderr, "Test color transform: 4-fold symmetry\n"); pix1 = pixRead("form1.tif"); pix2 = pixRotateOrth(pix1, 1); pix3 = pixRotateOrth(pix1, 2); pix4 = pixRotateOrth(pix1, 3); pix5 = pixLocToColorTransform(pix1); regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 5 */ pix6 = pixLocToColorTransform(pix2); regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 6 */ FindEMD(pix5, pix6, &distr, &distg, &distb); regTestCompareValues(rp, 0.12, distr, 0.01); /* 7 */ regTestCompareValues(rp, 0.00, distg, 0.01); /* 8 */ regTestCompareValues(rp, 0.00, distb, 0.01); /* 9 */ fprintf(stderr, "90 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix6); pix6 = pixLocToColorTransform(pix3); regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 10 */ FindEMD(pix5, pix6, &distr, &distg, &distb); regTestCompareValues(rp, 0.12, distr, 0.01); /* 11 */ regTestCompareValues(rp, 0.09, distg, 0.01); /* 12 */ regTestCompareValues(rp, 0.00, distb, 0.01); /* 13 */ fprintf(stderr, "180 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix6); pix6 = pixLocToColorTransform(pix4); regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 14 */ FindEMD(pix5, pix6, &distr, &distg, &distb); regTestCompareValues(rp, 0.00, distr, 0.01); /* 15 */ regTestCompareValues(rp, 0.09, distg, 0.01); /* 16 */ regTestCompareValues(rp, 0.00, distb, 0.01); /* 17 */ fprintf(stderr, "270 deg rotation: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); /* Test color transform: same form with translation */ fprintf(stderr, "Test color transform with translation\n"); pix1 = pixRead("form1.tif"); pix2 = pixLocToColorTransform(pix1); pixDisplayWithTitle(pix2, 0, 0, NULL, rp->display); pixTranslate(pix1, pix1, 10, 10, L_BRING_IN_WHITE); pix3 = pixLocToColorTransform(pix1); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 18 */ pixDisplayWithTitle(pix3, 470, 0, NULL, rp->display); FindEMD(pix2, pix3, &distr, &distg, &distb); regTestCompareValues(rp, 1.76, distr, 0.01); /* 19 */ regTestCompareValues(rp, 2.65, distg, 0.01); /* 20 */ regTestCompareValues(rp, 2.03, distb, 0.01); /* 21 */ fprintf(stderr, "Translation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Test color transform: same form with small rotation */ fprintf(stderr, "Test color transform with small rotation\n"); pix1 = pixRead("form1.tif"); pix2 = pixLocToColorTransform(pix1); pixRotateShearCenterIP(pix1, 0.1, L_BRING_IN_WHITE); pix3 = pixLocToColorTransform(pix1); regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 22 */ pixDisplayWithTitle(pix3, 880, 0, NULL, rp->display); FindEMD(pix2, pix3, &distr, &distg, &distb); regTestCompareValues(rp, 1.50, distr, 0.01); /* 23 */ regTestCompareValues(rp, 1.71, distg, 0.01); /* 24 */ regTestCompareValues(rp, 1.42, distb, 0.01); /* 25 */ fprintf(stderr, "Rotation dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Test color transform: 2 different forms */ fprintf(stderr, "Test color transform (2 forms)\n"); pix1 = pixRead("form1.tif"); pix2 = pixLocToColorTransform(pix1); pixDisplayWithTitle(pix2, 0, 600, NULL, rp->display); pix3 = pixRead("form2.tif"); pix4 = pixLocToColorTransform(pix3); regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 25 */ pixDisplayWithTitle(pix4, 470, 600, NULL, rp->display); FindEMD(pix2, pix4, &distr, &distg, &distb); regTestCompareValues(rp, 6.10, distr, 0.02); /* 27 */ regTestCompareValues(rp, 11.13, distg, 0.01); /* 28 */ regTestCompareValues(rp, 10.53, distb, 0.01); /* 29 */ fprintf(stderr, "Different forms: dist (r,g,b) = (%5.2f, %5.2f, %5.2f)\n", distr, distg, distb); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); return regTestCleanup(rp); }