47 namespace imageProcessing
52 template<
typename dtype>
56 STATIC_ASSERT_ARITHMETIC(dtype);
75 intensities_(inIntensityArrayPtr)
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)
114 return static_cast<uint32>(clusters_.size());
129 return clusters_[inIndex];
144 if (inIndex >= clusters_.size())
148 return clusters_[inIndex];
160 return clusters_.cbegin();
172 return clusters_.cend();
179 std::vector<Pixel<dtype> > xcdsVec_{};
183 std::vector<Cluster<dtype> > clusters_{};
195 Pixel<dtype> makePixel(
int32 inRow,
int32 inCol) noexcept
201 const dtype intensity = intensities_->operator()(row, col);
203 return Pixel<dtype>(row, col, intensity);
215 void findNeighbors(
const Pixel<dtype>& inPixel, std::set<Pixel<dtype> >& outNeighbors)
220 const auto row =
static_cast<int32>(inPixel.row);
221 const auto col =
static_cast<int32>(inPixel.col);
223 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col - 1));
224 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col));
225 outNeighbors.insert(outNeighbors.end(), makePixel(row - 1, col + 1));
226 outNeighbors.insert(outNeighbors.end(), makePixel(row, col - 1));
227 outNeighbors.insert(outNeighbors.end(), makePixel(row, col + 1));
228 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col - 1));
229 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col));
230 outNeighbors.insert(outNeighbors.end(), makePixel(row + 1, col + 1));
243 void findNeighborNotXcds(
const Pixel<dtype>& inPixel, std::vector<Pixel<dtype> >& outNeighbors)
245 std::set<Pixel<dtype> > neighbors;
246 findNeighbors(inPixel, neighbors);
249 for (
auto& pixel : neighbors)
251 if (!xcds_->operator()(pixel.row, pixel.col))
253 outNeighbors.push_back(pixel);
268 void findNeighborXcds(
const Pixel<dtype>& inPixel, std::vector<uint32>& outNeighbors)
270 std::set<Pixel<dtype> > neighbors;
271 findNeighbors(inPixel, neighbors);
272 std::vector<Pixel<dtype> > neighborXcds;
275 for (
auto& pixel : neighbors)
277 if (xcds_->operator()(pixel.row, pixel.col))
279 neighborXcds.push_back(pixel);
284 for (
auto& pixel : neighborXcds)
286 auto theExceedanceIter =
std::find(xcdsVec_.begin(), xcdsVec_.end(), pixel);
287 outNeighbors.push_back(
static_cast<uint32>(theExceedanceIter - xcdsVec_.begin()));
295 void runClusterMaker()
299 for (
auto& currentPixel : xcdsVec_)
302 if (currentPixel.clusterId == -1)
304 Cluster<dtype> newCluster(clusterId);
305 currentPixel.clusterId = clusterId;
306 newCluster.addPixel(currentPixel);
309 std::vector<uint32> neighborIds;
310 findNeighborXcds(currentPixel, neighborIds);
311 if (neighborIds.empty())
313 clusters_.push_back(newCluster);
319 for (
uint32 neighborsIdx = 0; neighborsIdx < neighborIds.size(); ++neighborsIdx)
321 Pixel<dtype>& currentNeighborPixel = xcdsVec_[neighborIds[neighborsIdx]];
324 std::vector<uint32> newNeighborIds;
325 findNeighborXcds(currentNeighborPixel, newNeighborIds);
328 for (
auto newNeighborId : newNeighborIds)
331 if (
std::find(neighborIds.begin(), neighborIds.end(), newNeighborId) == neighborIds.end())
333 neighborIds.push_back(newNeighborId);
338 if (currentNeighborPixel.clusterId == -1)
340 currentNeighborPixel.clusterId = clusterId;
341 newCluster.addPixel(currentNeighborPixel);
345 clusters_.push_back(std::move(newCluster));
355 void expandClusters()
358 for (
auto& theCluster : clusters_)
361 for (
auto& thePixel : theCluster)
363 std::vector<Pixel<dtype> > neighborsNotXcds;
364 findNeighborNotXcds(thePixel, neighborsNotXcds);
367 for (
auto& newPixel : neighborsNotXcds)
369 if (
std::find(theCluster.begin(), theCluster.end(), newPixel) == theCluster.end())
371 theCluster.addPixel(newPixel);