LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
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 <cstdint>
29 #include <iostream>
30 #include <vector>
31 #include <string>
32 
33 #include "lsst/pex/exceptions.h"
35 #include "lsst/afw/math/Kernel.h"
37 
39 
40 namespace lsst {
41 namespace afw {
42 namespace math {
43 
44 namespace {
45 
58 template <typename OutImageT, typename InImageT>
59 inline void setEdgePixels(OutImageT& outImage, Kernel const& kernel, InImageT const& inImage, bool doCopyEdge,
60  image::detail::Image_tag) {
61  const unsigned int imWidth = outImage.getWidth();
62  const unsigned int imHeight = outImage.getHeight();
63  const unsigned int kWidth = kernel.getWidth();
64  const unsigned int kHeight = kernel.getHeight();
65  const unsigned int kCtrX = kernel.getCtr().getX();
66  const unsigned int kCtrY = kernel.getCtr().getY();
67 
68  const typename OutImageT::SinglePixel edgePixel =
69  math::edgePixel<OutImageT>(typename image::detail::image_traits<OutImageT>::image_category());
71 
72  // create a list of bounding boxes describing edge regions, in this order:
73  // bottom edge, top edge (both edge to edge),
74  // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
75  int const numHeight = kHeight - (1 + kCtrY);
76  int const numWidth = kWidth - (1 + kCtrX);
77  bboxList.emplace_back(lsst::geom::Point2I(0, 0), lsst::geom::Extent2I(imWidth, kCtrY));
78  bboxList.emplace_back(lsst::geom::Point2I(0, imHeight - numHeight),
79  lsst::geom::Extent2I(imWidth, numHeight));
80  bboxList.emplace_back(lsst::geom::Point2I(0, kCtrY),
81  lsst::geom::Extent2I(kCtrX, imHeight + 1 - kHeight));
82  bboxList.emplace_back(lsst::geom::Point2I(imWidth - numWidth, kCtrY),
83  lsst::geom::Extent2I(numWidth, imHeight + 1 - kHeight));
84 
85  for (auto const &bboxIter : bboxList) {
86  OutImageT outView(outImage, bboxIter, image::LOCAL);
87  if (doCopyEdge) {
88  // note: set only works with data of the same type
89  // so convert the input image to output format
90  outView.assign(OutImageT(InImageT(inImage, bboxIter, image::LOCAL), true));
91  } else {
92  outView = edgePixel;
93  }
94  }
95 }
96 
109 template <typename OutImageT, typename InImageT>
110 inline void setEdgePixels(OutImageT& outImage, Kernel const& kernel, InImageT const& inImage, bool doCopyEdge,
111  image::detail::MaskedImage_tag) {
112  const unsigned int imWidth = outImage.getWidth();
113  const unsigned int imHeight = outImage.getHeight();
114  const unsigned int kWidth = kernel.getWidth();
115  const unsigned int kHeight = kernel.getHeight();
116  const unsigned int kCtrX = kernel.getCtr().getX();
117  const unsigned int kCtrY = kernel.getCtr().getY();
118 
119  const typename OutImageT::SinglePixel edgePixel =
120  math::edgePixel<OutImageT>(typename image::detail::image_traits<OutImageT>::image_category());
122 
123  // create a list of bounding boxes describing edge regions, in this order:
124  // bottom edge, top edge (both edge to edge),
125  // left edge, right edge (both omitting pixels already in the bottom and top edge regions)
126  int const numHeight = kHeight - (1 + kCtrY);
127  int const numWidth = kWidth - (1 + kCtrX);
128  bboxList.emplace_back(lsst::geom::Point2I(0, 0), lsst::geom::Extent2I(imWidth, kCtrY));
129  bboxList.emplace_back(lsst::geom::Point2I(0, imHeight - numHeight),
130  lsst::geom::Extent2I(imWidth, numHeight));
131  bboxList.emplace_back(lsst::geom::Point2I(0, kCtrY),
132  lsst::geom::Extent2I(kCtrX, imHeight + 1 - kHeight));
133  bboxList.emplace_back(lsst::geom::Point2I(imWidth - numWidth, kCtrY),
134  lsst::geom::Extent2I(numWidth, imHeight + 1 - kHeight));
135 
137  for (auto const &bboxIter : bboxList) {
138  OutImageT outView(outImage, bboxIter, image::LOCAL);
139  if (doCopyEdge) {
140  // note: set only works with data of the same type
141  // so convert the input image to output format
142  outView.assign(OutImageT(InImageT(inImage, bboxIter, image::LOCAL), true));
143  *(outView.getMask()) |= edgeMask;
144  } else {
145  outView = edgePixel;
146  }
147  }
148 }
149 
150 } // anonymous namespace
151 
152 template <typename OutImageT, typename InImageT>
153 void scaledPlus(OutImageT& outImage, double c1, InImageT const& inImage1, double c2,
154  InImageT const& inImage2) {
155  if (outImage.getDimensions() != inImage1.getDimensions()) {
157  os << "outImage dimensions = ( " << outImage.getWidth() << ", " << outImage.getHeight() << ") != ("
158  << inImage1.getWidth() << ", " << inImage1.getHeight() << ") = inImage1 dimensions";
160  } else if (inImage1.getDimensions() != inImage2.getDimensions()) {
162  os << "inImage1 dimensions = ( " << inImage1.getWidth() << ", " << inImage1.getHeight() << ") != ("
163  << inImage2.getWidth() << ", " << inImage2.getHeight() << ") = inImage2 dimensions";
165  }
166 
167  using InConstXIter = typename InImageT::const_x_iterator;
168  using OutXIter = typename OutImageT::x_iterator;
169  for (int y = 0; y != inImage1.getHeight(); ++y) {
170  InConstXIter const end1 = inImage1.row_end(y);
171  InConstXIter inIter1 = inImage1.row_begin(y);
172  InConstXIter inIter2 = inImage2.row_begin(y);
173  OutXIter outIter = outImage.row_begin(y);
174  for (; inIter1 != end1; ++inIter1, ++inIter2, ++outIter) {
175  *outIter = (*inIter1 * c1) + (*inIter2 * c2);
176  }
177  }
178 }
179 
180 template <typename OutImageT, typename InImageT, typename KernelT>
181 void convolve(OutImageT& convolvedImage, InImageT const& inImage, KernelT const& kernel,
182  ConvolutionControl const& convolutionControl) {
183  detail::basicConvolve(convolvedImage, inImage, kernel, convolutionControl);
184  setEdgePixels(convolvedImage, kernel, inImage, convolutionControl.getDoCopyEdge(),
186  convolvedImage.setXY0(inImage.getXY0());
187 }
188 
189 template <typename OutImageT, typename InImageT, typename KernelT>
190 void convolve(OutImageT& convolvedImage, InImageT const& inImage, KernelT const& kernel, bool doNormalize,
191  bool doCopyEdge) {
192  ConvolutionControl convolutionControl;
193  convolutionControl.setDoNormalize(doNormalize);
194  convolutionControl.setDoCopyEdge(doCopyEdge);
195  convolve(convolvedImage, inImage, kernel, convolutionControl);
196 }
197 
199 /*
200  * Explicit instantiation of all convolve functions.
201  *
202  * This code needs to be compiled with full optimization, and there's no reason why
203  * it should be instantiated in the swig wrappers.
204  */
205 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
206 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
207 //
208 // Next a macro to generate needed instantiations for IMGMACRO (either IMAGE or MASKEDIMAGE)
209 // and the specified pixel types
210 //
211 /* NL's a newline for debugging -- don't define it and say
212  g++ -C -E -I$(eups list -s -d boost)/include Convolve.cc | perl -pe 's| *NL *|\n|g'
213 */
214 #define NL /* */
215 //
216 // Instantiate one kernel-specific specializations of convolution functions for Image or MaskedImage
217 // IMGMACRO = IMAGE or MASKEDIMAGE
218 // KERNELTYPE = a kernel class
219 //
220 #define INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, KERNELTYPE) \
221  template void convolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &, KERNELTYPE const&, bool, \
222  bool); \
223  NL template void convolve(IMGMACRO(OUTPIXTYPE)&, IMGMACRO(INPIXTYPE) const &, KERNELTYPE const&, \
224  ConvolutionControl const&); \
225  NL
226 //
227 // Instantiate Image or MaskedImage versions of all functions defined in this file.
228 // Call INSTANTIATE_IM_OR_MI_KERNEL once for each kernel class.
229 // IMGMACRO = IMAGE or MASKEDIMAGE
230 //
231 #define INSTANTIATE_IM_OR_MI(IMGMACRO, OUTPIXTYPE, INPIXTYPE) \
232  template void scaledPlus(IMGMACRO(OUTPIXTYPE)&, double, IMGMACRO(INPIXTYPE) const &, double, \
233  IMGMACRO(INPIXTYPE) const &); \
234  NL INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, \
235  AnalyticKernel) INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, \
236  INPIXTYPE, \
237  DeltaFunctionKernel) \
238  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, FixedKernel) \
239  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, LinearCombinationKernel) \
240  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, SeparableKernel) \
241  INSTANTIATE_IM_OR_MI_KERNEL(IMGMACRO, OUTPIXTYPE, INPIXTYPE, Kernel) //
242 // Instantiate all functions defined in this file for one specific output and input pixel type
243 //
244 #define INSTANTIATE(OUTPIXTYPE, INPIXTYPE) \
245  INSTANTIATE_IM_OR_MI(IMAGE, OUTPIXTYPE, INPIXTYPE) \
246  INSTANTIATE_IM_OR_MI(MASKEDIMAGE, OUTPIXTYPE, INPIXTYPE)
247 //
248 // Instantiate all functions defined in this file
249 //
250 INSTANTIATE(double, double)
251 INSTANTIATE(double, float)
252 INSTANTIATE(double, int)
253 INSTANTIATE(double, std::uint16_t)
254 INSTANTIATE(float, float)
255 INSTANTIATE(float, int)
257 INSTANTIATE(int, int)
260 } // namespace math
261 } // namespace afw
262 } // namespace lsst
#define INSTANTIATE(FROMSYS, TOSYS)
Definition: Detector.cc:484
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::ostream * os
Definition: Schema.cc:557
int y
Definition: SpanSet.cc:48
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:372
Parameters to control convolution.
Definition: ConvolveImage.h:50
void setDoCopyEdge(bool doCopyEdge)
Definition: ConvolveImage.h:67
void setDoNormalize(bool doNormalize)
Definition: ConvolveImage.h:66
Reports invalid arguments.
Definition: Runtime.h:66
T emplace_back(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.
typename ImageT::image_category image_category
Definition: ImageBase.h:67