LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
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:509
#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
Represent a 2-dimensional array of bitmask pixels.
Definition Mask.h:81
Parameters to control convolution.
void setDoCopyEdge(bool doCopyEdge)
void setDoNormalize(bool doNormalize)
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
typename ImageT::image_category image_category
Definition ImageBase.h:67