I have a vector of points that form blobs inside a 2d region. This 2d region represents an image. I need to find the center point of the largest blob very quickly. My algorithm that I use takes ~1 minute for a 50x50 image and it took so long that I canceled it for a 2560x1440 image. I want to be able to calculate a 2560x1440 image in just a couple seconds. Is this possible? I don't mind if the center is just an approximation. It doesn't have to be exact.
Here is an image I created from the points:
The white points are the ones that I am interested in. I need the center of the largest blob. The points that are identified could look wildly different, so take this image with a grain of salt.
I took the code from here and adapted it for my purpose. The point.h file contains an iteration value. I create a 2d array where every point outside the blobs has an iteration value of -1 and the rest have a value greater than or equal to 0 and passed that into the method.
Point.h
class Point
{
private:
int x, y, iteration;
public:
Point(int Xin, int Yin) : x(Xin), y(Yin), iteration(-1) {}
Point(int Xin, int Yin, int Iterationin) : x(Xin), y(Yin), iteration(Iterationin) {}
int getX() { return x; };
int getY() { return y; };
int getIteration() { return iteration; };
};
Center Point
int calculateFramePerturbation2::fill(vector<vector<int>> arr, int r, int c, vector<Point>& points) {
int count = 0;
if (r < arr.size() && arr[r][c] >= 0) {
for (int i = c; i >= 0 && arr[r][i] >= 0; i--) {
Point pt(r, i, arr[r][i]);
points.push_back(pt);
arr[r][i] = -1;
count += fill(arr, r + 1, i, points) + 1;
}
for (int i = c + 1; i < arr[r].size() && arr[r][i] >= 0; i++) {
Point pt(r, i, arr[r][i]);
points.push_back(pt);
arr[r][i] = -1;
count += fill(arr, r + 1, i, points) + 1;
}
}
return count;
}
Point calculateFramePerturbation2::print_components(vector<vector<int>> arr) {
vector<int> pointAreas;
vector<vector<Point>> allPoints;
for (int r = 0; r < arr.size(); ++r) {
for (int c = 0; c < arr[r].size(); ++c) {
if (arr[r][c] >= 0) {
vector<Point> points;
fill(arr, r, c, points);
//cout << fill(arr, r, c, points) << " ";
//cout << points.size() << endl;
allPoints.push_back(points);
pointAreas.push_back(points.size());
}
}
}
//Identify the blob with the highest area.
int max = -1;
int index2 = 0;
for (int i = 0; i < pointAreas.size(); i++) {
if (pointAreas[i] > max) {
max = pointAreas[i];
index2 = i;
}
}
cout << endl;
cout << max << " " << index2 << endl;
//Find the center point
int totalX = 0;
int totalY = 0;
for (int i = 0; i < allPoints[index2].size(); i++) {
totalX += allPoints[index2][i].getX();
totalY += allPoints[index2][i].getY();
}
Point finalPoint(totalX / allPoints[index2].size(), totalY / allPoints[index2].size(), -1);
return finalPoint;
}
void run(vector<Point> pointsRemaining) {
//I'd prefer a solution where I could just take the points remaining array (it defines the blobs instead of converting it into a 2d array.
vector<vector<int>> glitch2DArray;
glitch2DArray.resize(WIDTH, vector<int>(HEIGHT, -1));
for (int i = 0; i < pointsRemaining.size(); i++) {
glitch2DArray[pointsRemaining[i].getX()][pointsRemaining[i].getY()] = pointsRemaining[i].getIteration();
}
Point finalPoint = print_components(glitch2DArray);
}