int main(int argc, char *argv[]) { int ok = 1, option, usage = 0; FILE *fP = NULL; char *inObjFileStr, *outObjFileStr; const char *errMsgStr; WlzErrorNum errNum = WLZ_ERR_NONE; WlzObject *inObj = NULL, *outObj = NULL; static char optList[] = "ho:"; const char inObjFileStrDef[] = "-", outObjFileStrDef[] = "-"; opterr = 0; inObjFileStr = (char *)inObjFileStrDef; outObjFileStr = (char *)outObjFileStrDef; while(ok && ((option = getopt(argc, argv, optList)) != EOF)) { switch(option) { case 'o': outObjFileStr = optarg; break; case 'h': default: usage = 1; ok = 0; break; } } if(ok) { 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) { if((inObjFileStr == NULL) || (*inObjFileStr == '\0') || ((fP = (strcmp(inObjFileStr, "-")? fopen(inObjFileStr, "r"): stdin)) == NULL) || ((inObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) || (errNum != WLZ_ERR_NONE)) { ok = 0; (void )fprintf(stderr, "%s: failed to read object from file %s\n", *argv, inObjFileStr); } if(fP && strcmp(inObjFileStr, "-")) { fclose(fP); } } if(ok) { outObj = WlzAutoCor(inObj, &errNum); if(errNum != WLZ_ERR_NONE) { ok = 0; (void )WlzStringFromErrorNum(errNum, &errMsgStr); (void )fprintf(stderr, "%s Failed objects autocorrelation, %s.\n", argv[0], errMsgStr); } } if(ok) { if((fP = (strcmp(outObjFileStr, "-")? fopen(outObjFileStr, "w"): stdout)) == NULL) { ok = 0; (void )fprintf(stderr, "%s: Failed to open output file %s.\n", argv[0], outObjFileStr); } } 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); } } (void )WlzFreeObj(inObj); (void )WlzFreeObj(outObj); if(usage) { fprintf(stderr, "Usage: %s [-h] [-o<output file>] [<input object>]\n" "Computes the autocorrelation of the given object.\n" "Version: %s\n" "Options are:\n" " -h Output this usage message.\n" " -o Output file.\n", argv[0], WlzVersion()); } return(!ok); }
/*! * \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); }