46 namespace imageProcessing
51 template<
typename dtype>
55 STATIC_ASSERT_ARITHMETIC(dtype);
73 uint8 inBorderWidth = 0) :
75 intensities_(inIntensityArrayPtr)
77 if (xcds_->
shape() != intensities_->shape())
82 shape_ = xcds_->
shape();
89 if (xcds_->operator()(row, col))
91 const Pixel<dtype> thePixel(row, col, intensities_->operator()(row, col));
92 xcdsVec_.push_back(thePixel);
99 for (
uint8 i = 0; i < inBorderWidth; ++i)
113 return static_cast<uint32>(clusters_.size());
126 return clusters_[inIndex];
139 if (inIndex >= clusters_.size())
143 return clusters_[inIndex];
154 return clusters_.cbegin();
165 return clusters_.cend();
172 std::vector<Pixel<dtype>> xcdsVec_{};
176 std::vector<Cluster<dtype>> clusters_{};
187 Pixel<dtype> makePixel(
int32 inRow,
int32 inCol) noexcept
193 const dtype intensity = intensities_->operator()(row, col);
195 return Pixel<dtype>(row, col, intensity);
206 void findNeighbors(
const Pixel<dtype>& inPixel, std::set<Pixel<dtype>>& outNeighbors)
211 const auto row =
static_cast<int32>(inPixel.row);
212 const auto col =
static_cast<int32>(inPixel.col);
214 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col - 1));
215 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col));
216 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col + 1));
217 outNeighbors.insert(outNeighbors.end(), makePixel(row, col - 1));
218 outNeighbors.insert(outNeighbors.end(), makePixel(row, col + 1));
219 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col - 1));
220 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col));
221 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col + 1));
233 void findNeighborNotXcds(
const Pixel<dtype>& inPixel, std::vector<Pixel<dtype>>& outNeighbors)
235 std::set<Pixel<dtype>> neighbors;
236 findNeighbors(inPixel, neighbors);
239 for (
auto& pixel : neighbors)
241 if (!xcds_->operator()(pixel.row, pixel.col))
243 outNeighbors.push_back(pixel);
257 void findNeighborXcds(
const Pixel<dtype>& inPixel, std::vector<uint32>& outNeighbors)
259 std::set<Pixel<dtype>> neighbors;
260 findNeighbors(inPixel, neighbors);
261 std::vector<Pixel<dtype>> neighborXcds;
264 for (
auto& pixel : neighbors)
266 if (xcds_->operator()(pixel.row, pixel.col))
268 neighborXcds.push_back(pixel);
273 for (
auto& pixel : neighborXcds)
275 auto theExceedanceIter =
std::find(xcdsVec_.begin(), xcdsVec_.end(), pixel);
276 outNeighbors.push_back(
static_cast<uint32>(theExceedanceIter - xcdsVec_.begin()));
284 void runClusterMaker()
288 for (
auto& currentPixel : xcdsVec_)
291 if (currentPixel.clusterId == -1)
293 Cluster<dtype> newCluster(clusterId);
294 currentPixel.clusterId = clusterId;
295 newCluster.addPixel(currentPixel);
298 std::vector<uint32> neighborIds;
299 findNeighborXcds(currentPixel, neighborIds);
300 if (neighborIds.empty())
302 clusters_.push_back(newCluster);
308 for (
uint32 neighborsIdx = 0; neighborsIdx < neighborIds.size(); ++neighborsIdx)
310 Pixel<dtype>& currentNeighborPixel = xcdsVec_[neighborIds[neighborsIdx]];
313 std::vector<uint32> newNeighborIds;
314 findNeighborXcds(currentNeighborPixel, newNeighborIds);
317 for (
auto newNeighborId : newNeighborIds)
320 if (
std::find(neighborIds.begin(), neighborIds.end(), newNeighborId) ==
323 neighborIds.push_back(newNeighborId);
328 if (currentNeighborPixel.clusterId == -1)
330 currentNeighborPixel.clusterId = clusterId;
331 newCluster.addPixel(currentNeighborPixel);
335 clusters_.push_back(std::move(newCluster));
345 void expandClusters()
348 for (
auto& theCluster : clusters_)
351 for (
auto& thePixel : theCluster)
353 std::vector<Pixel<dtype>> neighborsNotXcds;
354 findNeighborNotXcds(thePixel, neighborsNotXcds);
357 for (
auto& newPixel : neighborsNotXcds)
359 if (
std::find(theCluster.begin(), theCluster.end(), newPixel) == theCluster.end())
361 theCluster.addPixel(newPixel);
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:36
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4092
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
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:55
Clusters exceedance data into contiguous groups.
Definition: ClusterMaker.hpp:53
ClusterMaker(const NdArray< bool > *const inXcdArrayPtr, const NdArray< dtype > *const inIntensityArrayPtr, uint8 inBorderWidth=0)
Definition: ClusterMaker.hpp:71
const_iterator begin() const noexcept
Definition: ClusterMaker.hpp:152
const Cluster< dtype > & at(uint32 inIndex) const
Definition: ClusterMaker.hpp:137
const_iterator end() const noexcept
Definition: ClusterMaker.hpp:163
typename std::vector< Cluster< dtype > >::const_iterator const_iterator
Definition: ClusterMaker.hpp:59
uint32 size() noexcept
Definition: ClusterMaker.hpp:111
const Cluster< dtype > & operator[](uint32 inIndex) const noexcept
Definition: ClusterMaker.hpp:124
Holds the information for a single pixel.
Definition: Pixel.hpp:47
InputIt find(InputIt first, InputIt last, const T &value) noexcept
Definition: StlAlgorithms.hpp:207
Definition: Coordinate.hpp:45
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