/*! * \return Returns a preprocessed object for registration. * \ingroup WlzRegistration * \brief * \param obj Given object. * \param inv Flag, non zero if object values are * to be inverted. * \param dstErr Destination error pointer, * may be NULL. */ static WlzObject *WlzRegCCorNormaliseObj2D(WlzObject *obj, int inv, WlzErrorNum *dstErr) { WlzGreyType gType; WlzPixelV min, max, mean, minN, maxN, zero; WlzObject *obj0 = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; /* Normalise the object inverting the grey values if required -> obj0. */ minN.v.ubv = 0; maxN.v.ubv = 255; zero.v.ubv = 0; min.type = WLZ_GREY_DOUBLE; max.type = WLZ_GREY_DOUBLE; mean.type = WLZ_GREY_UBYTE; minN.type = WLZ_GREY_UBYTE; maxN.type = WLZ_GREY_UBYTE; zero.type = WLZ_GREY_UBYTE; mean.v.ubv = 128; if(inv) { minN.v.ubv = 255; maxN.v.ubv = 0; } (void )WlzGreyStats(obj, &gType, &(min.v.dbv), &(max.v.dbv), NULL, NULL, NULL, NULL, &errNum); if(errNum == WLZ_ERR_NONE) { WlzValueConvertPixel(&min, min, gType); WlzValueConvertPixel(&max, max, gType); WlzValueConvertPixel(&minN, minN, gType); WlzValueConvertPixel(&maxN, maxN, gType); obj0 = WlzCopyObject(obj, &errNum); } if(errNum == WLZ_ERR_NONE) { errNum = WlzSetBackground(obj0, zero); errNum = WlzGreySetRange(obj0, min, max, minN, maxN, 0); } if(errNum != WLZ_ERR_NONE) { (void )WlzFreeObj(obj0); obj0 = NULL; } if(dstErr) { *dstErr = errNum; } return(obj0); }
/*! * \return Woolz error number * \ingroup WlzValuesFilters * \brief Normalizes the the grey values of the input object to * fill the range 0-255. Colour values are independently * reset which will change colour balance. Use WlzGreySetRange * directly to avoid this. * Note grey-values are reset in place and not copied. * \par Source: * WlzGreyNormalise.c * \param obj Input object. * \param Dither values if destination range is greater than source * range and this flag is non-zero. */ WlzErrorNum WlzGreyNormalise( WlzObject *obj, int dither) { WlzPixelV min, max, Min, Max; WlzErrorNum errNum=WLZ_ERR_NONE; /* get then set the grey-range of the object */ errNum = WlzGreyRange(obj, &min, &max); Min = min; Max = max; if( errNum == WLZ_ERR_NONE ){ switch( min.type ){ case WLZ_GREY_INT: Min.v.inv = 0; Max.v.inv = 255; break; case WLZ_GREY_SHORT: Min.v.shv = 0; Max.v.shv = 255; break; case WLZ_GREY_UBYTE: Min.v.ubv = 0; Max.v.ubv = 255; break; case WLZ_GREY_FLOAT: Min.v.flv = 0.0; Max.v.flv = 255.0; break; case WLZ_GREY_DOUBLE: Min.v.dbv = 0.0; Max.v.dbv = 255.0; break; case WLZ_GREY_RGBA: Min.v.rgbv = 0xff000000; Max.v.rgbv = 0xffffffff; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } if(errNum == WLZ_ERR_NONE) { errNum = WlzGreySetRange(obj, min, max, Min, Max, dither); } } return(errNum); }
/*! * \ingroup WlzValuesFilters * \brief Set new grey-range by simple linear interpolation. It assumes that the min and max values enclose the true range of grey-values in the object. Failure to check this could result in a segmentation fault. The transform function is: \f[g' = \frac{(gMax - gMin)}{(gmax - gmin)} (g - gmin) + gMin + \delta \f] Here \f$\delta\f$ is the dither value. * * \return Woolz error number * \param obj Input grey-level object whose values are to be reset. * \param min Initial minimum value * \param max Initial maximum value * \param Min Final minimum value * \param Max Final maximum value * \param Dither values if destination range is greater than source range * and this flag is non-zero. * \par Source: * WlzGreySetRange.c */ WlzErrorNum WlzGreySetRange( WlzObject *obj, WlzPixelV min, WlzPixelV max, WlzPixelV Min, WlzPixelV Max, int dither) { double gMin = 0.0, gMax = 0.0, sigma = 0.0, factor, val; WlzIntervalWSpace iwsp; WlzGreyWSpace gwsp; WlzGreyP gptr; WlzObject *tempobj; WlzValues *values; WlzDomain *domains; int i, j, nplanes; WlzErrorNum errNum = WLZ_ERR_NONE; /* check object */ if( obj == NULL ){ errNum = WLZ_ERR_OBJECT_NULL; } if( errNum == WLZ_ERR_NONE ){ switch( obj->type ){ case WLZ_2D_DOMAINOBJ: if( obj->domain.i == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->values.core == NULL ){ return WLZ_ERR_VALUES_NULL; } if( WlzGreyTableIsTiled(obj->values.core->type) ){ return WLZ_ERR_VALUES_TYPE; } break; case WLZ_3D_DOMAINOBJ: /* check planedomain and voxeltable */ if( obj->domain.p == NULL ){ return WLZ_ERR_DOMAIN_NULL; } if( obj->domain.p->type != WLZ_PLANEDOMAIN_DOMAIN ){ return WLZ_ERR_PLANEDOMAIN_TYPE; } if( obj->values.vox == NULL ){ return WLZ_ERR_VALUES_NULL; } if( obj->values.vox->type != WLZ_VOXELVALUETABLE_GREY ){ return WLZ_ERR_VOXELVALUES_TYPE; } /* set range of each plane if non-empty - indicated by NULL */ domains = obj->domain.p->domains; values = obj->values.vox->values; nplanes = obj->domain.p->lastpl - obj->domain.p->plane1 + 1; for(i=0; i < nplanes; i++, domains++, values++){ if( (*domains).core == NULL || (*values).core == NULL ){ continue; } tempobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *values, NULL, NULL, &errNum); if((tempobj == NULL) && (errNum == WLZ_ERR_NONE) ){ errNum = WLZ_ERR_UNSPECIFIED; break; } errNum = WlzGreySetRange(tempobj, min, max, Min, Max, dither); WlzFreeObj( tempobj ); if( errNum != WLZ_ERR_NONE ){ break; } } return errNum; case WLZ_TRANS_OBJ: return WlzGreySetRange(obj->values.obj, min, max, Min, Max, dither); case WLZ_EMPTY_OBJ: return errNum; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if( errNum == WLZ_ERR_NONE ){ /* get conversion function - should use LUT use 4 LUTS for rgb type since bounded */ if( WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA ){ WlzUByte rgbaLut[4][256]; WlzUInt rgbamin[4], rgbaMin[4]; double rgbaFactor[4], val1; WlzUInt red, green, blue, alpha; rgbamin[0] = WLZ_RGBA_RED_GET(min.v.rgbv); rgbaMin[0] = WLZ_RGBA_RED_GET(Min.v.rgbv); if(WLZ_RGBA_RED_GET(max.v.rgbv) > WLZ_RGBA_RED_GET(min.v.rgbv)){ rgbaFactor[0] = (((double) WLZ_RGBA_RED_GET(Max.v.rgbv) - WLZ_RGBA_RED_GET(Min.v.rgbv))/ (WLZ_RGBA_RED_GET(max.v.rgbv) - WLZ_RGBA_RED_GET(min.v.rgbv))); } else { rgbaFactor[0] = 0.0; } rgbamin[1] = WLZ_RGBA_GREEN_GET(min.v.rgbv); rgbaMin[1] = WLZ_RGBA_GREEN_GET(Min.v.rgbv); if(WLZ_RGBA_GREEN_GET(max.v.rgbv) > WLZ_RGBA_GREEN_GET(min.v.rgbv)){ rgbaFactor[1] = (((double) WLZ_RGBA_GREEN_GET(Max.v.rgbv) - WLZ_RGBA_GREEN_GET(Min.v.rgbv))/ (WLZ_RGBA_GREEN_GET(max.v.rgbv) - WLZ_RGBA_GREEN_GET(min.v.rgbv))); } else { rgbaFactor[1] = 0.0; } rgbamin[2] = WLZ_RGBA_BLUE_GET(min.v.rgbv); rgbaMin[2] = WLZ_RGBA_BLUE_GET(Min.v.rgbv); if(WLZ_RGBA_BLUE_GET(max.v.rgbv) > WLZ_RGBA_BLUE_GET(min.v.rgbv)){ rgbaFactor[2] = (((double) WLZ_RGBA_BLUE_GET(Max.v.rgbv) - WLZ_RGBA_BLUE_GET(Min.v.rgbv))/ (WLZ_RGBA_BLUE_GET(max.v.rgbv) - WLZ_RGBA_BLUE_GET(min.v.rgbv))); } else { rgbaFactor[2] = 0.0; } rgbamin[3] = WLZ_RGBA_ALPHA_GET(min.v.rgbv); rgbaMin[3] = WLZ_RGBA_ALPHA_GET(Min.v.rgbv); if(WLZ_RGBA_ALPHA_GET(max.v.rgbv) > WLZ_RGBA_ALPHA_GET(min.v.rgbv)){ rgbaFactor[3] = (((double) WLZ_RGBA_ALPHA_GET(Max.v.rgbv) - WLZ_RGBA_ALPHA_GET(Min.v.rgbv))/ (WLZ_RGBA_ALPHA_GET(max.v.rgbv) - WLZ_RGBA_ALPHA_GET(min.v.rgbv))); } else { rgbaFactor[3] = 0.0; } /* now set up the LUTS */ for(i=0; i < 4; i++){ for(j=0; j < 256; j++){ val1 = rgbaFactor[i] * (j - rgbamin[i]) + rgbaMin[i]; rgbaLut[i][j] = (WlzUByte )WLZ_CLAMP(val1, 0, 255); } } /* set values - can assume rgba grey-type */ errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { while( WlzNextGreyInterval(&iwsp) == WLZ_ERR_NONE ){ gptr = gwsp.u_grintptr; for (i=0; i<iwsp.colrmn; i++, gptr.rgbp++){ red = rgbaLut[0][WLZ_RGBA_RED_GET(*gptr.rgbp)]; green = rgbaLut[0][WLZ_RGBA_GREEN_GET(*gptr.rgbp)]; blue = rgbaLut[0][WLZ_RGBA_BLUE_GET(*gptr.rgbp)]; alpha = rgbaLut[0][WLZ_RGBA_ALPHA_GET(*gptr.rgbp)]; WLZ_RGBA_RGBA_SET(*gptr.rgbp, red, green, blue, alpha); } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } else { WlzValueConvertPixel(&min, min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&max, max, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Min, Min, WLZ_GREY_DOUBLE); WlzValueConvertPixel(&Max, Max, WLZ_GREY_DOUBLE); if( fabs(max.v.dbv - min.v.dbv) < DBL_EPSILON ){ return WLZ_ERR_FLOAT_DATA; } errNum = WlzInitGreyScan(obj, &iwsp, &gwsp); if(errNum == WLZ_ERR_NONE) { factor = (Max.v.dbv - Min.v.dbv) / (max.v.dbv - min.v.dbv); if(dither) { if(fabs(factor) < 1.0 + DBL_EPSILON) { dither = 0; } else { sigma = fabs(2.0 / factor); AlgRandSeed(101); switch(gwsp.pixeltype) { case WLZ_GREY_INT: gMin = ALG_MAX(Min.v.dbv, INT_MIN); gMax = ALG_MIN(Max.v.dbv, INT_MAX); break; case WLZ_GREY_SHORT: gMin = ALG_MAX(Min.v.dbv, SHRT_MIN); gMax = ALG_MIN(Max.v.dbv, SHRT_MAX); break; case WLZ_GREY_UBYTE: gMin = ALG_MAX(Min.v.dbv, 0); gMax = ALG_MIN(Max.v.dbv, 255); break; case WLZ_GREY_FLOAT: gMin = ALG_MAX(Min.v.dbv, FLT_MIN); gMax = ALG_MIN(Max.v.dbv, FLT_MAX); break; case WLZ_GREY_DOUBLE: gMin = Min.v.dbv; gMax = Max.v.dbv; break; default: break; } } } while((errNum == WLZ_ERR_NONE) && ((errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE)){ gptr = gwsp.u_grintptr; switch (gwsp.pixeltype) { case WLZ_GREY_INT: for (i=0; i<iwsp.colrmn; i++, gptr.inp++){ if(dither){ val = factor * (*gptr.inp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.inp - min.v.dbv) + Min.v.dbv; } *gptr.inp = WLZ_NINT(val); } break; case WLZ_GREY_SHORT: for (i=0; i<iwsp.colrmn; i++, gptr.shp++){ if(dither){ val = factor * (*gptr.shp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.shp - min.v.dbv) + Min.v.dbv; } *gptr.shp = (short )WLZ_NINT(val); } break; case WLZ_GREY_UBYTE: for (i=0; i<iwsp.colrmn; i++, gptr.ubp++){ if(dither){ val = factor * (*gptr.ubp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.ubp - min.v.dbv) + Min.v.dbv; } *gptr.ubp = (WlzUByte )WLZ_NINT(val); } break; case WLZ_GREY_FLOAT: for (i=0; i<iwsp.colrmn; i++, gptr.flp++){ if(dither){ val = factor * (*gptr.flp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.flp - min.v.dbv) + Min.v.dbv; } *gptr.flp = (float )val; } break; case WLZ_GREY_DOUBLE: for (i=0; i<iwsp.colrmn; i++, gptr.dbp++){ if(dither){ val = factor * (*gptr.dbp + AlgRandZigNormal(0.0, sigma) - min.v.dbv) + Min.v.dbv; val = WLZ_CLAMP(val, gMin, gMax); } else { val = factor * (*gptr.dbp - min.v.dbv) + Min.v.dbv; } *gptr.dbp = val; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } (void )WlzEndGreyScan(&iwsp, &gwsp); if(errNum == WLZ_ERR_EOO){ errNum = WLZ_ERR_NONE; } } } } return errNum; }
void install_paint_reference_object( WlzObject *obj) { Widget toggle; WlzPixelV bckgrnd; WlzPixelV min, max, Min, Max; WlzErrorNum errNum=WLZ_ERR_NONE; if( globals.orig_obj != NULL ){ WlzFreeObj( globals.orig_obj ); } globals.orig_obj = WlzAssignObject(obj, &errNum); obj = NULL; /* check input object for grey-value type convert if necessary */ if( errNum == WLZ_ERR_NONE ){ bckgrnd = WlzGetBackground(globals.orig_obj, &errNum); Min.type = WLZ_GREY_INT; Max.type = WLZ_GREY_INT; Min.v.inv = 0; Max.v.inv = 255; } if( errNum == WLZ_ERR_NONE ){ switch( bckgrnd.type ){ case WLZ_GREY_LONG: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.lnv < 0) || (max.v.lnv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_INT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.inv < 0) || (max.v.inv > 255) ){ obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum); WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } break; case WLZ_GREY_SHORT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.shv < 0) || (max.v.shv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_SHORT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_FLOAT: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.flv < 0) || (max.v.flv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; case WLZ_GREY_DOUBLE: WlzGreyRange(globals.orig_obj, &min, &max); if( (min.v.dbv < 0) || (max.v.dbv > 255) ){ if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){ WlzGreySetRange(obj, min, max, Min, Max, 0); bckgrnd = WlzGetBackground(obj, &errNum); } } break; default: case WLZ_GREY_UBYTE: break; } } /* copy for later transform for display purposes, the original is kept for IP purposes note pixconvert loses the background value */ if( errNum == WLZ_ERR_NONE ){ if( globals.obj != NULL ){ WlzFreeObj( globals.obj ); } if( obj ){ globals.obj = WlzAssignObject(WlzConvertPix(obj, WLZ_GREY_UBYTE, &errNum), NULL); WlzFreeObj(globals.orig_obj); globals.orig_obj = WlzAssignObject(obj, NULL); } else { globals.obj = WlzAssignObject(WlzConvertPix(globals.orig_obj, WLZ_GREY_UBYTE, &errNum), NULL); } } if( errNum == WLZ_ERR_NONE ){ min.type = WLZ_GREY_UBYTE; max.type = WLZ_GREY_UBYTE; Min.type = WLZ_GREY_UBYTE; Max.type = WLZ_GREY_UBYTE; min.v.ubv = 0; max.v.ubv = 255; Min.v.ubv = globals.cmapstruct->gmin; Max.v.ubv = globals.cmapstruct->gmax; errNum = WlzGreySetRange(globals.obj, min, max, Min, Max, 0); } /* also convert the background values */ if( errNum == WLZ_ERR_NONE ){ /* min = WlzGetBackground(globals.orig_obj, NULL);*/ WlzValueConvertPixel(&bckgrnd, bckgrnd, WLZ_GREY_INT); max.type = WLZ_GREY_INT; max.v.inv = ((bckgrnd.v.inv * (Max.v.ubv - Min.v.ubv)) / 255) + Min.v.ubv; WlzSetBackground(globals.obj, max); /* fill blank planes here - should be a resource option */ if( (toggle = XtNameToWidget(read_obj_dialog, "*.fill_blanks")) ){ Boolean fill_blanks, min_domain; XtVaGetValues(toggle, XmNset, &fill_blanks, NULL); if( fill_blanks ){ if( (toggle = XtNameToWidget(read_obj_dialog, "*.min_domain")) ){ XtVaGetValues(toggle, XmNset, &min_domain, NULL); if( min_domain ){ WlzFillBlankPlanes(globals.obj, 1); } else { WlzFillBlankPlanes(globals.obj, 0); } } else { WlzFillBlankPlanes(globals.obj, 1); } } } /* setup the display list and properties dialog */ setup_ref_display_list_cb(read_obj_dialog, NULL, NULL); setup_obj_props_cb(read_obj_dialog, NULL, NULL); } /* log the object size */ if( (errNum == WLZ_ERR_NONE) && globals.logfileFp ){ char strBuf[64]; sprintf(strBuf, "(%d, %d, %d, %d, %d, %d)", globals.obj->domain.p->kol1, globals.obj->domain.p->line1, globals.obj->domain.p->plane1, globals.obj->domain.p->lastkl, globals.obj->domain.p->lastln, globals.obj->domain.p->lastpl); MAPaintLogData("BoundingBox", strBuf, 0, NULL); sprintf(strBuf, "%d", (int) WlzVolume(globals.obj, NULL)); MAPaintLogData("Volume", strBuf, 0, NULL); } if( errNum != WLZ_ERR_NONE ){ MAPaintReportWlzError(globals.topl, "install_paint_reference_object", errNum); } return; }
int main(int argc, char **argv) { int idx, option, dither = 0, overwrite = 1, ok = 1, usage = 0; WlzImArNorm norm = WLZ_IMARNORM_NONE; WlzErrorNum errNum = WLZ_ERR_NONE; FILE *fP = NULL; WlzObject *outObj = NULL; WlzObject *inObj[2]; WlzBinaryOperatorType operator = WLZ_BO_ADD; char *outObjFileStr; char *inObjFileStr[2]; WlzPixelV gMin[3], gMax[3]; const char *errMsg; static char optList[] = "O:o:ab:dgilmsnNh", outObjFileStrDef[] = "-", inObjFileStrDef[] = "-"; opterr = 0; inObj[0] = NULL; inObj[1] = NULL; outObjFileStr = outObjFileStrDef; inObjFileStr[0] = inObjFileStrDef; inObjFileStr[1] = inObjFileStrDef; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'O': if((sscanf(optarg, "%d", &overwrite) != 1) || (overwrite < 0) || (overwrite > 2)) { usage = 1; ok = 0; } break; case 'o': outObjFileStr = optarg; break; case 'a': operator = WLZ_BO_ADD; break; case 'b': operator = atoi(optarg); switch( operator ){ case WLZ_BO_ADD: case WLZ_BO_SUBTRACT: case WLZ_BO_MULTIPLY: case WLZ_BO_DIVIDE: case WLZ_BO_MODULUS: case WLZ_BO_EQ: case WLZ_BO_NE: case WLZ_BO_GT: case WLZ_BO_GE: case WLZ_BO_LT: case WLZ_BO_LE: case WLZ_BO_AND: case WLZ_BO_OR: case WLZ_BO_XOR: case WLZ_BO_MAX: case WLZ_BO_MIN: case WLZ_BO_MAGNITUDE: break; default: usage = 1; ok = 0; break; } break; case 'd': operator = WLZ_BO_DIVIDE; break; case 'g': operator = WLZ_BO_MAGNITUDE; break; case 'l': operator = WLZ_BO_MODULUS; break; case 'm': operator = WLZ_BO_MULTIPLY; break; case 's': operator = WLZ_BO_SUBTRACT; break; case 'n': norm = WLZ_IMARNORM_INPUT; break; case 'N': norm = WLZ_IMARNORM_256; break; case 'i': dither = 1; break; case 'h': default: usage = 1; ok = 0; break; } } if((inObjFileStr[0] == NULL) || (*inObjFileStr[0] == '\0') || (inObjFileStr[1] == NULL) || (*inObjFileStr[1] == '\0') || (outObjFileStr == NULL) || (*outObjFileStr == '\0')) { ok = 0; usage = 1; } if(ok && (optind < argc)) { idx = 0; while((idx < 2) && (optind < argc)) { inObjFileStr[idx] = *(argv + optind); ++optind; ++idx; } } if(ok && (optind != argc)) { usage = 1; ok = 0; } if(ok) { idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < 2)) { errNum = WLZ_ERR_READ_EOF; if((inObjFileStr[idx] == NULL) || (*inObjFileStr[idx] == '\0') || ((fP = (strcmp(inObjFileStr[idx], "-")? fopen(inObjFileStr[idx], "r"): stdin)) == NULL) || ((inObj[idx]= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to read object %d from file %s (%s)\n", *argv, idx, inObjFileStr[idx], errMsg); } if(fP && strcmp(inObjFileStr[idx], "-")) { fclose(fP); } ++idx; } } if(ok) { idx = 0; while((errNum == WLZ_ERR_NONE) && (idx < 2)) { if((inObj[idx]->type != WLZ_2D_DOMAINOBJ) && (inObj[idx]->type != WLZ_3D_DOMAINOBJ)) { ok = 0; (void )fprintf(stderr, "%s: input object %d is not a domain object\n", *argv, idx); } ++idx; } } if(ok && (norm == WLZ_IMARNORM_INPUT)) { if(((errNum = WlzGreyRange(inObj[0], gMin, gMax)) != WLZ_ERR_NONE) || ((errNum = WlzGreyRange(inObj[1], gMin + 1, gMax + 1)) != WLZ_ERR_NONE)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to find input objects grey range (%s)\n", *argv, errMsg); } } if(ok) { if( WlzGreyTypeFromObj(inObj[0], &errNum) == WLZ_GREY_RGBA ){ if((outObj = WlzRGBAImageArithmetic(inObj[0], inObj[1], operator, 1, &errNum)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute new object (%s).\n", *argv, errMsg); } } else if((outObj = WlzImageArithmetic(inObj[0], inObj[1], operator, 0, &errNum)) == NULL) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute new object (%s).\n", *argv, errMsg); } } if(ok && (norm != WLZ_IMARNORM_NONE) && (WlzGreyTypeFromObj(inObj[0], &errNum) != WLZ_GREY_RGBA) ) { if((errNum = WlzGreyRange(outObj, gMin+ 2, gMax + 2)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to find output object's grey range (%s)\n", *argv, errMsg); } if(ok) { if(norm == WLZ_IMARNORM_256) { gMin[0].type = WLZ_GREY_UBYTE; gMin[0].v.ubv = 0; gMax[0].type = WLZ_GREY_UBYTE; gMax[0].v.ubv = 255; (void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type); (void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type); } else { (void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type); (void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type); (void )WlzValueConvertPixel(gMin + 1, gMin[1], gMin[2].type); (void )WlzValueConvertPixel(gMax + 1, gMax[1], gMax[2].type); switch(gMin[2].type) { case WLZ_GREY_INT: if(gMin[1].v.inv < gMin[0].v.inv) { gMin[0].v.inv = gMin[1].v.inv; } if(gMax[1].v.inv > gMax[0].v.inv) { gMax[0].v.inv = gMax[1].v.inv; } break; case WLZ_GREY_SHORT: if(gMin[1].v.shv < gMin[0].v.shv) { gMin[0].v.shv = gMin[1].v.shv; } if(gMax[1].v.shv > gMax[0].v.shv) { gMax[0].v.shv = gMax[1].v.shv; } break; case WLZ_GREY_UBYTE: if(gMin[1].v.ubv < gMin[0].v.ubv) { gMin[0].v.ubv = gMin[1].v.ubv; } if(gMax[1].v.ubv > gMax[0].v.ubv) { gMax[0].v.ubv = gMax[1].v.ubv; } break; case WLZ_GREY_FLOAT: if(gMin[1].v.flv < gMin[0].v.flv) { gMin[0].v.flv = gMin[1].v.flv; } if(gMax[1].v.flv > gMax[0].v.flv) { gMax[0].v.flv = gMax[1].v.flv; } break; case WLZ_GREY_DOUBLE: if(gMin[1].v.dbv < gMin[0].v.dbv) { gMin[0].v.dbv = gMin[1].v.dbv; } if(gMax[1].v.dbv > gMax[0].v.dbv) { gMax[0].v.dbv = gMax[1].v.dbv; } break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } } if((errNum = WlzGreySetRange(outObj, gMin[2], gMax[2], gMin[0], gMax[0], dither)) != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to set output object's grey range (%s)\n", *argv, errMsg); } } if(ok) { 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); } } WlzFreeObj(inObj[0]); WlzFreeObj(inObj[1]); WlzFreeObj(outObj); if(usage) { fprintf(stderr, "Usage: %s" " [-O#] [-o<out file>] [-a] [-b <op>] [-d] [-g] [-i] [-l] [-m] [-s] [-h] " "[<in object 0>] [<in object 1>]\n" "Options:\n" " -O Overwrite option (only useful for debugging)\n" " -o Output file name.\n" " -a Add the object's grey values.\n" " -b <op> Apply binary operation to the grey-values.\n" " op = %d - Add\n" " = %d - SUBTRACT\n" " = %d - MULTIPLY\n" " = %d - DIVIDE\n" " = %d - MODULUS\n" " = %d - EQ\n" " = %d - NE\n" " = %d - GT\n" " = %d - GE\n" " = %d - LT\n" " = %d - LE\n" " = %d - AND\n" " = %d - OR\n" " = %d - XOR\n" " = %d - MAX\n" " = %d - MIN\n" " = %d - MAGNITUDE\n" " -d Divide the grey values of the 1st object by those of the 2nd.\n" " -g Vector magnitude of horizontal and vertical component objects\n" " -i Dither values if setting range\n" " -l Compute the modulus of the grey values of the 1st object wrt\n" " those of the 2nd.\n" " -m Multiply the object's grey values.\n" " -s Subtract the grey values of the 2nd object from those of the 1st.\n" " -n Normalises the output object to the range of the input objects.\n" " -N Normalises the output objects to the range [0-255].\n" " -h Help, prints this usage message.\n" "Computes an arithmetic binary (two objects) operation on two domain\n" "objects. The default operator is add.\n" "The input objects are read from stdin and values are written to stdout\n" "unless the filenames are given.\n" "Example:\n%s%s%s", *argv, WLZ_BO_ADD, WLZ_BO_SUBTRACT, WLZ_BO_MULTIPLY, WLZ_BO_DIVIDE, WLZ_BO_MODULUS, WLZ_BO_EQ, WLZ_BO_NE, WLZ_BO_GT, WLZ_BO_GE, WLZ_BO_LT, WLZ_BO_LE, WLZ_BO_AND, WLZ_BO_OR, WLZ_BO_XOR, WLZ_BO_MAX, WLZ_BO_MIN, WLZ_BO_MAGNITUDE, "cat obj1.wlz | ", *argv, " -o obj3.wlz -a obj2.wlz\n" "A new object 'obj3.wlz is formed by adding the grey values of obj1 and\n" "obj2.wlz.\n"); } return(!ok); }
int main(int argc, char **argv) { WlzObject *obj; FILE *inFile; char optList[] = "l:L:u:U:dhv"; int dither = 0, option; WlzPixelV max, min, Max, Min; WlzPixelV gmin, gmax; int getminFlg=1, getmaxFlg=1, verboseFlg=0; WlzErrorNum errNum = WLZ_ERR_NONE; const char *errMsg; int objCount=0; /* read the argument list and check for an input file */ opterr = 0; Max.type = Min.type = max.type = min.type = WLZ_GREY_DOUBLE; Max.v.dbv = 255.0; Min.v.dbv = 0.0; while( (option = getopt(argc, argv, optList)) != EOF ){ switch( option ){ case 'd': dither = 1; break; case 'l': min.v.dbv = atof(optarg); getminFlg = 0; break; case 'L': Min.v.dbv = atof(optarg); break; case 'u': max.v.dbv = atof(optarg); getmaxFlg = 0; break; case 'U': Max.v.dbv = atof(optarg); break; case 'v': verboseFlg = 1; break; case 'h': default: usage(argv[0]); return 1; } } inFile = stdin; if( optind < argc ){ if( (inFile = fopen(*(argv+optind), "r")) == NULL ){ fprintf(stderr, "%s: can't open file %s\n", argv[0], *(argv+optind)); usage(argv[0]); return 1; } } /* read objects and threshold if possible */ while(((obj = WlzAssignObject(WlzReadObj(inFile, NULL), NULL)) != NULL) && (errNum == WLZ_ERR_NONE)) { objCount++; switch( obj->type ) { case WLZ_2D_DOMAINOBJ: case WLZ_3D_DOMAINOBJ: /* get the existing min and max grey values */ if( (errNum = WlzGreyRange(obj, &gmin, &gmax)) == WLZ_ERR_NONE ){ if( getminFlg ){ WlzValueConvertPixel(&min, gmin, WLZ_GREY_DOUBLE); } if( getmaxFlg ){ WlzValueConvertPixel(&max, gmax, WLZ_GREY_DOUBLE); } if( verboseFlg ){ fprintf(stderr, "%s:\nconverting object %d with parameters:\n" "\tSource (l, u) = (%f, %f)\n" "\tDestination (L, U) = (%f, %f)\n", argv[0], objCount, min.v.dbv, max.v.dbv, Min.v.dbv, Max.v.dbv); } errNum = WlzGreySetRange(obj, min, max, Min, Max, dither); if( errNum == WLZ_ERR_NONE ){ errNum = WlzWriteObj(stdout, obj); } } if( errNum != WLZ_ERR_NONE ){ (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write object (%s).\n", argv[0], errMsg); return(errNum); } break; default: if((errNum = WlzWriteObj(stdout, obj)) != WLZ_ERR_NONE) { (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to write object (%s).\n", argv[0], errMsg); return(1); } break; } WlzFreeObj(obj); } return 0; }
int main(int argc, char *argv[]) { int option, nReg = 0, tNReg = 0, ok = 1, usage = 0, verbose = 0, threshSet = 0, centreSet = 0; double minArea = 2; char *inExt, *dbgExt, *inDir, *dbgDir, *inFile, *dbgFile, *inPath = NULL, *dbgPath = NULL, *outFile = NULL; WlzRadDistVal distSort = WLZ_RADDISTVAL_AREA; WlzRadDistRec *distData = NULL; WlzPixelV thrVal; WlzDVertex2 centre; WlzCompThreshType thrMtd = WLZ_COMPTHRESH_OTSU; WlzThresholdType thrMod = WLZ_THRESH_HIGH; WlzEffFormat inFmt = WLZEFF_FORMAT_NONE, dbgFmt = WLZEFF_FORMAT_NONE; WlzObject *inObj = NULL, *disObj = NULL, *segObj = NULL; WlzGreyValueWSpace *disGVWSp = NULL; WlzObject **regObjs = NULL; FILE *fP = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; const int maxObj = 1000000; char pathBuf[FILENAME_MAX]; const double eps = 1.0e-06; const char *errMsg; static char optList[] = "hvAGDHELR:c:d:n:o:t:", defFile[] = "-"; thrVal.type = WLZ_GREY_DOUBLE; thrVal.v.dbv = 0.0; outFile = defFile; while((usage == 0) && ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'A': distSort = WLZ_RADDISTVAL_AREA; break; case 'D': distSort = WLZ_RADDISTVAL_DIST; break; case 'G': distSort = WLZ_RADDISTVAL_ANGLE; break; case 'H': thrMod = WLZ_THRESH_HIGH; break; case 'E': thrMod = WLZ_THRESH_EQUAL; break; case 'L': thrMod = WLZ_THRESH_LOW; break; case 'R': distSort = WLZ_RADDISTVAL_RADIUS; break; case 'h': usage = 1; break; case 'v': verbose = 1; break; case 'c': centreSet = 1; if(sscanf(optarg, "%lg,%lg", &(centre.vtX), &(centre.vtY)) != 2) { usage = 1; } break; case 'd': dbgPath = optarg; break; case 'o': outFile = optarg; break; case 'n': if(sscanf(optarg, "%lg", &minArea) != 1) { usage = 1; } break; case 't': threshSet = 1; if(sscanf(optarg, "%lg", &(thrVal.v.dbv)) != 1) { usage = 1; } break; default: usage = 1; break; } } ok = !usage; if(ok) { if((optind + 1) != argc) { usage = 1; ok = 0; } else { inPath = *(argv + optind); } } if(ok && verbose) { (void )fprintf(stderr, "inPath = %s\n", inPath); } /* Parse input file path into path + name + ext. */ if(ok) { ok = (usage = WlzRadDistParsePath(inPath, &inDir, &inFile, &inExt, &inFmt)) == 0; } if(ok && verbose) { (void )fprintf(stderr, "inDir = %s\n", inDir); (void )fprintf(stderr, "inFile = %s\n", inFile); (void )fprintf(stderr, "inExt = %s\n", (inExt)? inExt: "(null)"); (void )fprintf(stderr, "inFmt = %s\n", WlzEffStringFromFormat(inFmt, NULL)); } /* Read image. */ if(ok) { errNum = WLZ_ERR_READ_EOF; if(inExt) { (void )sprintf(pathBuf, "%s/%s.%s", inDir, inFile, inExt); } else { (void )sprintf(pathBuf, "%s/%s", inDir, inFile); } if(((inObj = WlzAssignObject(WlzEffReadObj(NULL, pathBuf, inFmt, 0, 0, 0, &errNum), NULL)) == NULL) || (inObj->type != WLZ_2D_DOMAINOBJ)) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: Failed to read 2D image object from file %s (%s)\n", *argv, pathBuf, errMsg); } } if(ok && verbose) { (void )fprintf(stderr, "read input image ok.\n"); } /* Convert to grey if needed, normalise 0 - 255 if needed and compute * threshold value unless already known. */ if(ok) { if(WlzGreyTypeFromObj(inObj, NULL) == WLZ_GREY_RGBA) { WlzObject *ppObj; ppObj = WlzAssignObject( WlzRGBAToModulus(inObj, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { (void )WlzFreeObj(inObj); inObj = ppObj; } } if(threshSet == 0) { WlzObject *hObj = NULL; errNum = WlzGreyNormalise(inObj, 1); if(errNum == WLZ_ERR_NONE) { hObj = WlzHistogramObj(inObj, 256, 0.0, 1.0, &errNum); } if(errNum == WLZ_ERR_NONE) { threshSet = 1; errNum = WlzCompThreshold(&thrVal.v.dbv, hObj, thrMtd, 0); } (void )WlzFreeObj(hObj); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to normalise object (%s)\n", *argv, errMsg); } } /* Segment the object. */ if(ok) { if(inObj->values.core == NULL) { segObj = WlzAssignObject(inObj, NULL); } else { segObj = WlzAssignObject( WlzThreshold(inObj, thrVal, thrMod, &errNum), NULL); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to segment image (%s)\n", *argv, errMsg); } } } /* Compute object with the same domain as the input object but in which * the values are the minimum distance from an edge. */ if(ok) { WlzObject *bObj = NULL; bObj = WlzBoundaryDomain(inObj, &errNum); if(errNum == WLZ_ERR_NONE) { disObj = WlzAssignObject( WlzDistanceTransform(inObj, bObj, WLZ_OCTAGONAL_DISTANCE, 0.0, 0.0, &errNum), NULL); } if(errNum == WLZ_ERR_NONE) { disGVWSp = WlzGreyValueMakeWSp(disObj, &errNum); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute distance object (%s)\n", *argv, errMsg); } (void )WlzFreeObj(bObj); } /* Output the debug image if required. */ if(ok && dbgPath) { WlzObject *dbgObj; dbgObj = WlzAssignObject(WlzCopyObject(inObj, &errNum), NULL); if(errNum == WLZ_ERR_NONE) { WlzPixelV iMin, iMax, oMin, oMax; if(dbgObj->values.core == NULL) { WlzValues tmpVal; oMax.type = WLZ_GREY_UBYTE; oMax.v.ubv = 255; tmpVal.v = WlzNewValueTb(dbgObj, WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_UBYTE, NULL), oMax, &errNum); if(errNum == WLZ_ERR_NONE) { dbgObj->values = WlzAssignValues(tmpVal, NULL); } } else { WlzObject *tmpObj = NULL; oMin.type = WLZ_GREY_UBYTE; oMin.v.ubv = 0; oMax.type = WLZ_GREY_UBYTE; oMax.v.ubv = 200; errNum = WlzGreyRange(dbgObj, &iMin, &iMax); if(errNum == WLZ_ERR_NONE) { errNum = WlzGreySetRange(dbgObj, iMin, iMax, oMin, oMax, 0); } if(errNum == WLZ_ERR_NONE) { tmpObj = WlzMakeMain(inObj->type, segObj->domain, dbgObj->values, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { oMax.v.ubv = 255; errNum = WlzGreySetValue(tmpObj, oMax); } (void )WlzFreeObj(tmpObj); if(errNum == WLZ_ERR_NONE) { tmpObj = WlzConvertPix(dbgObj, WLZ_GREY_UBYTE, &errNum); (void )WlzFreeObj(dbgObj); dbgObj = WlzAssignObject(tmpObj, NULL); } } } if(errNum == WLZ_ERR_NONE) { (void )WlzRadDistParsePath(dbgPath, &dbgDir, &dbgFile, &dbgExt, &dbgFmt); if(dbgExt) { (void )sprintf(pathBuf, "%s/%s.%s", dbgDir, dbgFile, dbgExt); } else { (void )sprintf(pathBuf, "%s/%s", dbgDir, dbgFile); } errNum = WlzEffWriteObj(NULL, pathBuf, dbgObj, dbgFmt); } (void )WlzFreeObj(dbgObj); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to output the debug image (%s)\n", *argv, errMsg); } } /* Label the segmented object. */ if(ok) { errNum = WlzLabel(segObj, &nReg, ®Objs, maxObj, 0, WLZ_8_CONNECTED); if(errNum != WLZ_ERR_NONE) { ok = 0; errNum = WLZ_ERR_MEM_ALLOC; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to split into components (%s)\n", *argv, errMsg); } if(ok && verbose) { (void )fprintf(stderr, "nReg = %d\n", nReg); } } /* Compute centre of mass if not known. */ if(ok) { if(centreSet == 0) { centre = WlzCentreOfMass2D(inObj, 1, NULL, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute centre of mass (%s)\n", *argv, errMsg); } } if(ok && verbose) { (void )fprintf(stderr, "centre = %lg,%lg\n", centre.vtX, centre.vtY); } } /* Allocate a radial distribution table. */ if(ok) { if((distData = (WlzRadDistRec *) AlcCalloc(nReg, sizeof(WlzRadDistRec))) == NULL) { ok = 0; errNum = WLZ_ERR_MEM_ALLOC; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to allocate result lable (%s)\n", *argv, errMsg); } } /* Compute the redial distribution data. */ if(ok) { int idR = 0, idS = 0; while((errNum == WLZ_ERR_NONE) && (idR < nReg)) { double mass; WlzDVertex2 com; com = WlzCentreOfMass2D(regObjs[idR], 1, &mass, NULL); if(mass > minArea - eps) { WlzGreyValueGet(disGVWSp, 0.0, com.vtY, com.vtX); distData[idS].pos = com; distData[idS].area = mass; WLZ_VTX_2_SUB(com, centre, com); distData[idS].radius = WLZ_VTX_2_LENGTH(com); distData[idS].angle = ALG_M_PI + atan2(com.vtY, com.vtX); switch(disGVWSp->gType) { case WLZ_GREY_LONG: distData[idS].dist = *(disGVWSp->gPtr[0].lnp); break; case WLZ_GREY_INT: distData[idS].dist = *(disGVWSp->gPtr[0].inp); break; case WLZ_GREY_SHORT: distData[idS].dist = *(disGVWSp->gPtr[0].shp); break; case WLZ_GREY_UBYTE: distData[idS].dist = *(disGVWSp->gPtr[0].ubp); break; case WLZ_GREY_FLOAT: distData[idS].dist = *(disGVWSp->gPtr[0].flp); break; case WLZ_GREY_DOUBLE: distData[idS].dist = *(disGVWSp->gPtr[0].dbp); break; default: distData[idS].dist = 0.0; break; } ++idS; } ++idR; } tNReg = idS; switch(distSort) { case WLZ_RADDISTVAL_AREA: (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), WlzRadDistRecSortArea); break; case WLZ_RADDISTVAL_ANGLE: (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), WlzRadDistRecSortAngle); break; case WLZ_RADDISTVAL_RADIUS: (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), WlzRadDistRecSortRadius); break; case WLZ_RADDISTVAL_DIST: (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), WlzRadDistRecSortDist); break; } } /* Output the sorted radial distribution table. */ if(ok) { if(((fP = strcmp(outFile, "-")? fopen(outFile, "w"): stdout)) == NULL) { ok = 0; (void )fprintf(stderr, "%s: failed to open output file %s\n", *argv, outFile); } } if(ok) { int idR; for(idR = 0; idR < tNReg; ++idR) { double a; a = (distData[idR].angle > 0.0)? 0 + (180 * distData[idR].angle / ALG_M_PI): 360 + (180 * distData[idR].angle / ALG_M_PI); (void )fprintf(fP, "%g %g %g %g,%g %g\n", a, distData[idR].radius, distData[idR].area, distData[idR].pos.vtX, distData[idR].pos.vtY, distData[idR].dist); } } if(strcmp(outFile, "-")) { (void )fclose(fP); } /* Tidy up. */ AlcFree(distData); WlzGreyValueFreeWSp(disGVWSp); (void )WlzFreeObj(inObj); (void )WlzFreeObj(disObj); (void )WlzFreeObj(segObj); if(regObjs) { int idR; for(idR = 0; idR < nReg; ++idR) { (void )WlzFreeObj(regObjs[idR]); } AlcFree(regObjs); } if(usage) { (void )fprintf(stderr, "Usage: %s [-h] [-v] [-A] [-D] [-G] [-H] [-E] [-L] [-R]\n" "\t\t[-c #,#] [-d <debug image>] [-n #] [-o <out file>]\n" "\t\t[-t #] [<input image>]\n" "Segments the given object using a threshold value and outputs the \n" "radial distribution of the thresholded components.\n" "Version: %s\n" "Options:\n" " -h Help - prints this usage masseage.\n" " -v Verbose output.\n" " -A Sort output by area (default).\n" " -D Sort output by distance from boundary.\n" " -G Sort output by angle.\n" " -H Threshold high, use pixels at or above threshold (default).\n" " -E Threshold equal, use pixels at threshold.\n" " -L Threshold low, use pixels below threshold.\n" " -R Sort output by radial distance from centre.\n" " -c Centre (default is image centre).\n" " -d Debug image.\n" " -n Minimum area (default %g).\n" " -t Threshold value (default is to compute using Otsu's method).\n" "By default the input image object is read from the standard input and\n" "the radial distribution is written to the standard output.\n" "The image formats understood include wlz, jpg and tif.\n" "The output format is:\n" " <angle> <dist from centre> <area> <x pos>,<y pos> <dist form boundary>\n" "Example:\n" " %s -o out.txt -d debug.jpg in.tif\n" "The input image is read from in.tif, a debug image showing the\n" "segmented regions is written to debug.jpg and the radial distribution\n" "statistics are written to the file out.txt. With the output in\n" "out.txt, the following R code would plot the data as a set of circles\n" "with radius proportional to the square root of the component area:\n" " data <- read.table(\"out.txt\")\n" " attach(data)\n" " symbols(x=data$V1, y=data$V2, circles=sqrt(data$V3))\n", argv[0], WlzVersion(), minArea, argv[0]); } return(!ok); }