lsst.afw  22.0.1-31-gd62ef0f05+23bd69c089
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 
25 /*
26  * Definition of convolveWithInterpolation and helper functions declared in detail/ConvolveImage.h
27  */
28 #include <algorithm>
29 #include <cmath>
30 #include <cstdint>
31 #include <sstream>
32 #include <vector>
33 #include <iostream>
34 
35 #include "lsst/pex/exceptions.h"
36 #include "lsst/log/Log.h"
37 #include "lsst/geom.h"
39 #include "lsst/afw/math/Kernel.h"
41 
43 
44 namespace lsst {
45 namespace afw {
46 namespace math {
47 namespace detail {
48 
49 template <typename OutImageT, typename InImageT>
50 void convolveWithInterpolation(OutImageT &outImage, InImageT const &inImage, math::Kernel const &kernel,
51  math::ConvolutionControl const &convolutionControl) {
52  if (outImage.getDimensions() != inImage.getDimensions()) {
54  os << "outImage dimensions = ( " << outImage.getWidth() << ", " << outImage.getHeight() << ") != ("
55  << inImage.getWidth() << ", " << inImage.getHeight() << ") = inImage dimensions";
57  }
58 
59  // compute region covering good area of output image
61  lsst::geom::Point2I(0, 0), lsst::geom::Extent2I(outImage.getWidth(), outImage.getHeight()));
62  lsst::geom::Box2I goodBBox = kernel.shrinkBBox(fullBBox);
63  KernelImagesForRegion goodRegion(KernelImagesForRegion(kernel.clone(), goodBBox, inImage.getXY0(),
64  convolutionControl.getDoNormalize()));
65  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
66  "convolveWithInterpolation: full bbox minimum=(%d, %d), extent=(%d, %d)", fullBBox.getMinX(),
67  fullBBox.getMinY(), fullBBox.getWidth(), fullBBox.getHeight());
68  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
69  "convolveWithInterpolation: goodRegion bbox minimum=(%d, %d), extent=(%d, %d)",
70  goodRegion.getBBox().getMinX(), goodRegion.getBBox().getMinY(),
71  goodRegion.getBBox().getWidth(), goodRegion.getBBox().getHeight());
72 
73  // divide good region into subregions small enough to interpolate over
74  int nx = 1 + (goodBBox.getWidth() / convolutionControl.getMaxInterpolationDistance());
75  int ny = 1 + (goodBBox.getHeight() / convolutionControl.getMaxInterpolationDistance());
76  LOGL_DEBUG("TRACE3.afw.math.convolve.convolveWithInterpolation",
77  "convolveWithInterpolation: divide into %d x %d subregions", nx, ny);
78 
80  RowOfKernelImagesForRegion regionRow(nx, ny);
81  while (goodRegion.computeNextRow(regionRow)) {
82  for (auto const &rgnIter : regionRow) {
83  LOGL_DEBUG("TRACE5.afw.math.convolve.convolveWithInterpolation",
84  "convolveWithInterpolation: bbox minimum=(%d, %d), extent=(%d, %d)",
85  rgnIter->getBBox().getMinX(), rgnIter->getBBox().getMinY(),
86  rgnIter->getBBox().getWidth(), rgnIter->getBBox().getHeight());
87  convolveRegionWithInterpolation(outImage, inImage, *rgnIter, workingImages);
88  }
89  }
90 }
91 
92 template <typename OutImageT, typename InImageT>
93 void convolveRegionWithInterpolation(OutImageT &outImage, InImageT const &inImage,
94  KernelImagesForRegion const &region,
96  using OutLocator = typename OutImageT::xy_locator;
97  using InConstLocator = typename InImageT::const_xy_locator;
98  using KernelImage = KernelImagesForRegion::Image;
99  using KernelConstLocator = KernelImage::const_xy_locator;
100 
101  std::shared_ptr<Kernel const> kernelPtr = region.getKernel();
102  lsst::geom::Extent2I const kernelDimensions(kernelPtr->getDimensions());
105  workingImages.kernelImage.assign(workingImages.leftImage);
106 
107  lsst::geom::Box2I const goodBBox = region.getBBox();
108  lsst::geom::Box2I const fullBBox = kernelPtr->growBBox(goodBBox);
109 
110  // top and right images are computed one beyond bbox boundary,
111  // so the distance between edge images is bbox width/height pixels
112  double xfrac = 1.0 / static_cast<double>(goodBBox.getWidth());
113  double yfrac = 1.0 / static_cast<double>(goodBBox.getHeight());
115  -yfrac, workingImages.leftImage);
117  -yfrac, workingImages.rightImage);
118 
119  KernelConstLocator const kernelLocator = workingImages.kernelImage.xy_at(0, 0);
120 
121  // The loop is a bit odd for efficiency: the initial value of workingImages.kernelImage
122  // and related kernel images are set when they are allocated,
123  // so they are not computed in the loop until after the convolution; to save cpu cycles
124  // they are not computed at all for the last iteration.
125  InConstLocator inLocator = inImage.xy_at(fullBBox.getMinX(), fullBBox.getMinY());
126  OutLocator outLocator = outImage.xy_at(goodBBox.getMinX(), goodBBox.getMinY());
127  for (int j = 0;;) {
128  auto inLocatorInitialPosition = inLocator;
129  auto outLocatorInitialPosition = outLocator;
130  math::scaledPlus(workingImages.deltaImage, xfrac, workingImages.rightImage, -xfrac,
131  workingImages.leftImage);
132  for (int i = 0;;) {
133  *outLocator = math::convolveAtAPoint<OutImageT, InImageT>(
134  inLocator, kernelLocator, kernelDimensions.getX(), kernelDimensions.getY());
135  ++outLocator.x();
136  ++inLocator.x();
137  ++i;
138  if (i >= goodBBox.getWidth()) {
139  break;
140  }
141  workingImages.kernelImage += workingImages.deltaImage;
142  }
143 
144  ++j;
145  if (j >= goodBBox.getHeight()) {
146  break;
147  }
148  workingImages.leftImage += workingImages.leftDeltaImage;
149  workingImages.rightImage += workingImages.rightDeltaImage;
150  workingImages.kernelImage.assign(workingImages.leftImage);
151 
152  // Workaround for DM-5822
153  // Boost GIL locator won't decrement in x-dimension for some strange and still
154  // not understood reason. So instead store position at start of previous row,
155  // reset and move down.
156  inLocator = inLocatorInitialPosition;
157  outLocator = outLocatorInitialPosition;
158  ++inLocator.y();
159  ++outLocator.y();
160  }
161 }
162 
163 /*
164  * Explicit instantiation
165  */
167 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
168 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
169 #define NL /* */
170 // Instantiate Image or MaskedImage versions
171 #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \
172  template void convolveWithInterpolation(IMGMACRO(OUTPIXTYPE) &, IMGMACRO(INPIXTYPE) const &, \
173  math::Kernel const &, math::ConvolutionControl const &); \
174  NL template void convolveRegionWithInterpolation(IMGMACRO(OUTPIXTYPE) &, IMGMACRO(INPIXTYPE) const &, \
175  KernelImagesForRegion const &, \
176  ConvolveWithInterpolationWorkingImages &);
177 // Instantiate both Image and MaskedImage versions
178 #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \
179  INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \
180  INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE)
181 
182 INSTANTIATE(double, double)
183 INSTANTIATE(double, float)
184 INSTANTIATE(double, int)
185 INSTANTIATE(double, std::uint16_t)
186 INSTANTIATE(float, float)
187 INSTANTIATE(float, int)
189 INSTANTIATE(int, int)
192 } // namespace detail
193 } // namespace math
194 } // namespace afw
195 } // namespace lsst
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
#define LSST_EXCEPT(type,...)
#define LOGL_DEBUG(logger, message...)
std::ostream * os
Definition: Schema.cc:558
xy_locator xy_at(int x, int y) const
Return an xy_locator at the point (x, y) in the image.
Definition: ImageBase.h:425
void assign(ImageBase const &rhs, lsst::geom::Box2I const &bbox=lsst::geom::Box2I(), ImageOrigin origin=PARENT)
Copy pixels from another image to a specified subregion of this image.
Definition: Image.cc:165
Parameters to control convolution.
Definition: ConvolveImage.h:50
Kernels are used for convolution with MaskedImages and (eventually) Images.
Definition: Kernel.h:111
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
Definition: Kernel.h:213
virtual std::shared_ptr< Kernel > clone() const =0
Return a pointer to a deep copy of this kernel.
lsst::geom::Box2I shrinkBBox(lsst::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:182
A collection of Kernel images for special locations on a rectangular region of an image.
Definition: Convolve.h:172
KernelConstPtr getKernel() const
Get the kernel (as a shared pointer to const)
Definition: Convolve.h:254
bool computeNextRow(RowOfKernelImagesForRegion &regionRow) const
Compute next row of subregions.
ImagePtr getImage(Location location) const
Return the image and sum at the specified location.
lsst::geom::Box2I getBBox() const
Get the bounding box for the region.
Definition: Convolve.h:234
lsst::afw::image::Image< lsst::afw::math::Kernel::Pixel > Image
Definition: Convolve.h:175
int getMinY() const noexcept
int getHeight() const noexcept
int getMinX() const noexcept
int getWidth() const noexcept
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.
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.
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
A base class for image defects.
kernel images used by convolveRegionWithInterpolation
Definition: Convolve.h:418