LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
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)
Compute the scaled sum of two images.
An include file to include the header files for lsst::afw::geom.
Declare the Kernel class and subclasses.
geom::Extent2I const getDimensions() const
Return the Kernel&#39;s dimensions (width, height)
Definition: Kernel.h:223
bool computeNextRow(RowOfKernelImagesForRegion &regionRow) const
Compute next row of subregions.
int getMinY() const
Definition: Box.h:125
Include files required for standard LSST Exception handling.
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:57
#define INSTANTIATE(T)
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition: Log.h:513
An integer coordinate rectangle.
Definition: Box.h:53
kernel images used by convolveRegionWithInterpolation
Definition: Convolve.h:264
int getMinX() const
Definition: Box.h:124
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
LSST DM logging module built on log4cxx.
int getWidth() const
Definition: Box.h:154
KernelConstPtr getKernel() const
Get the kernel (as a shared pointer to const)
Definition: Convolve.h:169
void assign(ImageBase const &rsh, geom::Box2I const &bbox=geom::Box2I(), ImageOrigin origin=PARENT)
Copy pixels from another image to a specified subregion of this image.
Definition: Image.cc:242
lsst::afw::geom::Box2I getBBox() const
Get the bounding box for the region.
Definition: Convolve.h:156
A row of KernelImagesForRegion.
Definition: Convolve.h:203
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.
#define LSST_EXCEPT(type,...)
Create an exception with a given type and message and optionally other arguments (dependent on the ty...
Definition: Exception.h:46
ImagePtr getImage(Location location) const
Return the image and sum at the specified location.
int getHeight() const
Definition: Box.h:155
xy_locator xy_at(int x, int y) const
Return an xy_locator at the point (x, y) in the image.
Definition: Image.h:352
Implementation of the Class MaskedImage.
#define CONST_PTR(...)
A shared pointer to a const object.
Definition: base.h:47
Kernels are used for convolution with MaskedImages and (eventually) Images.
Definition: Kernel.h:131
A collection of Kernel images for special locations on a rectangular region of an image...
Definition: Convolve.h:109
lsst::afw::geom::Box2I shrinkBBox(lsst::afw::geom::Box2I const &bbox) const
Given a bounding box for an image one wishes to convolve with this kernel, return the bounding box fo...
Definition: Kernel.cc:207