LSST Applications g042eb84c57+730a74494b,g04e9c324dd+8c5ae1fdc5,g134cb467dc+1f1e3e7524,g199a45376c+0ba108daf9,g1fd858c14a+fa7d31856b,g210f2d0738+f66ac109ec,g262e1987ae+83a3acc0e5,g29ae962dfc+d856a2cb1f,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+a1e0c9f713,g47891489e3+0d594cb711,g4d44eb3520+c57ec8f3ed,g4d7b6aa1c5+f66ac109ec,g53246c7159+8c5ae1fdc5,g56a1a4eaf3+fd7ad03fde,g64539dfbff+f66ac109ec,g67b6fd64d1+0d594cb711,g67fd3c3899+f66ac109ec,g6985122a63+0d594cb711,g74acd417e5+3098891321,g786e29fd12+668abc6043,g81db2e9a8d+98e2ab9f28,g87389fa792+8856018cbb,g89139ef638+0d594cb711,g8d7436a09f+80fda9ce03,g8ea07a8fe4+760ca7c3fc,g90f42f885a+033b1d468d,g97be763408+a8a29bda4b,g99822b682c+e3ec3c61f9,g9d5c6a246b+0d5dac0c3d,ga41d0fce20+9243b26dd2,gbf99507273+8c5ae1fdc5,gd7ef33dd92+0d594cb711,gdab6d2f7ff+3098891321,ge410e46f29+0d594cb711,geaed405ab2+c4bbc419c6,gf9a733ac38+8c5ae1fdc5,w.2025.38
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
38namespace pexExcept = lsst::pex::exceptions;
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,
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 =
70 std::vector<lsst::geom::Box2I> bboxList;
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,
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 =
121 std::vector<lsst::geom::Box2I> bboxList;
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";
159 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
160 } else if (inImage1.getDimensions() != inImage2.getDimensions()) {
162 os << "inImage1 dimensions = ( " << inImage1.getWidth() << ", " << inImage1.getHeight() << ") != ("
163 << inImage2.getWidth() << ", " << inImage2.getHeight() << ") = inImage2 dimensions";
164 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
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
Represent a 2-dimensional array of bitmask pixels.
Definition Mask.h:82
Parameters to control convolution.
void setDoCopyEdge(bool doCopyEdge)
void setDoNormalize(bool doNormalize)
Kernels are used for convolution with MaskedImages and (eventually) Images.
Definition Kernel.h:110
T emplace_back(T... args)
std::int32_t MaskPixel
default type for Masks and MaskedImage Masks
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
Point< int, 2 > Point2I
Definition Point.h:321
T str(T... args)
A traits class for MaskedImage.
Definition MaskedImage.h:51
typename ImageT::image_category image_category
Definition ImageBase.h:67