43 #include "boost/pointer_cast.hpp"
44 #include "boost/regex.hpp"
57 namespace pexExcept = lsst::pex::exceptions;
59 namespace afwGeom = lsst::afw::geom;
60 namespace afwCoord = lsst::afw::coord;
61 namespace afwMath = lsst::afw::math;
79 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"bad ind argument in WarpingKernel::setKernelParameter()");
81 int ctr = p->
getCtr()[ind];
84 if (ctr == (size-1)/2) {
85 if (value < -1e-6 || value > 1+1e-6) {
86 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"bad coordinate in WarpingKernel::setKernelParameter()");
88 }
else if (ctr == (size+1)/2) {
89 if (value < -1-1e-6 || value > 1e-6) {
90 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"bad coordinate in WarpingKernel::setKernelParameter()");
93 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"bad ctr value in WarpingKernel::setKernelParameter()");
111 checkWarpingKernelParameter(
this, ind, value);
140 return 0.5 + (1.0 - (2.0 * fabs(this->_params[0]))) * (0.5 - fabs(x));
145 checkWarpingKernelParameter(
this, ind, value);
152 std::string afwMath::BilinearWarpingKernel::BilinearFunction1::toString(std::string
const& prefix)
const {
153 std::ostringstream os;
154 os <<
"_BilinearFunction1: ";
155 os << Function1<Kernel::Pixel>::toString(prefix);
172 return static_cast<double>((fabs(this->_params[0]) < 0.5) == (fabs(x) < 0.5));
177 checkWarpingKernelParameter(
this, ind, value);
184 std::string afwMath::NearestWarpingKernel::NearestFunction1::toString(std::string
const& prefix)
const {
185 std::ostringstream os;
186 os <<
"_NearestFunction1: ";
187 os << Function1<Kernel::Pixel>::toString(prefix);
192 typedef std::shared_ptr<afwMath::SeparableKernel> KernelPtr;
193 boost::cmatch matches;
194 static const boost::regex LanczosRE(
"lanczos(\\d+)");
195 if (name ==
"bilinear") {
197 }
else if (boost::regex_match(name.c_str(), matches, LanczosRE)) {
198 std::string orderStr(matches[1].first, matches[1].second);
200 std::istringstream(orderStr) >> order;
202 }
else if (name ==
"nearest") {
205 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
206 "unknown warping kernel name: \"" + name +
"\"");
211 if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
212 _warpingKernelPtr->computeCache(_cacheSize);
214 return _warpingKernelPtr;
221 setWarpingKernel(*warpingKernelPtr);
227 if (_maskWarpingKernelPtr) {
228 _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
231 _warpingKernelPtr = warpingKernelPtr;
236 if (_maskWarpingKernelPtr) {
237 if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
238 _maskWarpingKernelPtr->computeCache(_cacheSize);
241 return _maskWarpingKernelPtr;
245 std::string
const &maskWarpingKernelName
247 if (!maskWarpingKernelName.empty()) {
249 setMaskWarpingKernel(*maskWarpingKernelPtr);
251 _maskWarpingKernelPtr.reset();
258 _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
275 if (!kernelBBox.
contains(maskKernelBBox)) {
276 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
277 "warping kernel is smaller than mask warping kernel");
281 template<
typename DestExposureT,
typename SrcExposureT>
283 DestExposureT &destExposure,
284 SrcExposureT
const &srcExposure,
286 typename DestExposureT::MaskedImageT::SinglePixel padValue
289 if (!destExposure.hasWcs()) {
290 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"destExposure has no Wcs");
292 if (!srcExposure.hasWcs()) {
293 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"srcExposure has no Wcs");
295 typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
296 std::shared_ptr<afwImage::Calib> calibCopy(
new afwImage::Calib(*srcExposure.getCalib()));
297 destExposure.setCalib(calibCopy);
298 destExposure.setFilter(srcExposure.getFilter());
299 return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(),
322 inline double computeRelativeArea(
330 return std::abs(dSrcA.getX()*dSrcB.getY() - dSrcA.getY()*dSrcB.getX());
333 template<
typename DestImageT,
typename SrcImageT>
335 DestImageT &destImage,
336 SrcImageT
const &srcImage,
337 afwMath::detail::PositionFunctor
const &computeSrcPos,
340 typename DestImageT::SinglePixel padValue
343 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
344 "destImage is srcImage; cannot warp in place");
352 warpingKernelPtr->shrinkBBox(srcImage.getBBox(afwImage::
LOCAL));
355 for (
typename DestImageT::x_iterator destPtr = destImage.row_begin(
y), end = destImage.row_end(
y);
356 destPtr != end; ++destPtr) {
363 int interpLength = control.getInterpLength();
365 std::shared_ptr<afwMath::LanczosWarpingKernel const> const lanczosKernelPtr =
366 std::dynamic_pointer_cast<afwMath::LanczosWarpingKernel>(warpingKernelPtr);
369 int numGoodPixels = 0;
372 int const srcWidth = srcImage.getWidth();
373 int const srcHeight = srcImage.getHeight();
376 int const destWidth = destImage.getWidth();
377 int const destHeight = destImage.getHeight();
391 std::vector<afwGeom::
Point2D> _srcPosList(1 + destWidth);
392 std::vector<afwGeom::
Point2D>::iterator const srcPosView = _srcPosList.begin() + 1;
394 int const maxCol = destWidth - 1;
395 int const maxRow = destHeight - 1;
397 afwMath::detail::WarpAtOnePoint<DestImageT, SrcImageT> warpAtOnePoint(srcImage, control, padValue);
399 if (interpLength > 0) {
404 int const numColEdges = 2 + ((destWidth - 1) / interpLength);
408 std::vector<int> edgeColList;
409 edgeColList.reserve(numColEdges);
413 std::vector<double> invWidthList;
414 invWidthList.reserve(numColEdges);
417 edgeColList.push_back(-1);
418 invWidthList.push_back(0.0);
419 for (
int prevEndCol = -1; prevEndCol < maxCol; prevEndCol += interpLength) {
420 int endCol = prevEndCol + interpLength;
421 if (endCol > maxCol) {
424 edgeColList.push_back(endCol);
425 assert(endCol - prevEndCol > 0);
426 invWidthList.push_back(1.0 / static_cast<double>(endCol - prevEndCol));
428 assert(edgeColList.back() == maxCol);
431 std::vector<afwGeom::Extent2D> yDeltaSrcPosList(edgeColList.size());
435 srcPosView[-1] = computeSrcPos(-1, -1);
436 for (
int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
437 int const prevEndCol = edgeColList[colBand-1];
438 int const endCol = edgeColList[colBand];
441 afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
443 for (
int col = prevEndCol + 1; col <= endCol; ++
col) {
444 srcPosView[
col] = srcPosView[col-1] + xDeltaSrcPos;
449 while (endRow < maxRow) {
452 int prevEndRow = endRow;
453 endRow = prevEndRow + interpLength;
454 if (endRow > maxRow) {
457 assert(endRow - prevEndRow > 0);
458 double interpInvHeight = 1.0 /
static_cast<double>(endRow - prevEndRow);
461 for (
int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
462 int endCol = edgeColList[colBand];
464 yDeltaSrcPosList[colBand] = (bottomSrcPos - srcPosView[endCol]) * interpInvHeight;
467 for (
int row = prevEndRow + 1; row <= endRow; ++
row) {
468 typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
469 srcPosView[-1] += yDeltaSrcPosList[0];
470 for (
int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
473 int const prevEndCol = edgeColList[colBand-1];
474 int const endCol = edgeColList[colBand];
480 afwGeom::Point2D rightSrcPos = srcPosView[endCol] + yDeltaSrcPosList[colBand];
481 afwGeom::Extent2D xDeltaSrcPos = (rightSrcPos - leftSrcPos) * invWidthList[colBand];
483 for (
int col = prevEndCol + 1; col <= endCol; ++
col, ++destXIter) {
486 double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[col]);
488 srcPosView[
col] = srcPos;
490 if (warpAtOnePoint(destXIter, srcPos, relativeArea,
505 std::vector<afwGeom::Point2D>::iterator srcPosView = _srcPosList.begin() + 1;
506 for (
int col = -1; col < destWidth; ++
col) {
507 srcPosView[
col] = computeSrcPos(col, -1);
510 for (
int row = 0; row < destHeight; ++
row) {
511 typename DestImageT::x_iterator destXIter = destImage.row_begin(row);
513 srcPosView[-1] = computeSrcPos(-1, row);
515 for (
int col = 0; col < destWidth; ++
col, ++destXIter) {
517 double relativeArea = computeRelativeArea(srcPos, srcPosView[col-1], srcPosView[col]);
518 srcPosView[
col] = srcPos;
520 if (warpAtOnePoint(destXIter, srcPos, relativeArea,
528 return numGoodPixels;
533 template<
typename DestImageT,
typename SrcImageT>
535 DestImageT &destImage,
537 SrcImageT
const &srcImage,
540 typename DestImageT::SinglePixel padValue
544 afwMath::detail::XYTransformPositionFunctor
const computeSrcPos{destXY0, xyTransform};
545 return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue);
549 template<
typename DestImageT,
typename SrcImageT>
551 DestImageT &destImage,
552 SrcImageT
const &srcImage,
555 typename DestImageT::SinglePixel padValue
558 afwMath::detail::XYTransformPositionFunctor
const computeSrcPos(destXY0, xyTransform);
559 return doWarpImage(destImage, srcImage, computeSrcPos, control, padValue);
563 template<
typename DestImageT,
typename SrcImageT>
565 DestImageT &destImage,
566 SrcImageT
const &srcImage,
570 typename DestImageT::SinglePixel padValue
574 (destImage.getWidth() != srcImage.getWidth()) ||
575 (destImage.getHeight() != srcImage.getHeight()) ||
576 (destImage.getXY0() != srcImage.getXY0())
578 std::ostringstream errStream;
579 errStream <<
"src and dest images must have same size and xy0.";
580 throw LSST_EXCEPT(pexExcept::InvalidParameterError, errStream.str());
584 SrcImageT srcImageCopy(srcImage,
true);
585 srcImageCopy.setXY0(0, 0);
586 destImage.setXY0(0, 0);
597 static float t = 0.0;
598 float t_before = 1.0*clock()/CLOCKS_PER_SEC;
599 int n =
warpImage(destImage, srcImageCopy, affTran, control, padValue);
600 float t_after = 1.0*clock()/CLOCKS_PER_SEC;
601 float dt = t_after - t_before;
603 std::cout <<srcImage.getWidth()<<
"x"<<srcImage.getHeight()<<
": "<< dt <<
" "<< t <<std::endl;
605 int n =
warpImage(destImage, srcImageCopy, affXYTransform, control, padValue);
609 destImage.setXY0(srcImage.getXY0());
620 #define EXPOSURE(PIXTYPE) afwImage::Exposure<PIXTYPE, afwImage::MaskPixel, afwImage::VariancePixel>
621 #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage<PIXTYPE, afwImage::MaskPixel, afwImage::VariancePixel>
622 #define IMAGE(PIXTYPE) afwImage::Image<PIXTYPE>
625 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
626 template int afwMath::warpCenteredImage( \
627 IMAGE(DESTIMAGEPIXELT) &destImage, \
628 IMAGE(SRCIMAGEPIXELT) const &srcImage, \
629 afwGeom::LinearTransform const &linearTransform, \
630 afwGeom::Point2D const ¢erPosition, \
631 afwMath::WarpingControl const &control, \
632 IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
633 template int afwMath::warpCenteredImage( \
634 MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
635 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
636 afwGeom::LinearTransform const &linearTransform, \
637 afwGeom::Point2D const ¢erPosition, \
638 afwMath::WarpingControl const &control, \
639 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
640 template int afwMath::warpImage( \
641 IMAGE(DESTIMAGEPIXELT) &destImage, \
642 IMAGE(SRCIMAGEPIXELT) const &srcImage, \
643 afwGeom::XYTransform const &xyTransform, \
644 afwMath::WarpingControl const &control, \
645 IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
646 template int afwMath::warpImage( \
647 MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
648 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
649 afwGeom::XYTransform const &xyTransform, \
650 afwMath::WarpingControl const &control, \
651 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
652 template int afwMath::warpImage( \
653 IMAGE(DESTIMAGEPIXELT) &destImage, \
654 afwImage::Wcs const &destWcs, \
655 IMAGE(SRCIMAGEPIXELT) const &srcImage, \
656 afwImage::Wcs const &srcWcs, \
657 afwMath::WarpingControl const &control, \
658 IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
659 template int afwMath::warpImage( \
660 MASKEDIMAGE(DESTIMAGEPIXELT) &destImage, \
661 afwImage::Wcs const &destWcs, \
662 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
663 afwImage::Wcs const &srcWcs, \
664 afwMath::WarpingControl const &control, \
665 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); NL \
666 template int afwMath::warpExposure( \
667 EXPOSURE(DESTIMAGEPIXELT) &destExposure, \
668 EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, \
669 afwMath::WarpingControl const &control,\
670 EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
An include file to include the header files for lsst::afw::geom.
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
Declare the Kernel class and subclasses.
boost::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
double indexToPosition(double ind)
Convert image index to image position.
table::Key< std::string > name
Include files required for standard LSST Exception handling.
Extent< double, 2 > Extent2D
geom::Point2D skyToPixel(geom::Angle sky1, geom::Angle sky2) const
Convert from sky coordinates (e.g.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
Parameters to control convolution.
Implementation of the WCS standard for a any projection.
virtual Ptr clone(void) const
int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage, lsst::afw::geom::LinearTransform const &linearTransform, lsst::afw::geom::Point2D const ¢erPosition, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an image with a LinearTranform about a specified point.
boost::shared_ptr< coord::Coord > pixelToSky(double pix1, double pix2) const
Convert from pixel position to sky coordinates (e.g.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Describe an exposure's calibration.
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
An integer coordinate rectangle.
int warpImage(DestImageT &destImage, lsst::afw::image::Wcs const &destWcs, SrcImageT const &srcImage, lsst::afw::image::Wcs const &srcWcs, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an Image or MaskedImage to a new Wcs.
table::Key< table::Array< Kernel::Pixel > > image
int getOrder() const
get the order of the kernel
LSST DM logging module built on log4cxx.
int getWidth() const
Return the Kernel's width.
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.
metadata import lsst afw display as afwDisplay n
A class representing an Angle.
void ImageT ImageT int float saturatedPixelValue int const width
bool contains(Point2I const &point) const
Return true if the box contains the point.
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
bool isSameObject(A const &, B const &)
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
if(width!=gim.getWidth()||height!=gim.getHeight()||x0!=gim.getX0()||y0!=gim.getY0())
Classes to support calibration (e.g.
lsst::afw::geom::Point2I getCtr() const
Return index of kernel's center.
Bilinear warping: fast; good for undersampled data.
void ImageT ImageT int float saturatedPixelValue int const height
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
tbl::Key< std::string > warpingKernelName
Support for warping an image to a new WCS.
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
Nearest neighbor warping: fast; good for undersampled data.
void _testWarpingKernels(SeparableKernel const &warpingKernel, SeparableKernel const &maskWarpingKernel) const
Throw an exception if the two kernels are not compatible in shape.
Lanczos warping: accurate but slow and can introduce ringing artifacts.
Point< double, 2 > Point2D
ImageT::image_category image_category
virtual boost::shared_ptr< Kernel > clone() const
Return a pointer to a deep copy of this kernel.
Kernels are used for convolution with MaskedImages and (eventually) Images.
Functions to handle coordinates.