LSST Applications  21.0.0+c4f5df5339,21.0.0+e70536a077,21.0.0-1-ga51b5d4+7c60f8a6ea,21.0.0-10-gcf60f90+74aa0801fd,21.0.0-12-g63909ac9+643a1044a5,21.0.0-15-gedb9d5423+1041c3824f,21.0.0-2-g103fe59+a356b2badb,21.0.0-2-g1367e85+6d3f3f41db,21.0.0-2-g45278ab+e70536a077,21.0.0-2-g5242d73+6d3f3f41db,21.0.0-2-g7f82c8f+8d7c04eab9,21.0.0-2-g8f08a60+9c9a9cfcc8,21.0.0-2-ga326454+8d7c04eab9,21.0.0-2-gde069b7+bedfc5e1fb,21.0.0-2-gecfae73+6cb6558258,21.0.0-2-gfc62afb+6d3f3f41db,21.0.0-3-g21c7a62+f6e98b25aa,21.0.0-3-g357aad2+bd62456bea,21.0.0-3-g4be5c26+6d3f3f41db,21.0.0-3-g65f322c+03a4076c01,21.0.0-3-g7d9da8d+c4f5df5339,21.0.0-3-gaa929c8+c6b98066dc,21.0.0-3-gc44e71e+a26d5c1aea,21.0.0-3-ge02ed75+04b527a9d5,21.0.0-35-g64f566ff+b27e5ef93e,21.0.0-4-g591bb35+04b527a9d5,21.0.0-4-g88306b8+8773047b2e,21.0.0-4-gc004bbf+80a0b7acb7,21.0.0-4-gccdca77+a5c54364a0,21.0.0-4-ge8fba5a+ccfc328107,21.0.0-5-gdf36809+87b8d260e6,21.0.0-6-g00874e7+7eeda2b6ba,21.0.0-6-g2d4f3f3+e70536a077,21.0.0-6-g4e60332+04b527a9d5,21.0.0-6-g5ef7dad+f53629abd8,21.0.0-7-gc8ca178+b63e69433b,21.0.0-8-gfbe0b4b+c6b98066dc,w.2021.06
LSST Data Management Base Package
ConvolveImage.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 functions declared in ConvolveImage.h
27  */
28 #include <algorithm>
29 #include <cmath>
30 #include <cstdint>
31 #include <functional>
32 #include <iostream>
33 #include <sstream>
34 #include <limits>
35 #include <vector>
36 #include <string>
37 
38 #include "lsst/pex/exceptions.h"
39 #include "lsst/log/Log.h"
42 #include "lsst/afw/math/Kernel.h"
44 
46 
47 namespace lsst {
48 namespace afw {
49 namespace math {
50 
51 namespace {
52 
65 template <typename OutImageT, typename InImageT>
66 inline void setEdgePixels(OutImageT& outImage, Kernel const& kernel, InImageT const& inImage, bool doCopyEdge,
67  image::detail::Image_tag) {
68  const unsigned int imWidth = outImage.getWidth();
69  const unsigned int imHeight = outImage.getHeight();
70  const unsigned int kWidth = kernel.getWidth();
71  const unsigned int kHeight = kernel.getHeight();
72  const unsigned int kCtrX = kernel.getCtr().getX();
73  const unsigned int kCtrY = kernel.getCtr().getY();
74 
75  const typename OutImageT::SinglePixel edgePixel =
76  math::edgePixel<OutImageT>(typename image::detail::image_traits<OutImageT>::image_category());
78 
79  // create a list of bounding boxes describing edge regions, in this order:
80  // bottom edge, top edge (both edge to edge),
81  // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
82  int const numHeight = kHeight - (1 + kCtrY);
83  int const numWidth = kWidth - (1 + kCtrX);
84  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(0, 0), lsst::geom::Extent2I(imWidth, kCtrY)));
85  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(0, imHeight - numHeight),
86  lsst::geom::Extent2I(imWidth, numHeight)));
88  lsst::geom::Extent2I(kCtrX, imHeight + 1 - kHeight)));
89  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(imWidth - numWidth, kCtrY),
90  lsst::geom::Extent2I(numWidth, imHeight + 1 - kHeight)));
91 
92  for (std::vector<lsst::geom::Box2I>::const_iterator bboxIter = bboxList.begin();
93  bboxIter != bboxList.end(); ++bboxIter) {
94  OutImageT outView(outImage, *bboxIter, image::LOCAL);
95  if (doCopyEdge) {
96  // note: set only works with data of the same type
97  // so convert the input image to output format
98  outView.assign(OutImageT(InImageT(inImage, *bboxIter, image::LOCAL), true));
99  } else {
100  outView = edgePixel;
101  }
102  }
103 }
104 
117 template <typename OutImageT, typename InImageT>
118 inline void setEdgePixels(OutImageT& outImage, Kernel const& kernel, InImageT const& inImage, bool doCopyEdge,
119  image::detail::MaskedImage_tag) {
120  const unsigned int imWidth = outImage.getWidth();
121  const unsigned int imHeight = outImage.getHeight();
122  const unsigned int kWidth = kernel.getWidth();
123  const unsigned int kHeight = kernel.getHeight();
124  const unsigned int kCtrX = kernel.getCtr().getX();
125  const unsigned int kCtrY = kernel.getCtr().getY();
126 
127  const typename OutImageT::SinglePixel edgePixel =
128  math::edgePixel<OutImageT>(typename image::detail::image_traits<OutImageT>::image_category());
130 
131  // create a list of bounding boxes describing edge regions, in this order:
132  // bottom edge, top edge (both edge to edge),
133  // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
134  int const numHeight = kHeight - (1 + kCtrY);
135  int const numWidth = kWidth - (1 + kCtrX);
136  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(0, 0), lsst::geom::Extent2I(imWidth, kCtrY)));
137  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(0, imHeight - numHeight),
138  lsst::geom::Extent2I(imWidth, numHeight)));
140  lsst::geom::Extent2I(kCtrX, imHeight + 1 - kHeight)));
141  bboxList.push_back(lsst::geom::Box2I(lsst::geom::Point2I(imWidth - numWidth, kCtrY),
142  lsst::geom::Extent2I(numWidth, imHeight + 1 - kHeight)));
143 
145  for (std::vector<lsst::geom::Box2I>::const_iterator bboxIter = bboxList.begin();
146  bboxIter != bboxList.end(); ++bboxIter) {
147  OutImageT outView(outImage, *bboxIter, image::LOCAL);
148  if (doCopyEdge) {
149  // note: set only works with data of the same type
150  // so convert the input image to output format
151  outView.assign(OutImageT(InImageT(inImage, *bboxIter, image::LOCAL), true));
152  *(outView.getMask()) |= edgeMask;
153  } else {
154  outView = edgePixel;
155  }
156  }
157 }
158 
159 } // anonymous namespace
160 
161 template <typename OutImageT, typename InImageT>
162 void scaledPlus(OutImageT& outImage, double c1, InImageT const& inImage1, double c2,
163  InImageT const& inImage2) {
164  if (outImage.getDimensions() != inImage1.getDimensions()) {
166  os << "outImage dimensions = ( " << outImage.getWidth() << ", " << outImage.getHeight() << ") != ("
167  << inImage1.getWidth() << ", " << inImage1.getHeight() << ") = inImage1 dimensions";
169  } else if (inImage1.getDimensions() != inImage2.getDimensions()) {
171  os << "inImage1 dimensions = ( " << inImage1.getWidth() << ", " << inImage1.getHeight() << ") != ("
172  << inImage2.getWidth() << ", " << inImage2.getHeight() << ") = inImage2 dimensions";
174  }
175 
176  typedef typename InImageT::const_x_iterator InConstXIter;
177  typedef typename OutImageT::x_iterator OutXIter;
178  for (int y = 0; y != inImage1.getHeight(); ++y) {
179  InConstXIter const end1 = inImage1.row_end(y);
180  InConstXIter inIter1 = inImage1.row_begin(y);
181  InConstXIter inIter2 = inImage2.row_begin(y);
182  OutXIter outIter = outImage.row_begin(y);
183  for (; inIter1 != end1; ++inIter1, ++inIter2, ++outIter) {
184  *outIter = (*inIter1 * c1) + (*inIter2 * c2);
185  }
186  }
187 }
188 
189 template <typename OutImageT, typename InImageT, typename KernelT>
190 void convolve(OutImageT& convolvedImage, InImageT const& inImage, KernelT const& kernel,
191  ConvolutionControl const& convolutionControl) {
192  detail::basicConvolve(convolvedImage, inImage, kernel, convolutionControl);
193  setEdgePixels(convolvedImage, kernel, inImage, convolutionControl.getDoCopyEdge(),
195  convolvedImage.setXY0(inImage.getXY0());
196 }
197 
198 template <typename OutImageT, typename InImageT, typename KernelT>
199 void convolve(OutImageT& convolvedImage, InImageT const& inImage, KernelT const& kernel, bool doNormalize,
200  bool doCopyEdge) {
201  ConvolutionControl convolutionControl;
202  convolutionControl.setDoNormalize(doNormalize);
203  convolutionControl.setDoCopyEdge(doCopyEdge);
204  convolve(convolvedImage, inImage, kernel, convolutionControl);
205 }
206 
208 /*
209  * Explicit instantiation of all convolve functions.
210  *
211  * This code needs to be compiled with full optimization, and there's no reason why
212  * it should be instantiated in the swig wrappers.
213  */
214 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
215 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
216 //
217 // Next a macro to generate needed instantiations for IMGMACRO (either IMAGE or MASKEDIMAGE)
218 // and the specified pixel types
219 //
220 /* NL's a newline for debugging -- don't define it and say
221  g++ -C -E -I$(eups list -s -d boost)/include Convolve.cc | perl -pe 's| *NL *|\n|g'
222 */
223 #define NL /* */
224 //
225 // Instantiate one kernel-specific specializations of convolution functions for Image or MaskedImage
226 // IMGMACRO = IMAGE or MASKEDIMAGE
227 // KERNELTYPE = a kernel class
228 //
229 #define INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, KERNELTYPE) \
230  template void convolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &, KERNELTYPE const&, bool, \
231  bool); \
232  NL template void convolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &, KERNELTYPE const&, \
233  ConvolutionControl const&); \
234  NL
235 //
236 // Instantiate Image or MaskedImage versions of all functions defined in this file.
237 // Call INSTANTIATE_IM_OR_MI_KERNEL once for each kernel class.
238 // IMGMACRO = IMAGE or MASKEDIMAGE
239 //
240 #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \
241  template void scaledPlus(IMGMACRO(OUTPIXTYPE)&, double, IMGMACRO(INPIXTYPE) const &, double, \
242  IMGMACRO(INPIXTYPE) const &); \
243  NL INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, \
244  AnalyticKernel) INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, \
245  INPIXTYPE, \
246  DeltaFunctionKernel) \
247  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, FixedKernel) \
248  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, LinearCombinationKernel) \
249  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, SeparableKernel) \
250  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, Kernel) //
251 // Instantiate all functions defined in this file for one specific output and input pixel type
252 //
253 #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \
254  INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \
255  INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE)
256 //
257 // Instantiate all functions defined in this file
258 //
259 INSTANTIATE(double, double)
260 INSTANTIATE(double, float)
261 INSTANTIATE(double, int)
262 INSTANTIATE(double, std::uint16_t)
263 INSTANTIATE(float, float)
264 INSTANTIATE(float, int)
266 INSTANTIATE(int, int)
269 } // namespace math
270 } // namespace afw
271 } // namespace lsst
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
LSST DM logging module built on log4cxx.
std::ostream * os
Definition: Schema.cc:746
T begin(T... args)
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR'd together.
Definition: Mask.cc:379
Parameters to control convolution.
Definition: ConvolveImage.h:50
void setDoCopyEdge(bool doCopyEdge)
Definition: ConvolveImage.h:67
void setDoNormalize(bool doNormalize)
Definition: ConvolveImage.h:66
An integer coordinate rectangle.
Definition: Box.h:55
Reports invalid arguments.
Definition: Runtime.h:66
T end(T... args)
void basicConvolve(OutImageT &convolvedImage, InImageT const &inImage, lsst::afw::math::Kernel const &kernel, lsst::afw::math::ConvolutionControl const &convolutionControl)
Low-level convolution function that does not set edge pixels.
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
Compute the scaled sum of two images.
void convolve(OutImageT &convolvedImage, InImageT const &inImage, KernelT const &kernel, ConvolutionControl const &convolutionControl=ConvolutionControl())
Convolve an Image or MaskedImage with a Kernel, setting pixels of an existing output image.
ImageT::SinglePixel edgePixel(lsst::afw::image::detail::Image_tag)
Return an off-the-edge pixel appropriate for a given Image type.
Extent< int, 2 > Extent2I
Definition: Extent.h:397
A base class for image defects.
T push_back(T... args)
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
int y
Definition: SpanSet.cc:49
ImageT::image_category image_category
Definition: ImageBase.h:67