24#include <boost/random.hpp>
46 boost::random::mt19937 rng { ((
unsigned int)
time(NULL)) };
84 return total_intensity;
94 if (parent !=
nullptr) {
95 parent->flagAsSplit();
136 auto parent_source_id = original_source->getProperty<
SourceId>().getSourceId();
138 auto& detection_frame = original_source->getProperty<
DetectionFrame>();
141 const auto labelling_image = detection_frame_images.getLockedImage(
LayerFilteredImage);
143 auto& pixel_boundaries = original_source->getProperty<
PixelBoundaries>();
145 auto& pixel_coords = original_source->getProperty<
PixelCoordinateList>().getCoordinateList();
147 auto offset = pixel_boundaries.getMin();
149 pixel_boundaries.getWidth(), pixel_boundaries.getHeight());
150 thumbnail_image->fillValue(0);
152 auto min_value = original_source->getProperty<
PeakValue>().getMinValue() * .8;
153 auto peak_value = original_source->getProperty<
PeakValue>().getMaxValue();
155 for (
auto pixel_coord : pixel_coords) {
156 auto value = labelling_image->getValue(pixel_coord);
157 thumbnail_image->setValue(pixel_coord - offset, value);
160 auto root = std::make_shared<MultiThresholdNode>(pixel_coords, 0);
168 auto threshold = min_value *
pow(peak_value / min_value, (
double) i /
m_thresholds_nb);
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++;
183 if (nb_of_groups_inside == 0) {
184 active_nodes.remove(node);
187 if (nb_of_groups_inside > 1) {
188 active_nodes.remove(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);
202 double intensity_threshold = root->getTotalIntensity(*thumbnail_image, offset) *
m_contrast;
205 while (!junction_nodes.
empty()) {
206 auto node = junction_nodes.
back();
209 int nb_of_children_above_threshold = 0;
211 for (
auto child : node->getChildren()) {
212 if (child->getTotalIntensity(*thumbnail_image, offset) > intensity_threshold) {
213 nb_of_children_above_threshold++;
217 if (nb_of_children_above_threshold >= 2) {
219 for (
auto child : node->getChildren()) {
220 if (child->getTotalIntensity(*thumbnail_image, offset) > intensity_threshold && !child->isSplit()) {
228 if (source_nodes.
empty()) {
233 for (
auto source_node : source_nodes) {
235 for (
auto& pixel : source_node->getPixels()) {
236 thumbnail_image->setValue(pixel - offset, 0);
242 new_source->setProperty<
DetectionFrame>(detection_frame.getEncapsulatedFrame());
247 auto new_sources =
reassignPixels(sources, pixel_coords, thumbnail_image, source_nodes, offset);
249 for (
auto& new_source : new_sources) {
250 new_source->setProperty<
DetectionFrame>(detection_frame.getEncapsulatedFrame());
251 new_source->setProperty<
SourceId>(parent_source_id);
266 for (
auto& source : sources) {
270 auto thresh = source->getProperty<
PeakValue>().getMinValue();
271 auto peak = source->getProperty<
PeakValue>().getMaxValue();
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;
277 if (amp > 4.0 * peak) {
284 for (
auto pixel : pixel_coords) {
285 if (image->getValue(pixel - offset) > 0) {
286 SeFloat cumulated_probability = 0;
293 for (
auto& source : sources) {
297 auto dx = pixel.m_x - pixel_centroid.getCentroidX();
298 auto dy = pixel.m_y - pixel_centroid.getCentroidY();
300 auto dist = 0.5 * (shape_parameters.getEllipseCxx()*
dx*
dx +
301 shape_parameters.getEllipseCyy()*
dy*
dy + shape_parameters.getEllipseCxy()*
dx*
dy) /
304 if (dist < min_dist) {
306 closest_source_node = source_nodes[i];
309 cumulated_probability += dist < 70.0 ? amplitudes[i] * expf(-dist) : 0.0;
311 probabilities.
push_back(cumulated_probability);
315 if (probabilities.
back() > 1.0e-31) {
316 auto drand = double(probabilities.
back()) * boost::random::uniform_01<double>()(rng);
319 for (; i<probabilities.
size() && drand >= probabilities[i]; i++);
320 if (i < source_nodes.size()) {
321 source_nodes[i]->addPixel(pixel);
328 closest_source_node->addPixel(pixel);
333 int total_pixels = 0;
336 for (
auto source_node : source_nodes) {
338 for (
auto& pixel : source_node->getPixels()) {
339 image->setValue(pixel - offset, 0);
344 auto pixels = source_node->getPixels();
345 total_pixels += pixels.size();
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) {}
std::shared_ptr< SourceFactory > m_source_factory
std::shared_ptr< EngineParameter > dx
std::shared_ptr< EngineParameter > dy
T emplace_back(T... args)
T shared_from_this(T... args)