int main(int argc, char **argv) { int idx, option, deriv = 0, asciiFlag = 0, rsvFlag = 0, ok = 1, usage = 0; double sigma = 1.0; WlzErrorNum errNum = WLZ_ERR_NONE; FILE *fP = NULL; WlzHistogramDomain *histDom; WlzObject *inObj = NULL, *outObj = NULL; char *outObjFileStr, *inObjFileStr; const char *errMsg; static char optList[] = "aro:d:s:h", outObjFileStrDef[] = "-", inObjFileStrDef[] = "-"; opterr = 0; outObjFileStr = outObjFileStrDef; inObjFileStr = inObjFileStrDef; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'a': asciiFlag = 1; break; case 'r': rsvFlag = 1; break; case 'o': outObjFileStr = optarg; break; case 'd': if((sscanf(optarg, "%d", &deriv) != 1) || (deriv < 0) || (deriv > 2)) { usage = 1; ok = 0; } break; case 's': if(sscanf(optarg, "%lg", &sigma) != 1) { usage = 1; ok = 0; } break; case 'h': default: usage = 1; ok = 0; break; } } if((inObjFileStr == NULL) || (*inObjFileStr == '\0') || (outObjFileStr == NULL) || (*outObjFileStr == '\0')) { ok = 0; usage = 1; } if(ok && (optind < argc)) { if((optind + 1) != argc) { usage = 1; ok = 0; } else { inObjFileStr = *(argv + optind); } } if(ok) { errNum = WLZ_ERR_READ_EOF; if((inObjFileStr == NULL) || (*inObjFileStr == '\0') || ((fP = (strcmp(inObjFileStr, "-")? fopen(inObjFileStr, "r"): stdin)) == NULL) || ((inObj= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read object from file %s (%s).\n", *argv, inObjFileStr, errMsg); } if(fP && strcmp(inObjFileStr, "-")) { fclose(fP); } } if(ok) { if(inObj->type != WLZ_HISTOGRAM) { ok = 0; (void )fprintf(stderr, "%s: input object read from file %s not a histogram\n", *argv, inObjFileStr); } } if(ok) { outObj = WlzAssignObject(inObj, NULL); if(rsvFlag) { errNum = WlzHistogramRsvGauss(outObj, sigma, deriv); } else { errNum = WlzHistogramCnvGauss(outObj, sigma, deriv); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to filter histogram (%s).\n", *argv, errMsg); } } if(ok) { if(asciiFlag) { if((fP = (strcmp(outObjFileStr, "-")? fopen(outObjFileStr, "w"): stdout)) == NULL) { ok = 0; (void )fprintf(stderr, "%s: failed to write output data\n", *argv); } else { histDom = outObj->domain.hist; switch(histDom->type) { case WLZ_HISTOGRAMDOMAIN_INT: for(idx = 0; idx < histDom->nBins; ++idx) { fprintf(fP, "%8g %8d\n", histDom->origin + (idx * histDom->binSize), *(histDom->binValues.inp + idx)); } break; case WLZ_HISTOGRAMDOMAIN_FLOAT: for(idx = 0; idx < histDom->nBins; ++idx) { fprintf(fP, "%8g %8g\n", histDom->origin + (idx * histDom->binSize), *(histDom->binValues.dbp + idx)); } break; default: break; } } } else { errNum = WLZ_ERR_WRITE_EOF; if(((fP = (strcmp(outObjFileStr, "-")? fopen(outObjFileStr, "w"): stdout)) == NULL) || ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write output object (%s).\n", *argv, errMsg); } } if(fP && strcmp(outObjFileStr, "-")) { fclose(fP); } } if(inObj) { WlzFreeObj(inObj); } if(outObj) { WlzFreeObj(outObj); } if(usage) { (void )fprintf(stderr, "Usage: %s%s%s%sExample: %s%s", *argv, " [-h] [-a] [-r] [-o<out file>] [-d#] [-s#] [<in object>]\n" "Version: ", WlzVersion(), "\n" "Options:\n" " -a Output the histogram as ascii data not a Woolz histogram object.\n" " -r Use a recursive IIR filter.\n" " -o Output object/data file name.\n" " -d Derivative, range [0-2].\n" " -s Gaussian sigma (standard deviation).\n" " -h Help, prints this usage message.\n" "Convolves the bin values of a Woolz histogram object with a Gaussian\n" "or it's 1st or 2nd derivtive.\n" "Objects/data are read from stdin and written to stdout unless the\n" "filenames are given.\n", *argv, " -s3 -a myhist.wlz | xgraph\n" "The input Woolz histogram object is read from myhist.wlz, filtered\n" "by convolving the histogram bins with a Gaussian (sigma = 3.0) and\n" "written as ascii to the program xgraph for display.\n"); } return(!ok); }
/*! * \return Woolz error code. * \ingroup WlzBinaryOps * \brief Splits the reference object into component objects cliped * from the reference object, with the bounding box of each * of the component objects determined using the pre-processed * object. The component objects are returned in size order. * \param refObj Reference object. * \param ppObj Pre-processed object which is * normalised to values in the range * 0 - 255 as WlzUByte greys. * \param bWidth Border width. * \param bgdFrac Minimum fraction of values which are * background values, with range * [0.0+ - 1.0-]. * \param sigma Histogram smoothing parameter used * by WlzHistogramCnvGauss(). * \param compThrMethod Method for computing threshold, used * in call to WlzCompThresholdVT(). * \param nReqComp Number of required components. * \param dstNComp Destination pointer for the number of * components extracted, must not be NULL. * \param dstComp Destination pointer for the extracted * components, must not be NULL. */ WlzErrorNum WlzSplitObj(WlzObject *refObj, WlzObject *ppObj, int bWidth, double bgdFrac, double sigma, WlzCompThreshType compThrMethod, int nReqComp, int *dstNComp, WlzObject ***dstComp) { int dim, idC; WlzObject *hObj = NULL, *tObj = NULL; WlzObject **comp = NULL; WlzBox box; WlzPixelV tV; WlzSplitObjData split; WlzThresholdType tType; WlzConnectType lCon; WlzErrorNum errNum = WLZ_ERR_NONE; const int maxComp = 1024; split.nLComp = 0; split.compI = NULL; split.lCompSz = NULL; split.lComp = NULL; if((refObj == NULL) || (ppObj == NULL)) { errNum = WLZ_ERR_OBJECT_NULL; } else if((refObj->domain.core == NULL) || (ppObj->domain.core == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else if((refObj->values.core == NULL) || (ppObj->values.core == NULL)) { errNum = WLZ_ERR_VALUES_NULL; } else if(refObj->type != ppObj->type) { errNum = WLZ_ERR_OBJECT_TYPE; } else if((dstNComp == NULL) || (dstComp == NULL)) { errNum = WLZ_ERR_PARAM_NULL; } else if((bgdFrac < DBL_EPSILON) || (bgdFrac > (1.0 - DBL_EPSILON))) { errNum = WLZ_ERR_PARAM_DATA; } else { switch(refObj->type) { case WLZ_2D_DOMAINOBJ: dim = 2; lCon = WLZ_8_CONNECTED; break; case WLZ_3D_DOMAINOBJ: dim = 3; lCon = WLZ_26_CONNECTED; break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Compute threshold value and type from histogram. */ if(errNum == WLZ_ERR_NONE) { hObj = WlzAssignObject( WlzHistogramObj(ppObj, 256, 0.0, 1.0, &errNum), NULL); } if(errNum == WLZ_ERR_NONE) { errNum = WlzHistogramCnvGauss(hObj, sigma, 0); } if(errNum == WLZ_ERR_NONE) { errNum = WlzCompThresholdVT(hObj, compThrMethod, bgdFrac, 0.0, 0.0, &tV, &tType); } (void )WlzFreeObj(hObj); hObj = NULL; /* Threshold object. */ if(errNum == WLZ_ERR_NONE) { tObj = WlzAssignObject( WlzThreshold(ppObj, tV, tType, &errNum), NULL); } /* Label to get connected components. */ if(errNum == WLZ_ERR_NONE) { errNum = WlzLabel(tObj, &(split.nLComp), &(split.lComp), maxComp, 0, lCon); } /* Sort connected components by size. */ if(errNum == WLZ_ERR_NONE) { if(split.nLComp < nReqComp) { nReqComp = split.nLComp; } if(((split.compI = (int *)AlcMalloc(sizeof(int) * split.nLComp)) == NULL) || ((split.lCompSz = (int *)AlcMalloc(sizeof(int) * split.nLComp)) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } } if(errNum == WLZ_ERR_NONE) { idC = 0; while((errNum == WLZ_ERR_NONE) && (idC < split.nLComp)) { split.compI[idC] = idC; split.lCompSz[idC] = (dim == 2)? WlzArea(split.lComp[idC], &errNum): WlzVolume(split.lComp[idC], &errNum); ++idC; } } if(errNum == WLZ_ERR_NONE) { /* Sort component indices by component size. */ AlgQSort(split.compI, split.nLComp, sizeof(int), &split, WlzSplitObjSortSzFn); /* Allocate array for cliped component objects. */ if((comp = (WlzObject **)AlcCalloc(sizeof(WlzObject *), split.nLComp)) == NULL) { errNum = WLZ_ERR_MEM_ALLOC; } } /* Compute bounding box and clip objects from the reference object. */ if(errNum == WLZ_ERR_NONE) { idC = 0; while((errNum == WLZ_ERR_NONE) && (idC < nReqComp)) { if(dim == 2) { box.i2 = WlzBoundingBox2I(split.lComp[split.compI[idC]], &errNum); if(errNum == WLZ_ERR_NONE) { box.i2.xMin -= bWidth; box.i2.yMin -= bWidth; box.i2.xMax += bWidth; box.i2.yMax += bWidth; comp[idC] = WlzClipObjToBox2D(refObj, box.i2, &errNum); } } else /* dim == 3 */ { box.i3 = WlzBoundingBox3I(split.lComp[split.compI[idC]], &errNum); if(errNum == WLZ_ERR_NONE) { box.i3.xMin -= bWidth; box.i3.yMin -= bWidth; box.i3.zMin -= bWidth; box.i3.xMax += bWidth; box.i3.yMax += bWidth; box.i3.zMax += bWidth; comp[idC] = WlzClipObjToBox3D(refObj, box.i3, &errNum); } } ++idC; } } if(errNum == WLZ_ERR_NONE) { *dstNComp = nReqComp; *dstComp = comp; } /* Free temporary storage. */ if(split.lComp) { for(idC = 0; idC < split.nLComp; ++idC) { (void )WlzFreeObj(split.lComp[idC]); } AlcFree(split.lComp); } AlcFree(split.compI); AlcFree(split.lCompSz); (void )WlzFreeObj(tObj); return(errNum); }