/* * Copyright (c) 1999, University of Amsterdam, The Netherlands. * All rights reserved. * * Author(s): * Dennis Koelma (koelma@wins.uva.nl) * Edo Poll (poll@wins.uva.nl) * Marc Navarro (mnavarro@wins.uva.nl) * */ #include "HxSquaredDistance.h" #include "HxImgFtorBpo.h" #include "HxIncludedSigs.h" /** Pixel functor for computation of squared distance */ template<class DstValT, class Src1ValT, class Src2ValT> class HxBpoSqrDst { public: /** Functor is translation invariant */ typedef HxTagTransInVar TransVarianceCategory; /** Constructor : empty */ HxBpoSqrDst(HxTagList&) { } /** Actual operation : # return (x - y)^2 # */ inline DstValT doIt(const Src1ValT& arg1, const Src2ValT& arg2) { return (arg1 - arg2) * (arg1 - arg2); } /** The name : "sqrDst" */ static HxString className() { return HxString("sqrDst"); } }; /** Instantiator for binary pixel operation with squared distance */ template<class ImgSigT> struct HxInstantiatorSqrDst { /** Instantiate image functor */ HxImgFtorBpo<ImgSigT, ImgSigT, ImgSigT, HxBpoSqrDst<typename ImgSigT::ArithType, typename ImgSigT::ArithType, typename ImgSigT::ArithType> > f; }; // Put static variables in a namespace to avoid conflicts with file inclusion namespace HxSquaredDistance_c { /** Call instantiator for 2dByte images */ static HxInstantiatorSqrDst<HxImageSig2dByte> f001; /** Call instantiator for 2dShort images */ static HxInstantiatorSqrDst<HxImageSig2dShort> f002; /** Call instantiator for 2dInt images */ static HxInstantiatorSqrDst<HxImageSig2dInt> f003; /** Call instantiator for 2dFloat images */ static HxInstantiatorSqrDst<HxImageSig2dFloat> f004; /** Call instantiator for 2dDouble images */ static HxInstantiatorSqrDst<HxImageSig2dDouble> f005; /** Call instantiator for 2dVec2Byte images */ static HxInstantiatorSqrDst<HxImageSig2dVec2Byte> f006; /** Call instantiator for 2dVec2Short images */ static HxInstantiatorSqrDst<HxImageSig2dVec2Short> f007; /** Call instantiator for 2dVec2Int images */ static HxInstantiatorSqrDst<HxImageSig2dVec2Int> f008; /** Call instantiator for 2dVec2Float images */ static HxInstantiatorSqrDst<HxImageSig2dVec2Float> f009; /** Call instantiator for 2dVec2Double images */ static HxInstantiatorSqrDst<HxImageSig2dVec2Double> f010; /** Call instantiator for 2dVec3Byte images */ static HxInstantiatorSqrDst<HxImageSig2dVec3Byte> f011; /** Call instantiator for 2dVec3Short images */ static HxInstantiatorSqrDst<HxImageSig2dVec3Short> f012; /** Call instantiator for 2dVec3Int images */ static HxInstantiatorSqrDst<HxImageSig2dVec3Int> f013; /** Call instantiator for 2dVec3Float images */ static HxInstantiatorSqrDst<HxImageSig2dVec3Float> f014; /** Call instantiator for 2dVec3Double images */ static HxInstantiatorSqrDst<HxImageSig2dVec3Double> f015; /** Call instantiator for 3dByte images */ static HxInstantiatorSqrDst<HxImageSig3dByte> f016; /** Call instantiator for 3dShort images */ static HxInstantiatorSqrDst<HxImageSig3dShort> f017; /** Call instantiator for 3dInt images */ static HxInstantiatorSqrDst<HxImageSig3dInt> f018; /** Call instantiator for 3dFloat images */ static HxInstantiatorSqrDst<HxImageSig3dFloat> f019; /** Call instantiator for 3dDouble images */ static HxInstantiatorSqrDst<HxImageSig3dDouble> f020; }; // end of namespace /* Global function to do squared distance. */ HxImageRep HxSquaredDistance(HxImageRep im1, HxImageRep im2) { HxString fname("HxSquaredDistance"); if (im1.isNull()) { HxGlobalError::instance()->reportError(fname, im1.name(), "null image", HxGlobalError::HX_GE_INVALID); return HxImageRep(); } if (im2.isNull()) { HxGlobalError::instance()->reportError(fname, im2.name(), "null image", HxGlobalError::HX_GE_INVALID); return HxImageRep(); } if (im1.dimensionality() != im2.dimensionality()) { HxGlobalError::instance()->reportError(fname, "unequal image dimensionalities", HxGlobalError::HX_GE_UNEQUAL_IMAGES); return HxImageRep(); } if (im1.pixelDimensionality() != im2.pixelDimensionality()) { HxGlobalError::instance()->reportError(fname, "unequal pixel dimensionality", HxGlobalError::HX_GE_UNEQUAL_IMAGES); return HxImageRep(); } if (im1.sizes().x() != im2.sizes().x()) { HxGlobalError::instance()->reportError(fname, "unequal image widths", HxGlobalError::HX_GE_UNEQUAL_IMAGES); return HxImageRep(); } if (im1.sizes().y() != im2.sizes().y()) { HxGlobalError::instance()->reportError(fname, "unequal image heights", HxGlobalError::HX_GE_UNEQUAL_IMAGES); return HxImageRep(); } if (im1.dimensionality() > 2) { if (im1.sizes().z() != im2.sizes().z()) { HxGlobalError::instance()->reportError(fname, "unequal image depths", HxGlobalError::HX_GE_UNEQUAL_IMAGES); return HxImageRep(); } } // call HxImageRep member function to do the image processing return im1.binaryPixOp(im2, "sqrDst"); }
Instantiation of a new binary pixel operation basically includes the following steps:
In this example the function computes the squared distance between two pixel values. The functor is defined by class HxBpoSqrDst.
The binary pixel functor will apply the user defined pixel operation to all pixels in an image. The functor must be instantiated for all image types separately so we use a helper class HxInstantiatorSqrDst to do instantiation for one image type, and "call" the instantiator for each image type via declaration of a number of static variables (f001, f002, etc.).
This is taken care of by HxSquaredDistance.