/*! * \return Interiority score for the test object. * \ingroup WlzFeatures * \brief Computes an interiority score for the test object with * respect to the given distance object. See WlzInteriority(). * \param disObj Given distance object. * \param tstObjs Array of test objects. * \param dstErr Destination error pointer, may be NULL. */ static double WlzInteriorityPrv( WlzObject *disObj, WlzObject *tstObj, WlzErrorNum *dstErr) { double score = 0.0; WlzErrorNum errNum = WLZ_ERR_NONE; if(tstObj->type != WLZ_EMPTY_OBJ) { WlzObject *isn = NULL; isn = WlzAssignObject( WlzIntersect2(disObj, tstObj, &errNum), NULL); if((errNum == WLZ_ERR_NONE) && (isn != NULL) && (WlzIsEmpty(isn, NULL) == 0)) { WlzPixelV bgd; WlzObjectType gtt; WlzObject *ist = NULL, *isv = NULL; bgd.v.inv = 0; bgd.type = WLZ_GREY_INT; gtt = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_INT, NULL); isv = WlzNewObjectValues(isn, gtt, bgd, 0, bgd, &errNum); if(errNum == WLZ_ERR_NONE) { ist = WlzAssignObject( WlzGreyTransfer(isv, disObj, 0, &errNum), NULL); } (void )WlzFreeObj(isv); if(errNum == WLZ_ERR_NONE) { (void )WlzGreyStats(ist, NULL, NULL, NULL, NULL, NULL, &score, NULL, &errNum); } (void )WlzFreeObj(ist); } (void )WlzFreeObj(isn); } if(dstErr) { *dstErr = errNum; } return(score); }
/*! * \return New Woolz object or NULL on error. * \ingroup WlzValuesUtils * \brief Creates a new Woolz object in which the background value * is as given. The given object must be either a 2D or 3D * domain object with a valid domain, however it's values can * be NULL. If the values are NULL then a new value table is * created with the same grey type as the given background * value, or if non-NULL then a new value table is created * while sharing the values of the original object's value * table when this is possible. The given object remains * unchanged apart from linkcounts. * \param gObj Given object. * \param bgdV Given background value. * \param dstErr Destination error pointer, may be NULL. */ WlzObject *WlzSetBackGroundNewObj( WlzObject *gObj, WlzPixelV bgdV, WlzErrorNum *dstErr) { WlzObjectType tType; WlzObject *rObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; if(gObj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(gObj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(gObj->values.core == NULL) { /* Given object has NULL values so create a new value table. */ tType = WlzGreyValueTableType(0, WLZ_GREY_TAB_RAGR, bgdV.type, &errNum); if(errNum == WLZ_ERR_NONE) { rObj = WlzNewObjectValues(gObj, tType, bgdV, 1, bgdV, &errNum); } } else { /* Given object has values so create new value table using the same * values. */ rObj = WlzNewObjectValueTable(gObj, bgdV, &errNum); } if(dstErr) { *dstErr = errNum; } return(rObj); }
/*! * \return New filtered object with new values or NULL on error. * \ingroup WlzValuesFilters * \brief Applies a seperable filter along the z axis (planes) * to the given object using the given convolution kernel. * \param inObj Input 3D spatial domain object to be * filtered which must have scalar values. * \param bBox Object's bounding box. * \param maxThr Maximum number of threads to use. * \param iBuf Working buffers large enough for any * column in the image with one for each * thread. * \param rBuf Buffers as for iBuf. * \param cBufSz Convolution kernel size. * \param cBuf Convolution kernel buffer. * \param pad Type of padding. * \param padVal Padding value. * \param dstErr Destination error pointer may be NULL. */ static WlzObject *WlzSepFilterZ(WlzObject *inObj, WlzIBox3 bBox, int maxThr, double **iBuf, double **rBuf, int cBufSz, double *cBuf, AlgPadType pad, double padVal, WlzErrorNum *dstErr) { WlzObjectType rGTT; WlzPixelV zV; WlzObject *rnObj = NULL; WlzGreyValueWSpace **iVWSp = NULL, **rVWSp = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; zV.v.dbv = 0.0; zV.type = WLZ_GREY_DOUBLE; rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL); rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum); if(errNum == WLZ_ERR_NONE) { if(((iVWSp = (WlzGreyValueWSpace **) AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL) || ((rVWSp = (WlzGreyValueWSpace **) AlcCalloc(maxThr, sizeof(WlzGreyValueWSpace *))) == NULL)) { errNum = WLZ_ERR_MEM_ALLOC; } } if(errNum == WLZ_ERR_NONE) { int idt; for(idt = 0; (idt < maxThr) && (errNum == WLZ_ERR_NONE); ++idt) { iVWSp[idt] = WlzGreyValueMakeWSp(inObj, &errNum); if(errNum == WLZ_ERR_NONE) { rVWSp[idt] = WlzGreyValueMakeWSp(rnObj, &errNum); } } } if(errNum == WLZ_ERR_NONE) { int idy; #ifdef _OPENMP #pragma omp parallel for num_threads(maxThr) #endif for(idy = bBox.yMin; idy <= bBox.yMax; ++idy) { int idx, thrId = 0; WlzGreyValueWSpace *iVWSpT, *rVWSpT; #ifdef _OPENMP thrId = omp_get_thread_num(); #endif iVWSpT = iVWSp[thrId]; rVWSpT = rVWSp[thrId]; for(idx = bBox.xMin; idx <= bBox.xMax; ++idx) { int z0, z1, idz; WlzUByte in = 0; for(idz = bBox.zMin; idz <= bBox.zMax + 1; ++idz) { WlzGreyValueGet(iVWSpT, idz, idy, idx); if(iVWSpT->bkdFlag == 0) { double *ibp; if(in == 0) { z0 = idz; in = 1; } z1 = idz; ibp = iBuf[thrId] + (z1 - z0); switch(iVWSpT->gType) { case WLZ_GREY_INT: *ibp = iVWSpT->gVal[0].inv; break; case WLZ_GREY_SHORT: *ibp = iVWSpT->gVal[0].shv; break; case WLZ_GREY_UBYTE: *ibp = iVWSpT->gVal[0].ubv; break; case WLZ_GREY_FLOAT: *ibp = iVWSpT->gVal[0].flv; break; case WLZ_GREY_DOUBLE: *ibp = iVWSpT->gVal[0].dbv; break; default: break; } } else if(in) { int idr, len; len = z1 - z0 + 1; AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf, len, iBuf[thrId], pad, padVal); for(idr = z0; idr <= z1; ++idr) { WlzGreyValueGet(rVWSpT, idr, idy, idx); *(rVWSpT->gPtr[0].dbp) = rBuf[thrId][idr - z0]; } } } } } } if(iVWSp) { int idt; for(idt = 0; idt < maxThr; ++idt) { WlzGreyValueFreeWSp(iVWSp[idt]); } AlcFree(iVWSp); } if(rVWSp) { int idt; for(idt = 0; idt < maxThr; ++idt) { WlzGreyValueFreeWSp(rVWSp[idt]); } AlcFree(rVWSp); } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rnObj); rnObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rnObj); }
/*! * \return New filtered object with new values or NULL on error. * \ingroup WlzValuesFilters * \brief Applies a seperable filter along the y axis (lines) * to the given object using the given convolution kernel. * \param inObj Input 2 or 3D spatial domain object * to be filtered which must have scalar * values. * \param dim Object's dimension. * \param maxThr Maximum number of threads to use. * \param iBuf Working buffers large enough for any * column in the image with one for each * thread. * \param rBuf Buffers as for iBuf. * \param cBufSz Convolution kernel size. * \param cBuf Convolution kernel buffer. * \param pad Type of padding. * \param padVal Padding value. * \param dstErr Destination error pointer may be NULL. */ static WlzObject *WlzSepFilterY(WlzObject *inObj, int dim, int maxThr, double **iBuf, double **rBuf, int cBufSz, double *cBuf, AlgPadType pad, double padVal, WlzErrorNum *dstErr) { int idp, poff, nPln; WlzObjectType rGTT; WlzDomain *domains; WlzValues *iVal, *rVal; WlzPixelV zV; WlzObject *rnObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; zV.v.dbv = 0.0; zV.type = WLZ_GREY_DOUBLE; rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL); if(dim == 3) { WlzPlaneDomain *pDom; WlzVoxelValues *vVal; pDom = inObj->domain.p; vVal = inObj->values.vox; nPln = pDom->lastpl - pDom->plane1 + 1; domains = pDom->domains; iVal = vVal->values; poff = pDom->plane1 - vVal->plane1; rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum); if(errNum == WLZ_ERR_NONE) { rVal = rnObj->values.vox->values; } } else { nPln = 1; poff = 0; domains = &(inObj->domain); iVal = &(inObj->values); rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum); if(errNum == WLZ_ERR_NONE) { rVal = &(rnObj->values); } } if(errNum == WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp parallel for num_threads(maxThr) #endif for(idp = 0; idp < nPln; ++idp) { if(errNum == WLZ_ERR_NONE) { if(domains[idp].core != NULL) { int thrId = 0; WlzIBox2 bBox; WlzObject *iObj = NULL, *rObj = NULL; WlzGreyValueWSpace *iVWSp = NULL, *rVWSp = NULL; WlzErrorNum errNum2 = WLZ_ERR_NONE; #ifdef _OPENMP thrId = omp_get_thread_num(); #endif iObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], iVal[idp + poff], NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], rVal[idp], NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { bBox = WlzBoundingBox2I(iObj, &errNum); } if((errNum == WLZ_ERR_NONE) && ((iVWSp = WlzGreyValueMakeWSp(iObj, &errNum)) != NULL) && ((rVWSp = WlzGreyValueMakeWSp(rObj, &errNum)) != NULL)) { int idx; for(idx = bBox.xMin; idx <= bBox.xMax; ++idx) { int y0, y1, idy; WlzUByte in = 0; for(idy = bBox.yMin; idy <= bBox.yMax + 1; ++idy) { WlzGreyValueGet(iVWSp, 0, idy, idx); if(iVWSp->bkdFlag == 0) { double *ibp; if(in == 0) { y0 = idy; in = 1; } y1 = idy; ibp = iBuf[thrId] + (y1 - y0); switch(iVWSp->gType) { case WLZ_GREY_INT: *ibp = iVWSp->gVal[0].inv; break; case WLZ_GREY_SHORT: *ibp = iVWSp->gVal[0].shv; break; case WLZ_GREY_UBYTE: *ibp = iVWSp->gVal[0].ubv; break; case WLZ_GREY_FLOAT: *ibp = iVWSp->gVal[0].flv; break; case WLZ_GREY_DOUBLE: *ibp = iVWSp->gVal[0].dbv; break; default: break; } } else if(in) { int idr, len; len = y1 - y0 + 1; AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf, len, iBuf[thrId], pad, padVal); for(idr = y0; idr <= y1; ++idr) { WlzGreyValueGet(rVWSp, 0, idr, idx); *(rVWSp->gPtr[0].dbp) = rBuf[thrId][idr - y0]; } } } } } WlzGreyValueFreeWSp(iVWSp); WlzGreyValueFreeWSp(rVWSp); (void )WlzFreeObj(iObj); (void )WlzFreeObj(rObj); if(errNum2 != WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2; } #ifdef _OPENMP } #endif } } } } } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rnObj); rnObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rnObj); }
/*! * \return New filtered object with new values or NULL on error. * \ingroup WlzValuesFilters * \brief Applies a seperable filter along the x axis (columns) * to the given object using the given convolution kernel. * \param inObj Input 2 or 3D spatial domain object * to be filtered which must have scalar * values. * \param dim Object's dimension. * \param maxThr Maximum number of threads to use. * \param iBuf Working buffers large enough for any * line in the image with one for each * thread. * \param rBuf Buffers as for iBuf. * \param cBufSz Convolution kernel size. * \param cBuf Convolution kernel buffer. * \param pad Type of padding. * \param padVal Padding value. * \param dstErr Destination error pointer may be NULL. */ static WlzObject *WlzSepFilterX(WlzObject *inObj, int dim, int maxThr, double **iBuf, double **rBuf, int cBufSz, double *cBuf, AlgPadType pad, double padVal, WlzErrorNum *dstErr) { int idp, poff, nPln; WlzObjectType rGTT; WlzDomain *domains; WlzValues *iVal, *rVal; WlzPixelV zV; WlzObject *rnObj = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; zV.v.dbv = 0.0; zV.type = WLZ_GREY_DOUBLE; rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL); if(dim == 3) { WlzPlaneDomain *pDom; WlzVoxelValues *vVal; pDom = inObj->domain.p; vVal = inObj->values.vox; nPln = pDom->lastpl - pDom->plane1 + 1; domains = pDom->domains; iVal = vVal->values; poff = pDom->plane1 - vVal->plane1; rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum); if(errNum == WLZ_ERR_NONE) { rVal = rnObj->values.vox->values; } } else { nPln = 1; poff = 0; domains = &(inObj->domain); iVal = &(inObj->values); rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum); if(errNum == WLZ_ERR_NONE) { rVal = &(rnObj->values); } } if(errNum == WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp parallel for num_threads(maxThr) #endif for(idp = 0; idp < nPln; ++idp) { if(errNum == WLZ_ERR_NONE) { if(domains[idp].core != NULL) { int thrId = 0; WlzObject *iObj = NULL, *rObj = NULL; WlzIntervalWSpace iIWSp, rIWSp; WlzGreyWSpace iGWSp, rGWSp; WlzErrorNum errNum2 = WLZ_ERR_NONE; #ifdef _OPENMP thrId = omp_get_thread_num(); #endif iObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], iVal[idp + poff], NULL, NULL, &errNum2); if(errNum2 == WLZ_ERR_NONE) { rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], rVal[idp], NULL, NULL, &errNum2); } if((errNum2 == WLZ_ERR_NONE) && ((errNum2 = WlzInitGreyScan(iObj, &iIWSp, &iGWSp)) == WLZ_ERR_NONE) && ((errNum2 = WlzInitGreyScan(rObj, &rIWSp, &rGWSp)) == WLZ_ERR_NONE)) { while(((errNum2 = WlzNextGreyInterval(&iIWSp)) == WLZ_ERR_NONE) && ((errNum2 = WlzNextGreyInterval(&rIWSp)) == WLZ_ERR_NONE)) { size_t len; WlzGreyP iBufGP; iBufGP.dbp = iBuf[thrId]; len = iIWSp.rgtpos - iIWSp.lftpos + 1; WlzValueCopyGreyToGrey(iBufGP, 0, WLZ_GREY_DOUBLE, iGWSp.u_grintptr, 0, iGWSp.pixeltype, len); AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf, len, iBuf[thrId], pad, padVal); WlzValueCopyDoubleToDouble(rGWSp.u_grintptr.dbp, rBuf[thrId], len); } (void )WlzEndGreyScan(&iIWSp, &iGWSp); (void )WlzEndGreyScan(&rIWSp, &rGWSp); if(errNum2 == WLZ_ERR_EOO) { errNum2 = WLZ_ERR_NONE; } } (void )WlzFreeObj(iObj); (void )WlzFreeObj(rObj); if(errNum2 != WLZ_ERR_NONE) { #ifdef _OPENMP #pragma omp critical { #endif if(errNum == WLZ_ERR_NONE) { errNum = errNum2; } #ifdef _OPENMP } #endif } } } } } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(rnObj); rnObj = NULL; } if(dstErr) { *dstErr = errNum; } return(rnObj); }