49 template<
typename dtype>
53 STATIC_ASSERT_ARITHMETIC(dtype);
69 uint8 inBorderWidth = 0) :
71 intensities_(inIntensityArrayPtr)
73 if (xcds_->
shape() != intensities_->shape())
78 shape_ = xcds_->
shape();
85 if (xcds_->operator()(row, col))
87 const Pixel<dtype> thePixel(row, col, intensities_->operator()(row, col));
88 xcdsVec_.push_back(thePixel);
95 for (
uint8 i = 0; i < inBorderWidth; ++i)
109 return static_cast<uint32>(clusters_.size());
122 return clusters_[inIndex];
135 if (inIndex >= clusters_.size())
139 return clusters_[inIndex];
150 return clusters_.cbegin();
161 return clusters_.cend();
168 std::vector<Pixel<dtype>> xcdsVec_{};
172 std::vector<Cluster<dtype>> clusters_{};
183 Pixel<dtype> makePixel(
int32 inRow,
int32 inCol)
noexcept
189 const dtype intensity = intensities_->operator()(row, col);
191 return Pixel<dtype>(row, col, intensity);
202 void findNeighbors(
const Pixel<dtype>& inPixel, std::set<Pixel<dtype>>& outNeighbors)
207 const auto row =
static_cast<int32>(inPixel.row);
208 const auto col =
static_cast<int32>(inPixel.col);
210 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col - 1));
211 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col));
212 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col + 1));
213 outNeighbors.insert(outNeighbors.end(), makePixel(row, col - 1));
214 outNeighbors.insert(outNeighbors.end(), makePixel(row, col + 1));
215 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col - 1));
216 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col));
217 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col + 1));
229 void findNeighborNotXcds(
const Pixel<dtype>& inPixel, std::vector<Pixel<dtype>>& outNeighbors)
231 std::set<Pixel<dtype>> neighbors;
232 findNeighbors(inPixel, neighbors);
235 for (
auto& pixel : neighbors)
237 if (!xcds_->operator()(pixel.row, pixel.col))
239 outNeighbors.push_back(pixel);
253 void findNeighborXcds(
const Pixel<dtype>& inPixel, std::vector<uint32>& outNeighbors)
255 std::set<Pixel<dtype>> neighbors;
256 findNeighbors(inPixel, neighbors);
257 std::vector<Pixel<dtype>> neighborXcds;
260 for (
auto& pixel : neighbors)
262 if (xcds_->operator()(pixel.row, pixel.col))
264 neighborXcds.push_back(pixel);
269 for (
auto& pixel : neighborXcds)
271 auto theExceedanceIter =
std::find(xcdsVec_.begin(), xcdsVec_.end(), pixel);
272 outNeighbors.push_back(
static_cast<uint32>(theExceedanceIter - xcdsVec_.begin()));
280 void runClusterMaker()
284 for (
auto& currentPixel : xcdsVec_)
287 if (currentPixel.clusterId == -1)
289 Cluster<dtype> newCluster(clusterId);
290 currentPixel.clusterId = clusterId;
291 newCluster.addPixel(currentPixel);
294 std::vector<uint32> neighborIds;
295 findNeighborXcds(currentPixel, neighborIds);
296 if (neighborIds.empty())
298 clusters_.push_back(newCluster);
304 for (
uint32 neighborsIdx = 0; neighborsIdx < neighborIds.size(); ++neighborsIdx)
306 Pixel<dtype>& currentNeighborPixel = xcdsVec_[neighborIds[neighborsIdx]];
309 std::vector<uint32> newNeighborIds;
310 findNeighborXcds(currentNeighborPixel, newNeighborIds);
313 for (
auto newNeighborId : newNeighborIds)
316 if (
std::find(neighborIds.begin(), neighborIds.end(), newNeighborId) == neighborIds.end())
318 neighborIds.push_back(newNeighborId);
323 if (currentNeighborPixel.clusterId == -1)
325 currentNeighborPixel.clusterId = clusterId;
326 newCluster.addPixel(currentNeighborPixel);
330 clusters_.push_back(std::move(newCluster));
340 void expandClusters()
343 for (
auto& theCluster : clusters_)
346 for (
auto& thePixel : theCluster)
348 std::vector<Pixel<dtype>> neighborsNotXcds;
349 findNeighborNotXcds(thePixel, neighborsNotXcds);
352 for (
auto& newPixel : neighborsNotXcds)
354 if (
std::find(theCluster.begin(), theCluster.end(), newPixel) == theCluster.end())
356 theCluster.addPixel(newPixel);
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4511
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
Holds the information for a cluster of pixels.
Definition: Cluster.hpp:53
Clusters exceedance data into contiguous groups.
Definition: ClusterMaker.hpp:51
ClusterMaker(const NdArray< bool > *const inXcdArrayPtr, const NdArray< dtype > *const inIntensityArrayPtr, uint8 inBorderWidth=0)
Definition: ClusterMaker.hpp:67
const_iterator begin() const noexcept
Definition: ClusterMaker.hpp:148
const_iterator end() const noexcept
Definition: ClusterMaker.hpp:159
typename std::vector< Cluster< dtype > >::const_iterator const_iterator
Definition: ClusterMaker.hpp:57
const Cluster< dtype > & at(uint32 inIndex) const
Definition: ClusterMaker.hpp:133
const Cluster< dtype > & operator[](uint32 inIndex) const noexcept
Definition: ClusterMaker.hpp:120
uint32 size() noexcept
Definition: ClusterMaker.hpp:107
Holds the information for a single pixel.
Definition: Pixel.hpp:46
Definition: applyThreshold.hpp:34
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:205
NdArray< dtype > min(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: min.hpp:44
std::int32_t int32
Definition: Types.hpp:36
std::uint8_t uint8
Definition: Types.hpp:42
std::uint32_t uint32
Definition: Types.hpp:40