SourceXtractorPlusPlus
0.21
SourceXtractor++, the next generation SExtractor
Loading...
Searching...
No Matches
SEImplementation
src
lib
Partition
MultiThresholdPartitionStep.cpp
Go to the documentation of this file.
1
17
/*
18
* MultiThresholdPartitionStep.cpp
19
*
20
* Created on: Jan 17, 2017
21
* Author: mschefer
22
*/
23
24
#include <boost/random.hpp>
25
26
#include "
SEImplementation/Measurement/MultithreadedMeasurement.h
"
27
#include "
SEImplementation/Partition/MultiThresholdPartitionStep.h
"
28
29
#include "
SEFramework/Image/VectorImage.h
"
30
#include "
SEFramework/Image/ProcessedImage.h
"
31
32
#include "
SEImplementation/Plugin/DetectionFramePixelValues/DetectionFramePixelValues.h
"
33
#include "
SEImplementation/Plugin/PixelBoundaries/PixelBoundaries.h
"
34
#include "
SEImplementation/Plugin/ShapeParameters/ShapeParameters.h
"
35
#include "
SEImplementation/Plugin/PixelCentroid/PixelCentroid.h
"
36
#include "
SEImplementation/Plugin/PeakValue/PeakValue.h
"
37
#include "
SEImplementation/Plugin/DetectionFrameImages/DetectionFrameImages.h
"
38
39
#include "
SEImplementation/Property/SourceId.h
"
40
41
#include "
SEImplementation/Segmentation/Lutz.h
"
42
43
namespace
SourceXtractor
{
44
45
namespace
{
46
boost::random::mt19937 rng { ((
unsigned
int)
time
(NULL)) };
47
}
48
49
class
MultiThresholdNode
:
public
std::enable_shared_from_this
<MultiThresholdNode> {
50
public
:
51
52
MultiThresholdNode
(
const
std::vector<PixelCoordinate>
& pixel_list,
SeFloat
threshold
)
53
:
m_pixel_list
(pixel_list),
m_is_split
(
false
),
m_threshold
(
threshold
) {
54
}
55
56
void
addChild
(
std::shared_ptr<MultiThresholdNode>
child
) {
57
m_children
.push_back(
child
);
58
child
->m_parent =
shared_from_this
();
59
}
60
61
bool
contains
(
const
Lutz::PixelGroup
&
pixel_group
)
const
{
62
for
(
auto
pixel
:
m_pixel_list
) {
63
if
(
pixel_group
.pixel_list[0] ==
pixel
) {
64
return
true
;
65
}
66
}
67
return
false
;
68
}
69
70
const
std::vector<std::shared_ptr<MultiThresholdNode>
>&
getChildren
()
const
{
71
return
m_children
;
72
}
73
74
std::shared_ptr<MultiThresholdNode>
getParent
()
const
{
75
return
m_parent
.lock();
76
}
77
78
double
getTotalIntensity
(
VectorImage<DetectionImage::PixelType>
&
image
,
const
PixelCoordinate
& offset)
const
{
79
DetectionImage::PixelType
total_intensity
= 0;
80
for
(
const
auto
&
pixel_coord
:
m_pixel_list
) {
81
total_intensity
+= (
image
.getValue(
pixel_coord
- offset) -
m_threshold
);
82
}
83
84
return
total_intensity
;
85
}
86
87
bool
isSplit
()
const
{
88
return
m_is_split
;
89
}
90
91
void
flagAsSplit
() {
92
m_is_split
=
true
;
93
auto
parent
=
m_parent
.lock();
94
if
(
parent
!=
nullptr
) {
95
parent
->flagAsSplit();
96
}
97
}
98
99
const
std::vector<PixelCoordinate>
&
getPixels
()
const
{
100
return
m_pixel_list
;
101
}
102
103
void
debugPrint
()
const
{
104
std::cout
<<
"("
<<
m_pixel_list
.size();
105
106
for
(
auto
&
child
:
m_children
) {
107
std::cout
<<
", "
;
108
child
->debugPrint();
109
}
110
111
std::cout
<<
")"
;
112
}
113
114
void
addPixel
(
PixelCoordinate
pixel
) {
115
m_pixel_list
.emplace_back(
pixel
);
116
}
117
118
SeFloat
getThreshold
()
const
{
119
return
m_threshold
;
120
}
121
122
private
:
123
std::vector<PixelCoordinate>
m_pixel_list
;
124
125
std::weak_ptr<MultiThresholdNode>
m_parent
;
126
std::vector<std::shared_ptr<MultiThresholdNode>
>
m_children
;
127
128
bool
m_is_split
;
129
130
SeFloat
m_threshold
;
131
};
132
133
std::vector<std::unique_ptr<SourceInterface>
>
MultiThresholdPartitionStep::partition
(
134
std::unique_ptr<SourceInterface>
original_source
)
const
{
135
136
auto
parent_source_id
=
original_source
->getProperty<
SourceId
>().getSourceId();
137
138
auto
&
detection_frame
=
original_source
->getProperty<
DetectionFrame
>();
139
140
auto
&
detection_frame_images
=
original_source
->getProperty<
DetectionFrameImages
>();
141
const
auto
labelling_image
=
detection_frame_images
.getLockedImage(
LayerFilteredImage
);
142
143
auto
&
pixel_boundaries
=
original_source
->getProperty<
PixelBoundaries
>();
144
145
auto
&
pixel_coords
=
original_source
->getProperty<
PixelCoordinateList
>().getCoordinateList();
146
147
auto
offset =
pixel_boundaries
.getMin();
148
auto
thumbnail_image
=
VectorImage<DetectionImage::PixelType>::create
(
149
pixel_boundaries
.getWidth(),
pixel_boundaries
.getHeight());
150
thumbnail_image
->fillValue(0);
151
152
auto
min_value
=
original_source
->getProperty<
PeakValue
>().getMinValue() * .8;
153
auto
peak_value
=
original_source
->getProperty<
PeakValue
>().getMaxValue();
154
155
for
(
auto
pixel_coord
:
pixel_coords
) {
156
auto
value =
labelling_image
->getValue(
pixel_coord
);
157
thumbnail_image
->setValue(
pixel_coord
- offset, value);
158
}
159
160
auto
root =
std::make_shared<MultiThresholdNode>
(
pixel_coords
, 0);
161
162
std::list<std::shared_ptr<MultiThresholdNode>
>
active_nodes
{ root };
163
std::list<std::shared_ptr<MultiThresholdNode>
>
junction_nodes
;
164
165
// Build the tree
166
for
(
unsigned
int
i
= 1;
i
<
m_thresholds_nb
;
i
++) {
167
168
auto
threshold
=
min_value
*
pow
(
peak_value
/
min_value
, (
double
)
i
/
m_thresholds_nb
);
169
auto
subtracted_image
=
SubtractImage<DetectionImage::PixelType>::create
(
thumbnail_image
,
threshold
);
170
171
LutzList
lutz
;
172
lutz
.labelImage(*
subtracted_image
, offset);
173
174
std::list<std::shared_ptr<MultiThresholdNode>
>
active_nodes_copy
(
active_nodes
);
175
for
(
auto
&
node
:
active_nodes_copy
) {
176
int
nb_of_groups_inside
= 0;
177
for
(
auto
&
pixel_group
:
lutz
.getGroups()) {
178
if
(
pixel_group
.pixel_list.size() >=
m_min_deblend_area
&&
node
->contains(
pixel_group
)) {
179
nb_of_groups_inside
++;
180
}
181
}
182
183
if
(
nb_of_groups_inside
== 0) {
184
active_nodes
.remove(
node
);
185
}
186
187
if
(
nb_of_groups_inside
> 1) {
188
active_nodes
.remove(
node
);
189
junction_nodes
.push_back(
node
);
190
for
(
auto
&
pixel_group
:
lutz
.getGroups()) {
191
if
(
pixel_group
.pixel_list.size() >=
m_min_deblend_area
&&
node
->contains(
pixel_group
)) {
192
auto
new_node
=
std::make_shared<MultiThresholdNode>
(
pixel_group
.pixel_list,
threshold
);
193
node
->addChild(
new_node
);
194
active_nodes
.push_back(
new_node
);
195
}
196
}
197
}
198
}
199
}
200
201
// Identify the sources
202
double
intensity_threshold
= root->getTotalIntensity(*
thumbnail_image
, offset) *
m_contrast
;
203
204
std::vector<std::shared_ptr<MultiThresholdNode>
>
source_nodes
;
205
while
(!
junction_nodes
.empty()) {
206
auto
node
=
junction_nodes
.back();
207
junction_nodes
.pop_back();
208
209
int
nb_of_children_above_threshold
= 0;
210
211
for
(
auto
child
:
node
->getChildren()) {
212
if
(
child
->getTotalIntensity(*
thumbnail_image
, offset) >
intensity_threshold
) {
213
nb_of_children_above_threshold
++;
214
}
215
}
216
217
if
(
nb_of_children_above_threshold
>= 2) {
218
node
->flagAsSplit();
219
for
(
auto
child
:
node
->getChildren()) {
220
if
(
child
->getTotalIntensity(*
thumbnail_image
, offset) >
intensity_threshold
&& !
child
->isSplit()) {
221
source_nodes
.push_back(
child
);
222
}
223
}
224
}
225
}
226
227
std::vector<std::unique_ptr<SourceInterface>
>
sources
;
228
if
(
source_nodes
.empty()) {
229
sources
.emplace_back(
std::move
(
original_source
));
// no split, just forward the source unchanged
230
return
sources
;
231
}
232
233
for
(
auto
source_node
:
source_nodes
) {
234
// remove pixels in the new sources from the image
235
for
(
auto
&
pixel
:
source_node
->getPixels()) {
236
thumbnail_image
->setValue(
pixel
- offset, 0);
237
}
238
239
auto
new_source
=
m_source_factory
->createSource();
240
241
new_source
->setProperty<
PixelCoordinateList
>(
source_node
->getPixels());
242
new_source
->setProperty<
DetectionFrame
>(
detection_frame
.getEncapsulatedFrame());
243
244
sources
.push_back(
std::move
(
new_source
));
245
}
246
247
auto
new_sources
=
reassignPixels
(
sources
,
pixel_coords
,
thumbnail_image
,
source_nodes
, offset);
248
249
for
(
auto
&
new_source
:
new_sources
) {
250
new_source
->setProperty<
DetectionFrame
>(
detection_frame
.getEncapsulatedFrame());
251
new_source
->setProperty<
SourceId
>(
parent_source_id
);
252
}
253
254
return
new_sources
;
255
}
256
257
std::vector<std::unique_ptr<SourceInterface>
>
MultiThresholdPartitionStep::reassignPixels
(
258
const
std::vector
<
std::unique_ptr<SourceInterface>
>&
sources
,
259
const
std::vector<PixelCoordinate>
&
pixel_coords
,
260
std::shared_ptr
<
VectorImage<DetectionImage::PixelType>
>
image
,
261
const
std::vector
<
std::shared_ptr<MultiThresholdNode>
>&
source_nodes
,
262
const
PixelCoordinate
& offset
263
)
const
{
264
265
std::vector<SeFloat>
amplitudes
;
266
for
(
auto
&
source
:
sources
) {
267
auto
& pixel_list =
source
->getProperty<
PixelCoordinateList
>().getCoordinateList();
268
auto
&
shape_parameters
=
source
->getProperty<
ShapeParameters
>();
269
270
auto
thresh
=
source
->getProperty<
PeakValue
>().getMinValue();
271
auto
peak
=
source
->getProperty<
PeakValue
>().getMaxValue();
272
273
auto
dist
= pixel_list.size() / (2.0 *
M_PI
*
shape_parameters
.getAbcor() *
shape_parameters
.getEllipseA() *
shape_parameters
.getEllipseB());
274
auto
amp
=
dist
< 70.0 ?
thresh
*
expf
(
dist
) : 4.0 *
peak
;
275
276
// limit expansion ??
277
if
(
amp
> 4.0 *
peak
) {
278
amp
= 4.0 *
peak
;
279
}
280
281
amplitudes
.push_back(
amp
);
282
}
283
284
for
(
auto
pixel
:
pixel_coords
) {
285
if
(
image
->getValue(
pixel
- offset) > 0) {
286
SeFloat
cumulated_probability
= 0;
287
std::vector<SeFloat>
probabilities;
288
289
SeFloat
min_dist
=
std::numeric_limits<SeFloat>::max
();
290
std::shared_ptr<MultiThresholdNode>
closest_source_node
;
291
292
int
i
= 0;
293
for
(
auto
&
source
:
sources
) {
294
auto
&
shape_parameters
=
source
->getProperty<
ShapeParameters
>();
295
auto
&
pixel_centroid
=
source
->getProperty<
PixelCentroid
>();
296
297
auto
dx
=
pixel
.m_x -
pixel_centroid
.getCentroidX();
298
auto
dy
=
pixel
.m_y -
pixel_centroid
.getCentroidY();
299
300
auto
dist
= 0.5 * (
shape_parameters
.getEllipseCxx()*
dx
*
dx
+
301
shape_parameters
.getEllipseCyy()*
dy
*
dy
+
shape_parameters
.getEllipseCxy()*
dx
*
dy
) /
302
shape_parameters
.getAbcor();
303
304
if
(
dist
<
min_dist
) {
305
min_dist
=
dist
;
306
closest_source_node
=
source_nodes
[
i
];
307
}
308
309
cumulated_probability
+=
dist
< 70.0 ?
amplitudes
[
i
] *
expf
(-
dist
) : 0.0;
310
311
probabilities.push_back(
cumulated_probability
);
312
i
++;
313
}
314
315
if
(probabilities.back() > 1.0e-31) {
316
auto
drand
=
double
(probabilities.back()) * boost::random::uniform_01<double>()(
rng
);
317
318
unsigned
int
i
=0;
319
for
(;
i
<probabilities.size() &&
drand
>= probabilities[
i
];
i
++);
320
if
(
i
<
source_nodes
.size()) {
321
source_nodes
[
i
]->addPixel(
pixel
);
322
}
else
{
323
std::cout
<<
i
<<
" oops "
<<
drand
<<
" "
<< probabilities.back() <<
std::endl
;
324
}
325
326
}
else
{
327
// select closest source
328
closest_source_node
->addPixel(
pixel
);
329
}
330
}
331
}
332
333
int
total_pixels
= 0;
334
335
std::vector<std::unique_ptr<SourceInterface>
>
new_sources
;
336
for
(
auto
source_node
:
source_nodes
) {
337
// remove pixels in the new sources from the image
338
for
(
auto
&
pixel
:
source_node
->getPixels()) {
339
image
->setValue(
pixel
- offset, 0);
340
}
341
342
auto
new_source
=
m_source_factory
->createSource();
343
344
auto
pixels
=
source_node
->getPixels();
345
total_pixels
+=
pixels
.size();
346
347
new_source
->setProperty<
PixelCoordinateList
>(
pixels
);
348
349
new_sources
.push_back(
std::move
(
new_source
));
350
}
351
352
return
new_sources
;
353
}
354
355
MultiThresholdPartitionStep::MultiThresholdPartitionStep
(
std::shared_ptr<SourceFactory>
source_factory,
SeFloat
contrast
,
356
unsigned
int
thresholds_nb
,
unsigned
int
min_deblend_area
) :
357
m_source_factory
(source_factory), m_contrast(
contrast
), m_thresholds_nb(
thresholds_nb
),
358
m_min_deblend_area(
min_deblend_area
) {}
359
360
}
// namespace
DetectionFrameImages.h
DetectionFramePixelValues.h
m_source_factory
std::shared_ptr< SourceFactory > m_source_factory
Definition
LutzSegmentation.cpp:69
Lutz.h
dx
std::shared_ptr< EngineParameter > dx
Definition
MoffatModelFittingTask.cpp:93
dy
std::shared_ptr< EngineParameter > dy
Definition
MoffatModelFittingTask.cpp:93
MultiThresholdPartitionStep.h
MultithreadedMeasurement.h
PeakValue.h
PixelBoundaries.h
PixelCentroid.h
ProcessedImage.h
ShapeParameters.h
SourceId.h
VectorImage.h
std::cout
SourceXtractor::DetectionFrameImages
Definition
DetectionFrameImages.h:30
SourceXtractor::DetectionFrame
Definition
DetectionFrame.h:33
SourceXtractor::LutzList
Definition
Lutz.h:65
SourceXtractor::Lutz::PixelGroup
Definition
Lutz.h:39
SourceXtractor::MultiThresholdNode
Definition
MultiThresholdPartitionStep.cpp:49
SourceXtractor::MultiThresholdNode::m_pixel_list
std::vector< PixelCoordinate > m_pixel_list
Definition
MultiThresholdPartitionStep.cpp:123
SourceXtractor::MultiThresholdNode::contains
bool contains(const Lutz::PixelGroup &pixel_group) const
Definition
MultiThresholdPartitionStep.cpp:61
SourceXtractor::MultiThresholdNode::getThreshold
SeFloat getThreshold() const
Definition
MultiThresholdPartitionStep.cpp:118
SourceXtractor::MultiThresholdNode::m_parent
std::weak_ptr< MultiThresholdNode > m_parent
Definition
MultiThresholdPartitionStep.cpp:125
SourceXtractor::MultiThresholdNode::addChild
void addChild(std::shared_ptr< MultiThresholdNode > child)
Definition
MultiThresholdPartitionStep.cpp:56
SourceXtractor::MultiThresholdNode::flagAsSplit
void flagAsSplit()
Definition
MultiThresholdPartitionStep.cpp:91
SourceXtractor::MultiThresholdNode::m_children
std::vector< std::shared_ptr< MultiThresholdNode > > m_children
Definition
MultiThresholdPartitionStep.cpp:126
SourceXtractor::MultiThresholdNode::MultiThresholdNode
MultiThresholdNode(const std::vector< PixelCoordinate > &pixel_list, SeFloat threshold)
Definition
MultiThresholdPartitionStep.cpp:52
SourceXtractor::MultiThresholdNode::m_is_split
bool m_is_split
Definition
MultiThresholdPartitionStep.cpp:128
SourceXtractor::MultiThresholdNode::debugPrint
void debugPrint() const
Definition
MultiThresholdPartitionStep.cpp:103
SourceXtractor::MultiThresholdNode::isSplit
bool isSplit() const
Definition
MultiThresholdPartitionStep.cpp:87
SourceXtractor::MultiThresholdNode::getChildren
const std::vector< std::shared_ptr< MultiThresholdNode > > & getChildren() const
Definition
MultiThresholdPartitionStep.cpp:70
SourceXtractor::MultiThresholdNode::getTotalIntensity
double getTotalIntensity(VectorImage< DetectionImage::PixelType > &image, const PixelCoordinate &offset) const
Definition
MultiThresholdPartitionStep.cpp:78
SourceXtractor::MultiThresholdNode::getParent
std::shared_ptr< MultiThresholdNode > getParent() const
Definition
MultiThresholdPartitionStep.cpp:74
SourceXtractor::MultiThresholdNode::addPixel
void addPixel(PixelCoordinate pixel)
Definition
MultiThresholdPartitionStep.cpp:114
SourceXtractor::MultiThresholdNode::m_threshold
SeFloat m_threshold
Definition
MultiThresholdPartitionStep.cpp:130
SourceXtractor::MultiThresholdNode::getPixels
const std::vector< PixelCoordinate > & getPixels() const
Definition
MultiThresholdPartitionStep.cpp:99
SourceXtractor::MultiThresholdPartitionStep::m_thresholds_nb
unsigned int m_thresholds_nb
Definition
MultiThresholdPartitionStep.h:68
SourceXtractor::MultiThresholdPartitionStep::m_contrast
SeFloat m_contrast
Definition
MultiThresholdPartitionStep.h:67
SourceXtractor::MultiThresholdPartitionStep::m_min_deblend_area
unsigned int m_min_deblend_area
Definition
MultiThresholdPartitionStep.h:69
SourceXtractor::MultiThresholdPartitionStep::reassignPixels
std::vector< std::unique_ptr< SourceInterface > > reassignPixels(const std::vector< std::unique_ptr< SourceInterface > > &sources, const std::vector< PixelCoordinate > &pixel_coords, std::shared_ptr< VectorImage< DetectionImage::PixelType > > image, const std::vector< std::shared_ptr< MultiThresholdNode > > &source_nodes, const PixelCoordinate &offset) const
Definition
MultiThresholdPartitionStep.cpp:257
SourceXtractor::MultiThresholdPartitionStep::partition
virtual std::vector< std::unique_ptr< SourceInterface > > partition(std::unique_ptr< SourceInterface > source) const
Definition
MultiThresholdPartitionStep.cpp:133
SourceXtractor::MultiThresholdPartitionStep::m_source_factory
std::shared_ptr< SourceFactory > m_source_factory
Definition
MultiThresholdPartitionStep.h:66
SourceXtractor::MultiThresholdPartitionStep::MultiThresholdPartitionStep
MultiThresholdPartitionStep(std::shared_ptr< SourceFactory > source_factory, SeFloat contrast, unsigned int thresholds_nb, unsigned int min_deblend_area)
Definition
MultiThresholdPartitionStep.cpp:355
SourceXtractor::PeakValue
Definition
PeakValue.h:32
SourceXtractor::PixelBoundaries
The bounding box of all the pixels in the source. Both min and max coordinate are inclusive.
Definition
PixelBoundaries.h:37
SourceXtractor::PixelCentroid
The centroid of all the pixels in the source, weighted by their DetectionImage pixel values.
Definition
PixelCentroid.h:37
SourceXtractor::PixelCoordinateList
Definition
PixelCoordinateList.h:33
SourceXtractor::ShapeParameters
Definition
ShapeParameters.h:32
SourceXtractor::SourceId
Definition
SourceId.h:32
SourceXtractor::VectorImage::create
static std::shared_ptr< VectorImage< T > > create(Args &&... args)
Definition
VectorImage.h:100
std::enable_shared_from_this
std::endl
T endl(T... args)
std::function
std::numeric_limits::max
T max(T... args)
std::move
T move(T... args)
SourceXtractor
Definition
Aperture.h:30
SourceXtractor::LayerFilteredImage
@ LayerFilteredImage
Definition
Frame.h:40
SourceXtractor::SeFloat
SeFloat32 SeFloat
Definition
Types.h:32
std::pow
T pow(T... args)
std::enable_shared_from_this< MultiThresholdNode >::shared_from_this
T shared_from_this(T... args)
std::shared_ptr
SourceXtractor::PixelCoordinate
A pixel coordinate made of two integers m_x and m_y.
Definition
PixelCoordinate.h:37
std::time
T time(T... args)
std::vector
Generated by
1.10.0