/*! * \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 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 Object area or -1 on error. * \ingroup WlzFeatures * \brief Calculates simple quick statistics for the domain * object with RGBA values. Each component has its * statictics computed and entered into the four * double[4] arrays. * \param srcObj Given object. * \param colSpc Colour space. * \param dstGType Pointer for grey type. * \param dstMin Array for the 4 minimum value. * \param dstMax Array for the 4 maximum value. * \param dstSum Array for the 4 sum of values. * \param dstSumSq Array for the 4 sum of squares of * values. * \param dstMean Array for the 4 mean values. * \param dstStdDev Array for the 4 standard deviation * values. * \param dstErr Destination pointer for error, may * be NULL. */ int WlzRGBAGreyStats( WlzObject *srcObj, WlzRGBAColorSpace colSpc, WlzGreyType *dstGType, double *dstMin, double *dstMax, double *dstSum, double *dstSumSq, double *dstMean, double *dstStdDev, WlzErrorNum *dstErr) { int area; WlzCompoundArray *cmpnd; int i; WlzGreyType gType; WlzErrorNum errNum=WLZ_ERR_NONE; /* all object checks done bt RGBAToCOmpound including grey-level type */ if((cmpnd = WlzRGBAToCompound(srcObj, colSpc, &errNum)) != NULL){ *dstGType = WLZ_GREY_RGBA; for(i=0; (i < 4) && (errNum == WLZ_ERR_NONE) ; i++){ area = WlzGreyStats(cmpnd->o[i], &gType, dstMin + i, dstMax + i, dstSum + i, dstSumSq + i, dstMean + i, dstStdDev + i, &errNum); } WlzFreeObj((WlzObject *) cmpnd); } if( dstErr ){ *dstErr = errNum; } return area; }
/*! * \return Translation. * \ingroup WlzRegistration * \brief Registers the given 2D domain objects using a * frequency domain cross correlation, to find * the translation which has the highest cross * correlation value. * \param tObj The target object. Must have * been assigned. * \param sObj The source object to be * registered with target object. * Must have been assigned. * \param initTr Initial affine transform * to be applied to the source * object prior to registration. * \param maxTran Maximum translation. * \param maxTran Maximum translation. * \param winFn Window function. * \param noise Use Gaussian noise if non-zero. * \param dstCCor Destination ptr for the cross * correlation value, may be NULL. * \param dstErr Destination error pointer, * may be NULL. */ static WlzDVertex2 WlzRegCCorObjs2DTran(WlzObject *tObj, WlzObject *sObj, WlzAffineTransform *initTr, WlzDVertex2 maxTran, WlzWindowFnType winFn, int noise, double *dstCCor, WlzErrorNum *dstErr) { int oIdx; double cCor = 0.0; double sSq[2]; double **oAr[2]; WlzIBox2 aBox; WlzIBox2 oBox[2], pBox[2]; WlzIVertex2 aSz, aOrg, centre, radius, tran; WlzDVertex2 dstTran; WlzObject *oObj[2], *pObj[2]; WlzErrorNum errNum = WLZ_ERR_NONE; dstTran.vtX = 0.0; dstTran.vtY = 0.0; oAr[0] = oAr[1] = NULL; oObj[0] = oObj[1] = NULL; pObj[0] = pObj[1] = NULL; oObj[0] = WlzAssignObject(tObj, NULL); /* Transform source object. */ if((initTr == NULL) || WlzAffineTransformIsIdentity(initTr, NULL)) { oObj[1] = WlzAssignObject(sObj, NULL); } else { oObj[1] = WlzAssignObject( WlzAffineTransformObj(sObj, initTr, WLZ_INTERPOLATION_NEAREST, &errNum), NULL); } /* Preprocess the objects. */ if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { oBox[oIdx] = WlzBoundingBox2I(oObj[oIdx], &errNum); ++oIdx; } } if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { centre.vtX = (oBox[oIdx].xMin + oBox[oIdx].xMax) / 2; centre.vtY = (oBox[oIdx].yMin + oBox[oIdx].yMax) / 2; radius.vtX = (oBox[oIdx].xMax - oBox[oIdx].xMin) / 2; radius.vtY = (oBox[oIdx].yMax - oBox[oIdx].yMin) / 2; pObj[oIdx] = WlzAssignObject( WlzRegCCorPProcessObj2D(oObj[oIdx], winFn, centre, radius, &errNum), NULL); ++oIdx; } } /* Create double arrays. */ if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { pBox[oIdx] = WlzBoundingBox2I(pObj[oIdx], &errNum); ++oIdx; } } if(errNum == WLZ_ERR_NONE) { aBox.xMin = WLZ_MIN(pBox[0].xMin, pBox[1].xMin) - (int )(maxTran.vtX) + 1; aBox.yMin = WLZ_MIN(pBox[0].yMin, pBox[1].yMin) - (int )(maxTran.vtY) + 1; aBox.xMax = WLZ_MAX(pBox[0].xMax, pBox[1].xMax) + (int )(maxTran.vtX) + 1; aBox.yMax = WLZ_MAX(pBox[0].yMax, pBox[1].yMax) + (int )(maxTran.vtY) + 1; aOrg.vtX = aBox.xMin; aOrg.vtY = aBox.yMin; aSz.vtX = aBox.xMax - aBox.xMin + 1; aSz.vtY = aBox.yMax - aBox.yMin + 1; (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtX), aSz.vtX); (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtY), aSz.vtY); oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { errNum = WlzToArray2D((void ***)&(oAr[oIdx]), pObj[oIdx], aSz, aOrg, noise, WLZ_GREY_DOUBLE); ++oIdx; } } if((dstCCor != NULL) && (errNum == WLZ_ERR_NONE)) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { WlzArrayStats2D((void **)(oAr[oIdx]), aSz, WLZ_GREY_DOUBLE, NULL, NULL, NULL, &(sSq[oIdx]), NULL, NULL); ++oIdx; } } #ifdef WLZ_REGCCOR_DEBUG if(errNum == WLZ_ERR_NONE) { FILE *fP = NULL; WlzObject *cCObjT = NULL; cCObjT = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0, 0, 0, &errNum); if(cCObjT) { if((fP = fopen("oObjT0.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, cCObjT); (void )fclose(fP); } (void )WlzFreeObj(cCObjT); } } if(errNum == WLZ_ERR_NONE) { FILE *fP = NULL; WlzObject *cCObjT = NULL; cCObjT = WlzFromArray2D((void **)(oAr[1]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0, 0, 0, &errNum); if(cCObjT) { if((fP = fopen("oObjT1.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, cCObjT); (void )fclose(fP); } (void )WlzFreeObj(cCObjT); } } #endif /* WLZ_REGCCOR_DEBUG */ /* Cross correlate. */ if(errNum == WLZ_ERR_NONE) { (void )AlgCrossCorrelate2D(oAr[0], oAr[1], aSz.vtX, aSz.vtY); AlgCrossCorrPeakXY(&(tran.vtX), &(tran.vtY), &cCor, oAr[0], aSz.vtX, aSz.vtY, maxTran.vtX, maxTran.vtY); } #ifdef WLZ_REGCCOR_DEBUG if(errNum == WLZ_ERR_NONE) { FILE *fP = NULL; WlzObject *cCObjT = NULL; oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { (void )WlzGreyStats(pObj[oIdx], NULL, NULL, NULL, NULL, &(sSq[oIdx]), NULL, NULL, &errNum); ++oIdx; } if(errNum == WLZ_ERR_NONE) { cCObjT = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 255.0 / (1.0 + (sqrt(sSq[0] * sSq[1]) * aSz.vtX * aSz.vtY)), 0, 0, &errNum); } if(cCObjT) { if((fP = fopen("cCObjT.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, cCObjT); (void )fclose(fP); } (void )WlzFreeObj(cCObjT); } } #endif /* WLZ_REGCCOR_DEBUG */ for(oIdx = 0; oIdx < 2; ++oIdx) { (void )WlzFreeObj(oObj[oIdx]); (void )WlzFreeObj(pObj[oIdx]); AlcDouble2Free(oAr[oIdx]); } if(errNum == WLZ_ERR_NONE) { dstTran.vtX = tran.vtX; dstTran.vtY = tran.vtY; if(dstCCor) { cCor = cCor / (1.0 + (sqrt(sSq[0] * sSq[1]) * aSz.vtX * aSz.vtY)); *dstCCor = cCor; } } if(dstErr) { *dstErr = errNum; } return(dstTran); }
/*! * \return Angle of roatation. * \ingroup WlzRegistration * \brief Polar samples then registers the given 2D domain objects * using a frequency domain cross correlation, to find * the angle of rotation about the given centre of rotation * which has the highest cross correlation value. * The rotation is always about the objects cente of mass. * \param tObj The target object. Must have * been assigned. * \param sObj The source object to be * registered with target object. * Must have been assigned. * \param initTr Initial affine transform * to be applied to the source * object prior to registration. * \param maxRot Maximum rotation. * \param winFn Window function. * \param noise Use Gaussian noise if non-zero. * \param dstErr Destination error pointer, * may be NULL. */ static double WlzRegCCorObjs2DRot(WlzObject *tObj, WlzObject *sObj, WlzAffineTransform *initTr, double maxRot, WlzWindowFnType winFn, int noise, WlzErrorNum *dstErr) { int oIdx, angCnt; double angInc, dstRot = 0.0; WlzIBox2 aBox; WlzIBox2 oBox[2]; WlzIVertex2 rot, aSz, aOrg, winRad, winOrg, rotPad, rotCentreI; double **oAr[2]; WlzObject *oObj[2], *pObj[2], *wObj[2]; WlzErrorNum errNum = WLZ_ERR_NONE; const int rotCnt = 500; const double distInc = 1.0; /* Assign the target and transform source objects. */ oAr[0] = oAr[1] = NULL; oAr[0] = oAr[1] = NULL; oObj[0] = oObj[1] = NULL; pObj[0] = pObj[1] = NULL; wObj[0] = wObj[1] = NULL; oObj[0] = WlzAssignObject(tObj, NULL); if((initTr == NULL) || WlzAffineTransformIsIdentity(initTr, NULL)) { oObj[1] = WlzAssignObject(sObj, NULL); } else { oObj[1] = WlzAssignObject( WlzAffineTransformObj(sObj, initTr, WLZ_INTERPOLATION_NEAREST, &errNum), NULL); } if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { tObj = WlzAutoCor(oObj[oIdx], &errNum); (void )WlzFreeObj(oObj[oIdx]); oObj[oIdx] = WlzAssignObject(tObj, NULL); ++oIdx; } } /* Compute rectangular to polar transformation. */ if(errNum == WLZ_ERR_NONE) { angInc = (2.0 * (maxRot + WLZ_M_PI)) / rotCnt; angCnt = (2.0 * WLZ_M_PI) / angInc; oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { rotCentreI.vtX = 0; rotCentreI.vtY = 0; if(errNum == WLZ_ERR_NONE) { pObj[oIdx] = WlzAssignObject( WlzPolarSample(oObj[oIdx], rotCentreI, angInc, distInc, angCnt, 0, &errNum), NULL); } ++oIdx; } } /* Preproccess the objects using windows or noise. */ if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { oBox[oIdx] = WlzBoundingBox2I(pObj[oIdx], &errNum); if(errNum == WLZ_ERR_NONE) { winOrg.vtX = (oBox[oIdx].xMax + oBox[oIdx].xMin) / 2; winOrg.vtY = (oBox[oIdx].yMax + oBox[oIdx].yMin) / 2; winRad.vtX = (oBox[oIdx].xMax - oBox[oIdx].xMin) / 2; winRad.vtY = (oBox[oIdx].yMax - oBox[oIdx].yMin) / 2; wObj[oIdx] = WlzAssignObject( WlzRegCCorPProcessObj2D(pObj[oIdx], winFn, winOrg, winRad, &errNum), NULL); } ++oIdx; } } /* Create 2D double arrays from the polar sampled objects. */ if(errNum == WLZ_ERR_NONE) { oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { oBox[oIdx] = WlzBoundingBox2I(wObj[oIdx], &errNum); ++oIdx; } } if(errNum == WLZ_ERR_NONE) { aBox.xMin = WLZ_MIN(oBox[0].xMin, oBox[1].xMin); aBox.yMin = WLZ_MIN(oBox[0].yMin, oBox[1].yMin); aBox.xMax = WLZ_MAX(oBox[0].xMax, oBox[1].xMax); aBox.yMax = WLZ_MAX(oBox[0].yMax, oBox[1].yMax); rotPad.vtX = (aBox.xMax - aBox.xMin) / 2; rotPad.vtY = 1 + WLZ_NINT(maxRot / angInc); aBox.yMin -= rotPad.vtY; aBox.yMax += rotPad.vtY; aOrg.vtX = aBox.xMin; aOrg.vtY = aBox.yMin; aSz.vtX = aBox.xMax - aBox.xMin + 1; aSz.vtY = aBox.yMax - aBox.yMin + 1; (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtX), aSz.vtX); (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtY), aSz.vtY); oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { errNum = WlzToArray2D((void ***)&(oAr[oIdx]), wObj[oIdx], aSz, aOrg, noise, WLZ_GREY_DOUBLE); ++oIdx; } } #ifdef WLZ_REGCCOR_DEBUG if(errNum == WLZ_ERR_NONE) { FILE *fP = NULL; WlzObject *aObj = NULL; aObj = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0, 0, 0, &errNum); if((fP = fopen("cObjR0.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, aObj); (void )fclose(fP); } WlzFreeObj(aObj); aObj = WlzFromArray2D((void **)(oAr[1]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0, 0, 0, &errNum); if((fP = fopen("cObjR1.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, aObj); (void )fclose(fP); } WlzFreeObj(aObj); } #endif /* WLZ_REGCCOR_DEBUG */ /* Cross correlate. */ if(errNum == WLZ_ERR_NONE) { (void )AlgCrossCorrelate2D(oAr[0], oAr[1], aSz.vtX, aSz.vtY); AlgCrossCorrPeakXY(&(rot.vtX), &(rot.vtY), NULL, oAr[0], aSz.vtX, aSz.vtY, rotPad.vtX, rotPad.vtY); dstRot = rot.vtY * angInc; /* dstRot = -(rot.vtY) * angInc; */ } #ifdef WLZ_REGCCOR_DEBUG if(errNum == WLZ_ERR_NONE) { double sSq[2]; FILE *fP = NULL; WlzObject *cCObjR = NULL; oIdx = 0; while((errNum == WLZ_ERR_NONE) && (oIdx < 2)) { (void )WlzGreyStats(wObj[oIdx], NULL, NULL, NULL, NULL, &(sSq[oIdx]), NULL, NULL, &errNum); ++oIdx; } if(errNum == WLZ_ERR_NONE) { cCObjR = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg, WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 255.0 / (1.0 + (sqrt(sSq[0] * sSq[1]) * aSz.vtX * aSz.vtY)), 0, 0, &errNum); } if(cCObjR) { if((fP = fopen("cCObjR.wlz", "w")) != NULL) { (void )WlzWriteObj(fP, cCObjR); (void )fclose(fP); } (void )WlzFreeObj(cCObjR); } } #endif /* WLZ_REGCCOR_DEBUG */ for(oIdx = 0; oIdx < 2; ++oIdx) { (void )WlzFreeObj(oObj[oIdx]); (void )WlzFreeObj(pObj[oIdx]); (void )WlzFreeObj(wObj[oIdx]); AlcDouble2Free(oAr[oIdx]); } if(dstErr) { *dstErr = errNum; } return(dstRot); }
int main( int argc, char **argv) { FILE *inFileObj=NULL, *inFileTiles=NULL; char optList[] = "f:hv"; int option; WlzErrorNum errNum=WLZ_ERR_NONE; int verboseFlg=0; int func=1; WlzObject *imageObj = NULL, *tilesObj=NULL, *obj; WlzCompoundArray *tilesCompObj; double tileVal=0.0; int i; WlzPixelV tmplVal; WlzGreyType dstGType; double dstMin, dstMax, dstSum, dstSumSq, dstMean, dstStdDev; /* read the argument list and check for an input file */ opterr = 0; while( (option = getopt(argc, argv, optList)) != EOF ){ switch( option ){ case 'f': func = atoi(optarg); switch (func){ default: fprintf(stderr, "%s: invalid tile function option %d, reset to 1\n", argv[0], func); func = 1; break; case 1: /* average */ break; } case 'v': verboseFlg = 1; break; case 'h': default: usage(argv[0]); return 1; } } /* must have image and tile file */ /* check input file/stream */ if( (argc - optind) < 2 ){ fprintf(stderr, "%s: not enough arguments\n", argv[0]); usage(argv[0]); return 1; } else { if( (inFileObj = fopen(*(argv+optind), "rb")) == NULL ){ fprintf(stderr, "%s: can't open image object file %s\n", argv[0], *(argv+optind)); usage(argv[0]); return 1; } if( (inFileTiles = fopen(*(argv+optind+1), "rb")) == NULL ){ fprintf(stderr, "%s: can't open tiles file %s\n", argv[0], *(argv+optind+1)); usage(argv[0]); return 1; } } /* verbose output */ if( verboseFlg ){ fprintf(stderr, "%s: tile function value value: %d\n", argv[0], func); fprintf(stderr, "%s: image object file: %s\n", argv[0], *(argv+optind)); fprintf(stderr, "%s: tiles object file: %s\n", argv[0], *(argv+optind+1)); } /* get woolz objects */ if((imageObj = WlzReadObj(inFileObj, &errNum)) == NULL){ fprintf(stderr, "%s: can't read image object\n", argv[0]); usage(argv[0]); return 1; } imageObj = WlzAssignObject(imageObj, NULL); if((tilesObj = WlzReadObj(inFileTiles, &errNum)) == NULL){ fprintf(stderr, "%s: can't read tiles object\n", argv[0]); usage(argv[0]); return 1; } tilesObj = WlzAssignObject(tilesObj, NULL); tilesCompObj = (WlzCompoundArray *) tilesObj; /* now calculate the tile values */ switch( tilesObj->type ){ case WLZ_COMPOUND_ARR_1: case WLZ_COMPOUND_ARR_2: tmplVal.type = WLZ_GREY_UBYTE; tmplVal.v.ubv = 0; for(i=0; i < tilesCompObj->n; i++){ switch( func ){ case 1: /* average */ /* get tile object with values */ if( (obj = WlzGreyTemplate(imageObj, tilesCompObj->o[i], tmplVal, &errNum)) != NULL ){ WlzGreyStats(obj, &dstGType, &dstMin, &dstMax, &dstSum, &dstSumSq, &dstMean, &dstStdDev, &errNum); tileVal = dstMean; } else { fprintf(stderr, "%s: error in tile template\n", argv[0]); tileVal = -1.0; } break; default: break; } if( i > 0 ){ fprintf(stdout, ", %8.3f", tileVal); } else{ fprintf(stdout, "%8.3f", tileVal); } } break; default: fprintf(stderr, "%s: invalid tiles object type - must be compound array\n", argv[0]); return 1; } return 0; }
int main(int argc, char **argv) { int area, option, ok = 1, verbose = 0, colFlg = 0, usage = 0; WlzErrorNum errNum = WLZ_ERR_NONE; FILE *fP = NULL; WlzObject *inObj = NULL; double min, max, sum, sumSq, mean, stdDev; double minA[4], maxA[4], sumA[4], sumSqA[4], meanA[4], stdDevA[4]; WlzGreyType gType; char *outFileStr, *inObjFileStr; const char *errMsg; static char optList[] = "co:vh", outFileStrDef[] = "-", inObjFileStrDef[] = "-"; opterr = 0; outFileStr = outFileStrDef; inObjFileStr = inObjFileStrDef; while(ok && ((option = getopt(argc, argv, optList)) != -1)) { switch(option) { case 'c': colFlg = 1; break; case 'o': outFileStr = optarg; break; case 'v': verbose = 1; break; case 'h': default: usage = 1; ok = 0; break; } } if((inObjFileStr == NULL) || (*inObjFileStr == '\0') || (outFileStr == NULL) || (*outFileStr == '\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= WlzReadObj(fP, &errNum)) == 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(colFlg) { area = WlzRGBAGreyStats(inObj, WLZ_RGBA_SPACE_RGB, &gType, minA, maxA, sumA, sumSqA, meanA, stdDevA, &errNum); } else { area = WlzGreyStats(inObj, &gType, &min, &max, &sum, &sumSq, &mean, &stdDev, &errNum); } if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsg); (void )fprintf(stderr, "%s: failed to compute object's grey value statistics" " (%s)\n", *argv, errMsg); } } if(ok) { if(((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL)) { ok = 0; (void )fprintf(stderr, "%s: failed to write output file\n", *argv); } else { if( colFlg ){ if(verbose) { (void )fprintf(fP, "area %d\n" "grey type %s\n" "min (%lg, %lg, %lg, %lg)\n" "max (%lg, %lg, %lg, %lg)\n" "sum (%lg, %lg, %lg, %lg)\n" "sum sq (%lg, %lg, %lg, %lg)\n" "mean (%lg, %lg, %lg, %lg)\n" "std dev (%lg, %lg, %lg, %lg)\n", area, WlzStringFromGreyType(gType, NULL), minA[0], minA[1], minA[2], minA[3], maxA[0], maxA[1], maxA[2], maxA[3], sumA[0], sumA[1], sumA[2], sumA[3], sumSqA[0], sumSqA[1], sumSqA[2], sumSqA[3], meanA[0], meanA[1], meanA[2], meanA[3], stdDevA[0], stdDevA[1], stdDevA[2], stdDevA[3]); } else { (void )fprintf(fP, "%d %s (%lg,%lg,%lg,%lg) (%lg %lg %lg %lg)\n" "(%lg,%lg,%lg,%lg) (%lg %lg %lg %lg)\n" "(%lg,%lg,%lg,%lg) (%lg %lg %lg %lg)\n", area, WlzStringFromGreyType(gType, NULL), minA[0], minA[1], minA[2], minA[3], maxA[0], maxA[1], maxA[2], maxA[3], sumA[0], sumA[1], sumA[2], sumA[3], sumSqA[0], sumSqA[1], sumSqA[2], sumSqA[3], meanA[0], meanA[1], meanA[2], meanA[3], stdDevA[0], stdDevA[1], stdDevA[2], stdDevA[3]); } } else { if(verbose) { (void )fprintf(fP, "area % 14d\n" "grey type %14s\n" "min % 14g\n" "max % 14g\n" "sum % 14g\n" "sum sq % 14g\n" "mean % 14g\n" "std dev % 14g\n", area, WlzStringFromGreyType(gType, NULL), min, max, sum, sumSq, mean, stdDev); } else { (void )fprintf(fP, "%d %s %lg %lg %lg %lg %lg %lg\n", area, WlzStringFromGreyType(gType, NULL), min, max, sum, sumSq, mean, stdDev); } } } if(fP && strcmp(outFileStr, "-")) { fclose(fP); } } if(usage) { (void )fprintf(stderr, "Usage: %s%sExample: %s%s", *argv, " [-o<out file>] [-c] [-v] [-h] [<in object>]\n" "Options:\n" " -c Colour stats if RGB, otherwise modulus stats calculated\n" " -o Output file name.\n" " -v Verbose output flag.\n" " -h Help, prints this usage message.\n" "Calculates the area, minimum, maximum, sum, sum of squares, mean\n" "and the standard deviation of the input 2D or 3D Woolz object's\n" "grey values.\n" "If the verbose output flag is not set then the following are written\n" "to the output file in the following order:\n" " <area> <grey type> <min> <max> <sum> <sum of sq> <mean> <std dev>.\n" "The input object is read from stdin and values are written to stdout\n" "unless the filenames are given.\n", *argv, " -o stats.txt myobj.wlz\n" "The input Woolz object is read from myobj.wlz. The statistics are\n" "calculated and written to out.txt.\n"); } return(!ok); }
/*! * \return Woolz error code. * \ingroup WlzExtFF * \brief Writes the given Woolz object to the given file(s) * using the ANALYZE 7.5 file format. The given file name is * used to generate the '.hdr' and '.img' filenames. * \param gvnFileName Given file name with .hdr, .img or no * extension. * \param obj Given woolz object. */ WlzErrorNum WlzEffWriteObjAnl(const char *gvnFileName, WlzObject *obj) { int cnt = 0; double dMin, dMax; FILE *fP = NULL; void *data = NULL; WlzGreyP dataP; WlzEffAnlDsr dsr; WlzGreyType gType; WlzVertex org, sz; char *fileName = NULL, *hdrFileName = NULL, *imgFileName = NULL; WlzErrorNum errNum = WLZ_ERR_NONE; dataP.v = NULL; if((gvnFileName == NULL) || (*gvnFileName == '\0')) { errNum = WLZ_ERR_PARAM_NULL; } else if(obj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else if(obj->values.core == NULL) { errNum = WLZ_ERR_VALUES_NULL; } else { errNum = WlzEffAnlFileNames(&fileName, &hdrFileName, &imgFileName, gvnFileName); } /* Fill in the ANALYZE file header data structures. */ if(errNum == WLZ_ERR_NONE) { (void )memset(&dsr, 0, sizeof(WlzEffAnlDsr)); switch(obj->type) { case WLZ_2D_DOMAINOBJ: org.i2.vtX = obj->domain.i->kol1; org.i2.vtY = obj->domain.i->line1; sz.i2.vtX = obj->domain.i->lastkl - org.i2.vtX + 1; sz.i2.vtY = obj->domain.i->lastln - org.i2.vtY + 1; if((sz.i2.vtX <= 0) || (sz.i2.vtY <= 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else { dsr.dim.dim[0] = 2; dsr.dim.dim[1] = sz.i2.vtX; dsr.dim.dim[2] = sz.i2.vtY; dsr.dim.pixdim[0] = 2; dsr.dim.pixdim[1] = 1.0; dsr.dim.pixdim[2] = 1.0; } break; case WLZ_3D_DOMAINOBJ: org.i3.vtX = obj->domain.p->kol1; org.i3.vtY = obj->domain.p->line1; org.i3.vtZ = obj->domain.p->plane1; sz.i3.vtX = obj->domain.p->lastkl - org.i3.vtX + 1; sz.i3.vtY = obj->domain.p->lastln - org.i3.vtY + 1; sz.i3.vtZ = obj->domain.p->lastpl - org.i3.vtZ + 1; if((sz.i3.vtX <= 0) || (sz.i3.vtY <= 0) || (sz.i3.vtZ <= 0)) { errNum = WLZ_ERR_DOMAIN_DATA; } else { dsr.dim.dim[0] = 3; dsr.dim.dim[1] = sz.i3.vtX; dsr.dim.dim[2] = sz.i3.vtY; dsr.dim.dim[3] = sz.i3.vtZ; dsr.dim.pixdim[0] = 3; dsr.dim.pixdim[1] = obj->domain.p->voxel_size[0]; dsr.dim.pixdim[2] = obj->domain.p->voxel_size[1]; dsr.dim.pixdim[3] = obj->domain.p->voxel_size[2]; } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { (void )WlzGreyStats(obj, &gType, &dMin, &dMax, NULL, NULL, NULL, NULL, &errNum); } if(errNum == WLZ_ERR_NONE) { dsr.dim.glMax = (int )ceil(dMax); dsr.dim.glMin = (int )floor(dMin); switch(gType) { case WLZ_GREY_INT: dsr.dim.dataType = WLZEFF_ANL_DT_SIGNED_INT; dsr.dim.bitPix = 32; break; case WLZ_GREY_SHORT: dsr.dim.dataType = WLZEFF_ANL_DT_SIGNED_SHORT; dsr.dim.bitPix = 16; break; case WLZ_GREY_UBYTE: dsr.dim.dataType = WLZEFF_ANL_DT_UNSIGNED_CHAR; dsr.dim.bitPix = 8; break; case WLZ_GREY_FLOAT: dsr.dim.dataType = WLZEFF_ANL_DT_FLOAT; dsr.dim.bitPix = 32; break; case WLZ_GREY_DOUBLE: dsr.dim.dataType = WLZEFF_ANL_DT_DOUBLE; dsr.dim.bitPix = 64; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } if(errNum == WLZ_ERR_NONE) { dsr.hk.hdrSz = 348; dsr.hk.regular = 'r'; dsr.hk.extents = 16384; (void )strcpy(dsr.hist.descrip, "Converted from Woolz"); (void )strcpy(dsr.hist.originator, "Woolz"); (void )strcpy(dsr.hist.generated, "Woolz"); } /* Get Woolz object's values as an array. */ if(WLZ_ERR_NONE == errNum) { switch(obj->type) { case WLZ_2D_DOMAINOBJ: cnt = sz.i2.vtX * sz.i2.vtY; errNum = WlzToArray2D((void ***)&data, obj, sz.i2, org.i2, 0, gType); if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: dataP.inp = *(int **)data; break; case WLZ_GREY_SHORT: dataP.shp = *(short **)data; break; case WLZ_GREY_UBYTE: dataP.ubp = *(WlzUByte **)data; break; case WLZ_GREY_FLOAT: dataP.flp = *(float **)data; break; case WLZ_GREY_DOUBLE: dataP.dbp = *(double **)data; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } break; case WLZ_3D_DOMAINOBJ: cnt = sz.i3.vtX * sz.i3.vtY * sz.i3.vtZ; errNum = WlzToArray3D((void ****)&data, obj, sz.i3, org.i3, 0, gType); if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: dataP.inp = **(int ***)data; break; case WLZ_GREY_SHORT: dataP.shp = **(short ***)data; break; case WLZ_GREY_UBYTE: dataP.ubp = **(WlzUByte ***)data; break; case WLZ_GREY_FLOAT: dataP.flp = **(float ***)data; break; case WLZ_GREY_DOUBLE: dataP.dbp = **(double ***)data; break; default: errNum = WLZ_ERR_GREY_TYPE; break; } } break; default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } /* Open the ANALYZE .hdr file and write the header information. */ if(errNum == WLZ_ERR_NONE) { if((fP = fopen(hdrFileName, "w")) == NULL) { errNum = WLZ_ERR_WRITE_EOF; } #ifdef _WIN32 else if(_setmode(_fileno(fP), 0x8000) == -1) { errNum = WLZ_ERR_READ_EOF; } #endif } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrKey(fP, &dsr); } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrImageDim(fP, &dsr); } if(errNum == WLZ_ERR_NONE) { errNum = WlzEffWriteAnlHdrDataHistory(fP, &dsr); } if(fP) { (void )fclose(fP); fP = NULL; } /* Open the ANALYZE .img file and write the image data. */ if(errNum == WLZ_ERR_NONE) { if((fP = fopen(imgFileName, "w")) == NULL) { errNum = WLZ_ERR_WRITE_EOF; } #ifdef _WIN32 else if(_setmode(_fileno(fP), 0x8000) == -1) { errNum = WLZ_ERR_READ_EOF; } #endif } if(errNum == WLZ_ERR_NONE) { switch(gType) { case WLZ_GREY_INT: errNum = WlzEffWriteAnlInt(fP, cnt, dataP.inp); break; case WLZ_GREY_SHORT: errNum = WlzEffWriteAnlShort(fP, cnt, dataP.shp); break; case WLZ_GREY_UBYTE: errNum = WlzEffWriteAnlChar(fP, cnt, dataP.ubp); break; case WLZ_GREY_FLOAT: errNum = WlzEffWriteAnlFloat(fP, cnt, dataP.flp); break; case WLZ_GREY_DOUBLE: errNum = WlzEffWriteAnlDouble(fP, cnt, dataP.dbp); break; default: break; } } if(fP) { (void )fclose(fP); } if(data) { switch(obj->type) { case WLZ_2D_DOMAINOBJ: Alc2Free((void **)data); break; case WLZ_3D_DOMAINOBJ: Alc3Free((void ***)data); break; default: break; } } (void )AlcFree(fileName); (void )AlcFree(hdrFileName); (void )AlcFree(imgFileName); return(errNum); }
int main(int argc, char *argv[]) { int ok = 1, option, usage = 0, stats = 0; char *inFileStr[2]; char *outFileStr; int maxDist = 0; WlzObject *outObj = NULL; WlzObject *inObj[2] = {NULL}; WlzErrorNum errNum = WLZ_ERR_NONE; const char *errMsgStr; static char optList[] = "hSm:o:"; const char fileStrDef[] = "-"; /* Parse the argument list and check for input files. */ opterr = 0; outFileStr = (char *)fileStrDef; inFileStr[0] = inFileStr[1] = (char *)fileStrDef; while(ok && !usage && ((option = getopt(argc, argv, optList)) != EOF)) { switch(option) { case 'm': if((sscanf(optarg, "%d", &maxDist) != 1) || (maxDist < 0)) { usage = 1; } break; case 'o': outFileStr = optarg; break; case 'h': default: usage = 1; break; } } if(ok) { ok = !usage; } if(ok && (optind < argc)) { if((optind + 2) != argc) { usage = 1; ok = 0; } else { inFileStr[0] = argv[optind + 0]; inFileStr[1] = argv[optind + 1]; } } /* Read the reference object. */ if(ok) { int idx; for(idx = 0; idx < 2; ++idx) { FILE *fP = NULL; if((inFileStr[idx] == NULL) || (*inFileStr[idx] == '\0') || ((fP = (strcmp(inFileStr[idx], "-")? fopen(inFileStr[idx], "r"): stdin)) == NULL) || ((inObj[idx] = WlzAssignObject( WlzReadObj(fP, &errNum), NULL)) == NULL)) { ok = 0; (void )fprintf(stderr, "%s: Failed to read object from file %s.\n", argv[0], inFileStr[idx]); } if(fP && strcmp(inFileStr[idx], "-")) { (void )fclose(fP); fP = NULL; } } } /* Compute the equi-distant distance object. */ if(ok) { outObj = WlzAssignObject( WlzOffsetDist(inObj[0], inObj[1], maxDist, &errNum), NULL); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to compute equi-distant distance object, %s.\n", argv[0], errMsgStr); } } /* Output the nearby domain object. */ if(ok) { FILE *fP = NULL; if((fP = (strcmp(outFileStr, "-")? fopen(outFileStr, "w"): stdout)) == NULL) { ok = 0; (void )fprintf(stderr, "%s: Failed to open output file %s.\n", argv[0], outFileStr); } if(ok) { if(stats == 0) { /* Output equi-distant distance object. */ if(ok) { errNum = WlzWriteObj(fP, outObj); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to write output object, %s.\n", argv[0], errMsgStr); } } } else { int n; double dMin, dMax, dSum, dSSq, dMean, dSDev; n = WlzGreyStats(outObj, NULL, &dMin, &dMax, &dSum, &dSSq, &dMean, &dSDev, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s: Failed to compute equi-distant distance statistics, %s.\n", argv[0], errMsgStr); } else { (void )fprintf(fP, "%d %lg %lg %lg %lg %lg %lg\n", n, dMin, dMax, dSum, dSSq, dMean, dSDev); } } } if(fP && strcmp(outFileStr, "-")) { (void )fclose(fP); fP = NULL; } } (void )WlzFreeObj(outObj); if(usage) { (void )fprintf(stderr, "Usage: %s [-m#] [-S] [-o<output file>] [-h]\n" "\t\t[<object 1>] [<object 2>]\n" "Version: %s\n" "Computes an object with domain and values that are the set of minimum\n" "distances between the two given objects. The equidistant boundary is\n" "computed between the domains of the two given objects, within the\n" " distance limit and within the convex hull of the union of the two\n" "given object's domains.\n" "By default all files are read from the standard input and written\n" "to the standard output.\n" "Options:\n" " -m Maximum distance to consider (default 0, limit is convex hull).\n" " -S Output statistics rather than distance object. Output statistics\n" " are printed on a single line with the order:\n" " volume, min, max, sum, sum of squares, mean, standard deviation.\n" " -o Output object file.\n" " -h Help - prints this usage message\n" "By default all files are read from the standard input and written to\n" "the standard output.\n" "Example:\n" " %s -o out.wlz -o out.wlz obj1.wlz obj2.wlz\n" "which creates a domain object corresponding to the minimum equidistant\n" "voxel set between the given objects, with maximum distance constrained\n" "only be the convex hull of the two given objects. The resulting object\n" "is written to the file out.wlz.\n", argv[0], WlzVersion(), argv[0]); } return(!ok); }