LSST Applications g0b6bd0c080+a72a5dd7e6,g1182afd7b4+2a019aa3bb,g17e5ecfddb+2b8207f7de,g1d67935e3f+06cf436103,g38293774b4+ac198e9f13,g396055baef+6a2097e274,g3b44f30a73+6611e0205b,g480783c3b1+98f8679e14,g48ccf36440+89c08d0516,g4b93dc025c+98f8679e14,g5c4744a4d9+a302e8c7f0,g613e996a0d+e1c447f2e0,g6c8d09e9e7+25247a063c,g7271f0639c+98f8679e14,g7a9cd813b8+124095ede6,g9d27549199+a302e8c7f0,ga1cf026fa3+ac198e9f13,ga32aa97882+7403ac30ac,ga786bb30fb+7a139211af,gaa63f70f4e+9994eb9896,gabf319e997+ade567573c,gba47b54d5d+94dc90c3ea,gbec6a3398f+06cf436103,gc6308e37c7+07dd123edb,gc655b1545f+ade567573c,gcc9029db3c+ab229f5caf,gd01420fc67+06cf436103,gd877ba84e5+06cf436103,gdb4cecd868+6f279b5b48,ge2d134c3d5+cc4dbb2e3f,ge448b5faa6+86d1ceac1d,gecc7e12556+98f8679e14,gf3ee170dca+25247a063c,gf4ac96e456+ade567573c,gf9f5ea5b4d+ac198e9f13,gff490e6085+8c2580be5c,w.2022.27
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"
37
39
40namespace lsst {
41namespace afw {
42namespace math {
43
44namespace {
45
58template <typename OutImageT, typename InImageT>
59inline 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
109template <typename OutImageT, typename InImageT>
110inline 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
152template <typename OutImageT, typename InImageT>
153void 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
180template <typename OutImageT, typename InImageT, typename KernelT>
181void 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
189template <typename OutImageT, typename InImageT, typename KernelT>
190void 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//
250INSTANTIATE(double, double)
251INSTANTIATE(double, float)
252INSTANTIATE(double, int)
254INSTANTIATE(float, float)
255INSTANTIATE(float, int)
257INSTANTIATE(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:412
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