В настоящее время я работаю над проектом, который пытается сгруппировать трехмерные точки из набора данных, определяя связность как минимальное евклидово расстояние. Мой алгоритм прямо сейчас - это просто 3D-адаптация наивной заливки.
size_t PointSegmenter::growRegion(size_t & seed, size_t segNumber) {
size_t numPointsLabeled = 0;
//alias for points to avoid retyping
vector<Point3d> & points = _img.points;
deque<size_t> ptQueue;
ptQueue.push_back(seed);
points[seed].setLabel(segNumber);
while (!ptQueue.empty()) {
size_t currentIdx = ptQueue.front();
ptQueue.pop_front();
points[currentIdx].setLabel(segNumber);
numPointsLabeled++;
vector<int> newPoints = _img.queryRadius(currentIdx, SEGMENT_MAX_DISTANCE, MATCH_ACCURACY);
for (int i = 0; i < (int)newPoints.size(); i++) {
int newIdx = newPoints[i];
Point3d &newPoint = points[newIdx];
if(!newPoint.labeled()) {
newPoint.setLabel(segNumber);
ptQueue.push_back(newIdx);
}
}
}
//NOTE to whoever wrote the other code, the compiler optimizes i++
//to ++i in cases like these, so please don't change them just for speed :)
for (size_t i = seed; i < points.size(); i++) {
if(!points[i].labeled()) {
//search for an unlabeled point to serve as the next seed.
seed = i;
return numPointsLabeled;
}
}
return numPointsLabeled;
}
Где этот фрагмент кода запускается снова для нового начального числа, а _img.queryRadius () - это поиск с фиксированным радиусом в библиотеке ANN:
vector<int> Image::queryRadius(size_t index, double range, double epsilon) {
int k = kdTree->annkFRSearch(dataPts[index], range*range, 0);
ANNidxArray nnIdx = new ANNidx[k];
kdTree->annkFRSearch(dataPts[index], range*range, k, nnIdx);
vector<int> outPoints;
outPoints.reserve(k);
for(int i = 0; i < k; i++) {
outPoints.push_back(nnIdx[i]);
}
delete[] nnIdx;
return outPoints;
}
Моя проблема с этим кодом состоит в том, что он работает waaaaaaaaaaaaaaaay слишком медленно для больших наборов данных. Если я не ошибаюсь, этот код будет выполнять поиск для каждой отдельной точки, и поиск будет O (NlogN), что дает временную сложность (N ^ 2 * log (N)).
В дополнение к этому, удаление, если я помню, прямо из KD-деревьев, обходится довольно дорого, но также не удаление точек создает проблемы в том, что каждую точку можно искать сотни раз, каждый соседний с ней рядом.
Итак, мой вопрос: есть ли лучший способ сделать это? Особенно таким образом, что будет расти линейно с набором данных?
Спасибо за любую помощь, которую вы можете оказать
EDIT
Я попытался использовать простой отсортированный список, как сказал dash-tom-bang, но результат оказался даже медленнее, чем то, что я использовал раньше. Я не уверен, что это была реализация, или просто слишком медленно повторять каждую точку и проверять евклидово расстояние (даже при использовании квадратного расстояния.
Есть ли у людей другие идеи? Я честно сейчас в замешательстве.