SourceXtractorPlusPlus 1.0.3
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
SEBackgroundLevelAnalyzer.cpp
Go to the documentation of this file.
1
17
19
29
30namespace SourceXtractor {
31
33 const std::vector<int>& smoothing_box,
34 const WeightImageConfig::WeightType weight_type)
35 : m_weight_type(weight_type) {
36 assert(cell_size.size() > 0 && cell_size.size() < 3);
37 assert(smoothing_box.size() > 0 && smoothing_box.size() < 3);
38 m_cell_size[0] = cell_size.front();
39 m_cell_size[1] = cell_size.back();
40 m_smoothing_box[0] = smoothing_box.front();
41 m_smoothing_box[1] = smoothing_box.back();
42}
43
46 std::vector<float> ratios;
47 ratios.reserve(variance->getWidth() * variance->getHeight());
48
49 for (int y = 0; y < variance->getHeight(); ++y) {
50 for (int x = 0; x < variance->getWidth(); ++x) {
51 auto w = weight->getValue(x, y);
52 if (w > 0) {
53 auto v = variance->getValue(x, y);
54 auto ratio = (v * v) / w;
55 if (ratio > 0) {
56 ratios.emplace_back(ratio);
57 }
58 }
59 }
60 }
61
62 std::sort(ratios.begin(), ratios.end());
63 if (ratios.size() % 2 == 1) {
64 return ratios[ratios.size() / 2];
65 }
66 return (ratios[ratios.size() / 2] + ratios[ratios.size() / 2 - 1]) / 2;
67}
68
70 auto v = img.getData();
71 std::sort(v.begin(), v.end());
72 auto nitems = v.size();
73 if (nitems % 2 == 1) {
74 return v[nitems / 2];
75 }
76 return (v[nitems / 2] + v[nitems / 2 - 1]) / 2;
77}
78
81 std::shared_ptr<Image<unsigned char>> mask, WeightImage::PixelType variance_threshold) const {
82
84
85 if (mask != nullptr) {
86 bck_model_logger.debug() << "\tMask image with size: (" << mask->getWidth() << "," << mask->getHeight() << ")";
87
88 // make sure the dimensions are the same
89 if (image->getWidth() != mask->getWidth())
90 throw Elements::Exception() << "X-dims do not match: image=" << image->getWidth() << " mask=" << mask->getWidth();
91 if (image->getHeight() != mask->getHeight())
92 throw Elements::Exception() << "Y-dims do not match: image=" << image->getHeight() << " mask="
93 << mask->getHeight();
94
95 image = MaskedImage<DetectionImage::PixelType, uint8_t>::create(image, mask, mask_value);
96 }
97
98 if (variance_map != nullptr) {
99 bck_model_logger.debug() << "\tVariance image with size: (" << variance_map->getWidth() << ","
100 << variance_map->getHeight() << ")";
101 // make sure the dimensions are the same
102 if (image->getWidth() != variance_map->getWidth())
103 throw Elements::Exception() << "X-dims do not match: image=" << image->getWidth() << " variance="
104 << variance_map->getWidth();
105 if (image->getHeight() != variance_map->getHeight())
106 throw Elements::Exception() << "Y-dims do not match: image=" << image->getHeight() << " variance="
107 << variance_map->getHeight();
108
109 // Anything above the threshold is masked out
111 image, variance_map, mask_value, variance_threshold);
113 variance_map, variance_map, mask_value, variance_threshold);
114 }
115
116 // Create histogram model for the image
117 ImageMode<DetectionImage::PixelType> histo(image, variance_map, m_cell_size[0], m_cell_size[1], mask_value, 2, 5, 3);
118 auto mode = histo.getModeImage();
119 auto var = histo.getSigmaImage();
120
121 // Interpolate missing values
122 // The result is "materialized" into a VectorImage to avoid redundant computations on the next steps
123 mode = ReplaceUndef<DetectionImage::PixelType>(*mode, mask_value);
124 var = ReplaceUndef<WeightImage::PixelType>(*var, mask_value);
125
126 // Smooth with the smooth_box (median filtering)
128 auto median = getMedian(*mode);
129 auto median_sigma = getMedian(*var);
130
131 SeFloat scaling = 99999;
132
134
135 if (variance_map) {
136 // Create histogram model for the variance image
137 auto weight = histo.getVarianceModeImage();
138 auto weight_var = histo.getVarianceSigmaImage();
139 // Interpolate missing values
140 weight = ReplaceUndef<DetectionImage::PixelType>(*weight, mask_value);
141 // Smooth with the smooth_box (median filtering)
142 std::tie(weight, weight_var) = MedianFilter<WeightImage::PixelType>(m_smoothing_box)(*weight, *weight_var);
143 // Compute scaling
144 scaling = computeScaling(var, weight);
145 // Transform RMS to variance
149 final_var, image->getWidth(), image->getHeight(),
151 )
152 );
153 }
154 else {
155 final_var = ConstantImage<DetectionImage::PixelType>::create(image->getWidth(), image->getHeight(),
156 median_sigma * median_sigma);
157 }
158
159 bck_model_logger.info() << "Background for image: " << image->getRepr() << " median: " << median
160 << " rms: " << median_sigma << "!";
161
164 mode, image->getWidth(), image->getHeight(),
166 )
167 );
168
169 return BackgroundModel(final_bg, final_var, scaling, median_sigma);
170}
171
172} // end of namespace SourceXtractor
T back(T... args)
T begin(T... args)
static std::shared_ptr< BufferedImage< T > > create(std::shared_ptr< const ImageSource > source, std::shared_ptr< TileManager > tile_manager=TileManager::getInstance())
static std::shared_ptr< ConstantImage< T > > create(int width, int height, T constant_value)
std::shared_ptr< VectorImage< T > > getVarianceSigmaImage() const
Definition ImageMode.cpp:84
std::shared_ptr< VectorImage< T > > getVarianceModeImage() const
Definition ImageMode.cpp:79
std::shared_ptr< VectorImage< T > > getSigmaImage() const
Definition ImageMode.cpp:74
std::shared_ptr< VectorImage< T > > getModeImage() const
Definition ImageMode.cpp:69
Interface representing an image.
Definition Image.h:44
static std::shared_ptr< MaskedImage< T, M, Operator > > create(const std::shared_ptr< Image< T > > &image, const std::shared_ptr< Image< M > > &mask, T replacement, M mask_flag=0x01)
Definition MaskedImage.h:78
static std::shared_ptr< ProcessedImage< T, MultiplyOperation< T > > > create(std::shared_ptr< const Image< T > > image_a, std::shared_ptr< const Image< T > > image_b)
SEBackgroundLevelAnalyzer(const std::vector< int > &cell_size, const std::vector< int > &smoothing_box, const WeightImageConfig::WeightType weight_type)
BackgroundModel analyzeBackground(std::shared_ptr< DetectionImage > image, std::shared_ptr< WeightImage > variance_map, std::shared_ptr< Image< unsigned char > > mask, WeightImage::PixelType variance_threshold) const override
Image implementation which keeps the pixel values in memory.
Definition VectorImage.h:52
const std::vector< T > & getData() const
T emplace_back(T... args)
T end(T... args)
T front(T... args)
T lowest(T... args)
T make_shared(T... args)
static float getMedian(const VectorImage< DetectionImage::PixelType > &img)
SeFloat32 SeFloat
Definition Types.h:32
static Elements::Logging bck_model_logger
Definition Utils.h:25
std::shared_ptr< VectorImage< T > > ReplaceUndef(const VectorImage< T > &original, T mask)
static float computeScaling(const std::shared_ptr< VectorImage< DetectionImage::PixelType > > &variance, const std::shared_ptr< VectorImage< WeightImage::PixelType > > &weight)
T reserve(T... args)
T size(T... args)
T sort(T... args)
T tie(T... args)