LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
ConvolveWithInterpolation.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
34 #include <algorithm>
35 #include <cmath>
36 #include <cstdint>
37 #include <sstream>
38 #include <vector>
39 #include <iostream>
40 
41 #include "lsst/pex/exceptions.h"
42 #include "lsst/log/Log.h"
44 #include "lsst/afw/math/Kernel.h"
45 #include "lsst/afw/geom.h"
47 
48 namespace pexExcept = lsst::pex::exceptions;
49 namespace afwGeom = lsst::afw::geom;
50 namespace afwImage = lsst::afw::image;
51 namespace afwMath = lsst::afw::math;
52 namespace mathDetail = lsst::afw::math::detail;
53 
68 template <typename OutImageT, typename InImageT>
70  OutImageT &outImage,
71  InImageT const &inImage,
72  lsst::afw::math::Kernel const &kernel,
73  lsst::afw::math::ConvolutionControl const &convolutionControl)
74 {
75  if (outImage.getDimensions() != inImage.getDimensions()) {
76  std::ostringstream os;
77  os << "outImage dimensions = ( "
78  << outImage.getWidth() << ", " << outImage.getHeight()
79  << ") != (" << inImage.getWidth() << ", " << inImage.getHeight() << ") = inImage dimensions";
80  throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
81  }
82 
83  // compute region covering good area of output image
84  afwGeom::Box2I fullBBox = afwGeom::Box2I(
85  afwGeom::Point2I(0, 0),
86  afwGeom::Extent2I(outImage.getWidth(), outImage.getHeight()));
87  afwGeom::Box2I goodBBox = kernel.shrinkBBox(fullBBox);
89  kernel.clone(),
90  goodBBox,
91  inImage.getXY0(),
92  convolutionControl.getDoNormalize()));
93  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
94  "convolveWithInterpolation: full bbox minimum=(%d, %d), extent=(%d, %d)",
95  fullBBox.getMinX(), fullBBox.getMinY(),
96  fullBBox.getWidth(), fullBBox.getHeight());
97  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
98  "convolveWithInterpolation: goodRegion bbox minimum=(%d, %d), extent=(%d, %d)",
99  goodRegion.getBBox().getMinX(), goodRegion.getBBox().getMinY(),
100  goodRegion.getBBox().getWidth(), goodRegion.getBBox().getHeight());
101 
102  // divide good region into subregions small enough to interpolate over
103  int nx = 1 + (goodBBox.getWidth() / convolutionControl.getMaxInterpolationDistance());
104  int ny = 1 + (goodBBox.getHeight() / convolutionControl.getMaxInterpolationDistance());
105  LOGL_DEBUG("TRACE3.afw.math.convolve.convolveWithInterpolation",
106  "convolveWithInterpolation: divide into %d x %d subregions", nx, ny);
107 
109  RowOfKernelImagesForRegion regionRow(nx, ny);
110  while (goodRegion.computeNextRow(regionRow)) {
111  for (RowOfKernelImagesForRegion::ConstIterator rgnIter = regionRow.begin(), rgnEnd = regionRow.end();
112  rgnIter != rgnEnd; ++rgnIter) {
113  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
114  "convolveWithInterpolation: bbox minimum=(%d, %d), extent=(%d, %d)",
115  (*rgnIter)->getBBox().getMinX(), (*rgnIter)->getBBox().getMinY(),
116  (*rgnIter)->getBBox().getWidth(), (*rgnIter)->getBBox().getHeight());
117  convolveRegionWithInterpolation(outImage, inImage, **rgnIter, workingImages);
118  }
119  }
120 }
121 
129 template <typename OutImageT, typename InImageT>
131  OutImageT &outImage,
132  InImageT const &inImage,
133  KernelImagesForRegion const &region,
135 {
136  typedef typename OutImageT::xy_locator OutLocator;
137  typedef typename InImageT::const_xy_locator InConstLocator;
138  typedef KernelImagesForRegion::Image KernelImage;
139  typedef KernelImage::const_xy_locator KernelConstLocator;
140 
141  CONST_PTR(afwMath::Kernel) kernelPtr = region.getKernel();
142  geom::Extent2I const kernelDimensions(kernelPtr->getDimensions());
145  workingImages.kernelImage.assign(workingImages.leftImage);
146 
147  afwGeom::Box2I const goodBBox = region.getBBox();
148  afwGeom::Box2I const fullBBox = kernelPtr->growBBox(goodBBox);
149 
150  // top and right images are computed one beyond bbox boundary,
151  // so the distance between edge images is bbox width/height pixels
152  double xfrac = 1.0 / static_cast<double>(goodBBox.getWidth());
153  double yfrac = 1.0 / static_cast<double>(goodBBox.getHeight());
154  afwMath::scaledPlus(workingImages.leftDeltaImage,
156  -yfrac, workingImages.leftImage);
157  afwMath::scaledPlus(workingImages.rightDeltaImage,
159  -yfrac, workingImages.rightImage);
160 
161  KernelConstLocator const kernelLocator = workingImages.kernelImage.xy_at(0, 0);
162 
163  // The loop is a bit odd for efficiency: the initial value of workingImages.kernelImage
164  // and related kernel images are set when they are allocated,
165  // so they are not computed in the loop until after the convolution; to save cpu cycles
166  // they are not computed at all for the last iteration.
167  InConstLocator inLocator = inImage.xy_at(fullBBox.getMinX(), fullBBox.getMinY());
168  OutLocator outLocator = outImage.xy_at(goodBBox.getMinX(), goodBBox.getMinY());
169  for (int j = 0; ; ) {
170  auto inLocatorInitialPosition = inLocator;
171  auto outLocatorInitialPosition = outLocator;
173  workingImages.deltaImage, xfrac, workingImages.rightImage, -xfrac, workingImages.leftImage);
174  for (int i = 0; ; ) {
175  *outLocator = afwMath::convolveAtAPoint<OutImageT, InImageT>(
176  inLocator, kernelLocator, kernelDimensions.getX(), kernelDimensions.getY());
177  ++outLocator.x();
178  ++inLocator.x();
179  ++i;
180  if (i >= goodBBox.getWidth()) {
181  break;
182  }
183  workingImages.kernelImage += workingImages.deltaImage;
184  }
185 
186  ++j;
187  if (j >= goodBBox.getHeight()) {
188  break;
189  }
190  workingImages.leftImage += workingImages.leftDeltaImage;
191  workingImages.rightImage += workingImages.rightDeltaImage;
192  workingImages.kernelImage.assign(workingImages.leftImage);
193 
194  // Workaround for DM-5822
195  // Boost GIL locator won't decrement in x-dimension for some strange and still
196  // not understood reason. So instead store position at start of previous row,
197  // reset and move down.
198  inLocator = inLocatorInitialPosition;
199  outLocator = outLocatorInitialPosition;
200  ++inLocator.y();
201  ++outLocator.y();
202  }
203 }
204 
205 /*
206  * Explicit instantiation
207  */
209 #define IMAGE(PIXTYPE) afwImage::Image<PIXTYPE>
210 #define MASKEDIMAGE(PIXTYPE) afwImage::MaskedImage<PIXTYPE, afwImage::MaskPixel, afwImage::VariancePixel>
211 #define NL /* */
212 // Instantiate Image or MaskedImage versions
213 #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \
214  template void mathDetail::convolveWithInterpolation( \
215  IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, afwMath::Kernel const&, \
216  afwMath::ConvolutionControl const&); NL \
217  template void mathDetail::convolveRegionWithInterpolation( \
218  IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const&, KernelImagesForRegion const&, \
219  ConvolveWithInterpolationWorkingImages&);
220 // Instantiate both Image and MaskedImage versions
221 #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \
222  INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \
223  INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE)
224 
225 INSTANTIATE(double, double)
226 INSTANTIATE(double, float)
227 INSTANTIATE(double, int)
228 INSTANTIATE(double, std::uint16_t)
229 INSTANTIATE(float, float)
230 INSTANTIATE(float, int)
231 INSTANTIATE(float, std::uint16_t)
232 INSTANTIATE(int, int)
233 INSTANTIATE(std::uint16_t, std::uint16_t)
Convolution support.
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
An include file to include the header files for lsst::afw::geom.
Declare the Kernel class and subclasses.
lsst::afw::geom::Box2I getBBox() const
Definition: Convolve.h:157
geom::Extent2I const getDimensions() const
Return the Kernel&#39;s dimensions (width, height)
Definition: Kernel.h:223
#define LOGL_DEBUG(logger, message...)
Definition: Log.h:513
void convolveRegionWithInterpolation(OutImageT &outImage, InImageT const &inImage, KernelImagesForRegion const &region, ConvolveWithInterpolationWorkingImages &workingImages)
Convolve a region of an Image or MaskedImage with a spatially varying Kernel using interpolation...
Parameters to control convolution.
Definition: ConvolveImage.h:58
#define CONST_PTR(...)
Definition: base.h:47
#define INSTANTIATE(T)
An integer coordinate rectangle.
Definition: Box.h:53
kernel images used by convolveRegionWithInterpolation
Definition: Convolve.h:265
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
int getMinY() const
Definition: Box.h:125
void assign(ImageBase const &rsh, geom::Box2I const &bbox=geom::Box2I(), ImageOrigin origin=PARENT)
Definition: Image.cc:242
int getMinX() const
Definition: Box.h:124
A row of KernelImagesForRegion.
Definition: Convolve.h:204
void convolveWithInterpolation(OutImageT &outImage, InImageT const &inImage, lsst::afw::math::Kernel const &kernel, ConvolutionControl const &convolutionControl)
Convolve an Image or MaskedImage with a spatially varying Kernel using linear interpolation.
virtual boost::shared_ptr< Kernel > clone() const =0
Return a pointer to a deep copy of this kernel.
int getWidth() const
Definition: Box.h:154
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
int getHeight() const
Definition: Box.h:155
xy_locator xy_at(int x, int y) const
Definition: Image.h:353
Implementation of the Class MaskedImage.
Include files required for standard LSST Exception handling.
bool computeNextRow(RowOfKernelImagesForRegion &regionRow) const
Compute next row of subregions.
Kernels are used for convolution with MaskedImages and (eventually) Images.
Definition: Kernel.h:131
lsst::afw::geom::Box2I shrinkBBox(lsst::afw::geom::Box2I const &bbox) const
Definition: Kernel.cc:207