// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include #include "ImageSpotFinder.h" #include "SpotFindingSettings.h" #include "../../common/AzimuthalIntegrationMapping.h" #include "../../common/DiffractionSpot.h" // This is "slow" spot finder for image-based analysis // To complement "fast" PSI detector module based spot finder // This one is expected to be used in cases, where images are already assembled // and it aims for 100 ms execution class ImageSpotFinderCPU : public ImageSpotFinder { // Output of the first pass, and the exclusion mask for the second. std::vector first_pass_buffer; // One detection pass. prev_strong is the previous pass's bitmap, or nullptr for the first pass; // a pixel set in it is treated as INT32_MAX, i.e. kept out of every local background it would // fall into, and reported strong. // // With candidates set (SNR test only), the window sums of every candidate pixel are also recorded // in candidate_windows, in pixel order, and fill_row (see DetectAt) is called. void DetectPass(const ImagePreprocessorBuffer &image, const SpotFindingSettings &settings, const uint32_t *prev_strong, std::vector &out, const uint32_t *candidates = nullptr, const std::function &fill_row = {}); // Local-box sums (centre pixel included) of one candidate pixel, as the first pass saw them. struct CandidateWindow { int32_t pxl; int64_t sum, sum2, valid; }; std::vector candidate_windows; // Where the first pass's own result is read by DetectAt - within NBX of a candidate - per row and // 32-column block. Elsewhere that pass keeps its sums but skips the test. std::vector first_pass_needed; protected: // Detect, but with the result wanted only at the candidate pixels (packed like output_buffer): // output_buffer ends up holding (Detect's result & candidates). The second pass is not run over // the image: a candidate's second-pass window is its first-pass window with the pixels the first // pass found strong taken out, and those are few, so they are subtracted from the sums the first // pass recorded. Integer sums and the same test, so the bits are exactly Detect's. // // fill_row(row), when given, sets the candidates of that row: it is called once for every row, in // order, before any candidate of the row is read, when the pass is about to read the row anyway. void DetectAt(const ImagePreprocessorBuffer &image, const SpotFindingSettings &settings, const std::vector &candidates, const std::function &fill_row = {}); public: ImageSpotFinderCPU(int32_t width, int32_t height); void Detect(const ImagePreprocessorBuffer &image, const SpotFindingSettings &settings) override; };