LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
saturated.cc
Go to the documentation of this file.
1 
6 #include "boost/format.hpp"
7 #include "lsst/utils/ieee.h"
8 #include "lsst/afw/detection.h"
10 #include "Rgb.h"
11 
12 namespace lsst { namespace afw { namespace display {
13 
14 namespace {
15  template <typename ImageT>
16  class SetPixels : public detection::FootprintFunctor<ImageT> {
17  public:
18  explicit SetPixels(ImageT const& img // The image the source lives in
19  ) : detection::FootprintFunctor<ImageT>(img), _value(0) {}
20 
21  void setValue(float value) { _value = value; }
22 
23  // method called for each pixel by apply()
24  void operator()(typename ImageT::xy_locator loc, // locator pointing at the pixel
25  int, // column-position of pixel
26  int // row-position of pixel
27  ) {
28  *loc = _value;
29  }
30  private:
31  float _value;
32  };
33 }
34 
35 template<typename ImageT>
36 void
37 replaceSaturatedPixels(ImageT & rim, // R image (e.g. i)
38  ImageT & gim, // G image (e.g. r)
39  ImageT & bim, // B image (e.g. g)
40  int borderWidth, // width of border used to estimate colour of saturated regions
41  float saturatedPixelValue // the brightness of a saturated pixel, once fixed
42  )
43 {
44  int const width = rim.getWidth(), height = rim.getHeight();
45  int const x0 = rim.getX0(), y0 = rim.getY0();
46 
47  if (width != gim.getWidth() || height != gim.getHeight() || x0 != gim.getX0() || y0 != gim.getY0()) {
48  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
49  str(boost::format("R image has different size/origin from G image "
50  "(%dx%d+%d+%d v. %dx%d+%d+%d") %
51  width % height % x0 % y0 %
52  gim.getWidth() % gim.getHeight() % gim.getX0() % gim.getY0()));
53 
54  }
55  if (width != bim.getWidth() || height != bim.getHeight() || x0 != bim.getX0() || y0 != bim.getY0()) {
56  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
57  str(boost::format("R image has different size/origin from B image "
58  "(%dx%d+%d+%d v. %dx%d+%d+%d") %
59  width % height % x0 % y0 %
60  bim.getWidth() % bim.getHeight() % bim.getX0() % bim.getY0()));
61 
62  }
63 
64  bool const useMaxPixel = !utils::isfinite(saturatedPixelValue);
65 
66  SetPixels<typename ImageT::Image>
67  setR(*rim.getImage()),
68  setG(*gim.getImage()),
69  setB(*bim.getImage()); // functors used to set pixel values
70 
71  // Find all the saturated pixels in any of the three image
72  int const npixMin = 1; // minimum number of pixels in an object
73  afw::image::MaskPixel const SAT = rim.getMask()->getPlaneBitMask("SAT");
75 
76  detection::FootprintSet sat(*rim.getMask(), satThresh, npixMin);
77  sat.merge(detection::FootprintSet(*gim.getMask(), satThresh, npixMin));
78  sat.merge(detection::FootprintSet(*bim.getMask(), satThresh, npixMin));
79  // go through the list of saturated regions, determining the mean colour of the surrounding pixels
81  PTR(FootprintList) feet = sat.getFootprints();
82  for (FootprintList::const_iterator ptr = feet->begin(), end = feet->end(); ptr != end; ++ptr) {
83  PTR(detection::Footprint) const foot = *ptr;
84  PTR(detection::Footprint) const bigFoot = growFootprint(*foot, borderWidth);
85 
86  double sumR = 0, sumG = 0, sumB = 0; // sum of all non-saturated adjoining pixels
87  double maxR = 0, maxG = 0, maxB = 0; // maximum of non-saturated adjoining pixels
88 
89  for (detection::Footprint::SpanList::const_iterator sptr = bigFoot->getSpans().begin(),
90  send = bigFoot->getSpans().end(); sptr != send; ++sptr) {
91  PTR(detection::Span) const span = *sptr;
92 
93  int const y = span->getY() - y0;
94  if (y < 0 || y >= height) {
95  continue;
96  }
97  int sx0 = span->getX0() - x0;
98  if (sx0 < 0) {
99  sx0 = 0;
100  }
101  int sx1 = span->getX1() - x0;
102  if (sx1 >= width) {
103  sx1 = width - 1;
104  }
105 
106  for (typename ImageT::iterator
107  rptr = rim.at(sx0, y),
108  rend = rim.at(sx1 + 1, y),
109  gptr = gim.at(sx0, y),
110  bptr = bim.at(sx0, y); rptr != rend; ++rptr, ++gptr, ++bptr) {
111  if (!((rptr.mask() | gptr.mask() | bptr.mask()) & SAT)) {
112  float val = rptr.image();
113  sumR += val;
114  if (val > maxR) {
115  maxR = val;
116  }
117 
118  val = gptr.image();
119  sumG += val;
120  if (val > maxG) {
121  maxG = val;
122  }
123 
124  val = bptr.image();
125  sumB += val;
126  if (val > maxB) {
127  maxB = val;
128  }
129  }
130  }
131  }
132  // OK, we have the mean fluxes for the pixels surrounding this set of saturated pixels
133  // so we can figure out the proper values to use for the saturated ones
134  float R = 0, G = 0, B = 0; // mean intensities
135  if (sumR + sumB + sumG > 0) {
136  if (sumR > sumG) {
137  if (sumR > sumB) {
138  R = useMaxPixel ? maxR : saturatedPixelValue;
139 
140  G = (R*sumG)/sumR;
141  B = (R*sumB)/sumR;
142  } else {
143  B = useMaxPixel ? maxB : saturatedPixelValue;
144  R = (B*sumR)/sumB;
145  G = (B*sumG)/sumB;
146  }
147  } else {
148  if (sumG > sumB) {
149  G = useMaxPixel ? maxG : saturatedPixelValue;
150  R = (G*sumR)/sumG;
151  B = (G*sumB)/sumG;
152  } else {
153  B = useMaxPixel ? maxB : saturatedPixelValue;
154  R = (B*sumR)/sumB;
155  G = (B*sumG)/sumB;
156  }
157  }
158  }
159  // Now that we know R, G, and B we can fix the values
160  setR.setValue(R); setR.apply(*foot);
161  setG.setValue(G); setG.apply(*foot);
162  setB.setValue(B); setB.apply(*foot);
163  }
164 }
165 
166 template
167 void
171  int borderWidth,
172  float saturatedPixelValue
173  );
174 
175 }}}
int y
for(FootprintList::const_iterator ptr=feet->begin(), end=feet->end();ptr!=end;++ptr)
Definition: saturated.cc:82
boost::shared_ptr< FootprintList > feet
Definition: saturated.cc:81
boost::uint16_t MaskPixel
float _value
Definition: saturated.cc:31
#define PTR(...)
Definition: base.h:41
Use (pixels &amp; (given mask))
Definition: Threshold.h:49
A Threshold is used to pass a threshold value to detection algorithms.
Definition: Threshold.h:44
int const x0
Definition: saturated.cc:45
bool val
boost::shared_ptr< Footprint > growFootprint(Footprint const &foot, int nGrow, bool isotropic=true)
void ImageT ImageT int float saturatedPixelValue int const width
Definition: saturated.cc:44
An include file to include the header files for lsst::afw::detection.
afw::image::MaskPixel const SAT
Definition: saturated.cc:73
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:77
detection::FootprintSet::FootprintList FootprintList
Definition: saturated.cc:80
A set of pixels in an Image.
Definition: Footprint.h:62
int isfinite(T t)
Definition: ieee.h:100
void ImageT ImageT int float saturatedPixelValue int const height
Definition: saturated.cc:44
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
std::vector< Footprint::Ptr > FootprintList
The FootprintSet&#39;s set of Footprints.
Definition: FootprintSet.h:57
A set of Footprints, associated with a MaskedImage.
Definition: FootprintSet.h:53
void ImageT & gim
Definition: Rgb.h:9
void ImageT ImageT int float saturatedPixelValue
Definition: Rgb.h:12
void ImageT ImageT & bim
Definition: Rgb.h:9
detection::Threshold const satThresh(SAT, detection::Threshold::BITMASK)
bool const useMaxPixel
Definition: saturated.cc:64
Implementation of the Class MaskedImage.
int const npixMin
Definition: saturated.cc:72
template void replaceSaturatedPixels(image::MaskedImage< float > &rim, image::MaskedImage< float > &gim, image::MaskedImage< float > &bim, int borderWidth, float saturatedPixelValue)
int const y0
Definition: saturated.cc:45
A functor class to allow users to process all the pixels in a Footprint.
SetPixels< typename ImageT::Image > setR * rim()), setG(*gim.getImage()), setB(*bim.getImage()
void ImageT ImageT int borderWidth
Definition: Rgb.h:11
void merge(FootprintSet const &rhs, int tGrow=0, int rGrow=0, bool isotropic=true)