# Revision history [back]

I am not quite sure after which parameter the circles are sorted, but I ask you: do you actually need that at all? You have the circles and now you are interested in each mid-point between the two closest circles. So, what you only need is to search for the nearest center of each circle.

vector<Vec3f> circles;
HoughCircles( img, circles, CV_HOUGH_GRADIENT, 10,  80, 10, 25, 70 );
// to save some time let's mark the already visited circles
std::vector<bool> visited(circles.size(),false);

// search now for the nearest circle
for( size_t i =0; i < circles.size(); i++){
visited[i] = true;
float min_dist = std::numerical_limits<float>::max();
// set nearest circle idx first to -1
int nearest_circle_idx = -1;
for( size_t k =0; k < circles.size(); k++){
if (visited[k]) continue;
// choose squared Eudlidian distance
float dist = (circles[i][0]-circles[k][0])*(circles[i][0]-circles[k][0])
+(circles[i][1]-circles[k][1])*(circles[i][1]-circles[k][1])
if( dist < min_dist) {
nearest_circle_idx = k;
min_dist = dist;
}
}
// we don't need to visit nearest circle any more
visited[ nearest_circle_idx ] = true;

// now compute half distance between circles:
int x_half = std::abs(circles[i][0]-circles[nearest_circle_idx][0]) / 2;
int y_half = std::abs(circles[i][1]-circles[nearest_circle_idx][1]) / 2;

// do whatever you actually wanted now to do with that point
// ...
}


I am not quite sure after which parameter the circles are sorted, but I ask you: do you actually need that at all? You have the circles and now you are interested in each mid-point between the two closest circles. So, what you only need is to search for the nearest center of each circle.

Not tested, but similar to the following it should work. Good luck!

vector<Vec3f> circles;
HoughCircles( img, circles, CV_HOUGH_GRADIENT, 10,  80, 10, 25, 70 );
// to save some time let's mark the already visited circles
std::vector<bool> visited(circles.size(),false);

// search now for the nearest circle
for( size_t i =0; i < circles.size(); i++){
visited[i] = true;
float min_dist = std::numerical_limits<float>::max();
// set nearest circle idx first to -1
int nearest_circle_idx = -1;
for( size_t k =0; k < circles.size(); k++){
if (visited[k]) continue;
// choose squared Eudlidian distance
float dist = (circles[i][0]-circles[k][0])*(circles[i][0]-circles[k][0])
+(circles[i][1]-circles[k][1])*(circles[i][1]-circles[k][1])
if( dist < min_dist) {
nearest_circle_idx = k;
min_dist = dist;
}
}
// we don't need to visit nearest circle any more
visited[ nearest_circle_idx ] = true;

// now compute half distance between circles:
int x_half = std::abs(circles[i][0]-circles[nearest_circle_idx][0]) / 2;
int y_half = std::abs(circles[i][1]-circles[nearest_circle_idx][1]) / 2;

// do whatever you actually wanted now to do with that point
// ...
}


I am not quite sure after which parameter the circles are sorted, but I ask you: do you actually need that at all? You have the circles and now you are interested in each mid-point between the two closest circles. So, what you only need is to search for the nearest center of each circle.

Not tested, but similar to the following it should work. Good luck!

vector<Vec3f> std::vector<cv::Vec3f> circles;
cv::Mat edges;
GaussianBlur( img, img, cv::Size(9, 9), 3, 3 );
cv::Canny( img, edges, 50, 100, 3);
HoughCircles( img, edges, circles, CV_HOUGH_GRADIENT, 10,  1, img.rows / 8, 80, 10, 25, 70 );
// to save some time let's mark the already visited circles
std::vector<bool> visited(circles.size(),false);

// search now for the nearest circle
for( size_t i =0; i < circles.size(); i++){
visited[i] = true;
float min_dist = std::numerical_limits<float>::max();
// set nearest circle idx first to -1
int nearest_circle_idx = -1;
for( size_t k =0; k < circles.size(); k++){
if (visited[k]) continue;
// choose squared Eudlidian distance
float dist = (circles[i][0]-circles[k][0])*(circles[i][0]-circles[k][0])
+(circles[i][1]-circles[k][1])*(circles[i][1]-circles[k][1])
if( dist < min_dist) {
nearest_circle_idx = k;
min_dist = dist;
}
}
// we don't need to visit nearest circle any more
visited[ nearest_circle_idx ] = true;

// now compute half distance between circles:
int x_half = std::abs(circles[i][0]-circles[nearest_circle_idx][0]) (circles[i][0]+circles[nearest_circle_idx][0]) / 2;
int y_half = std::abs(circles[i][1]-circles[nearest_circle_idx][1]) (circles[i][1]+circles[nearest_circle_idx][1]) / 2;

// do whatever you actually wanted now to do with that point
// ...
cv::circle( img, cv::Point(x_half,y_half), 3, cv::Scalar(0,0,255), -1, 8, 0 );
}


My result image:

I am not quite sure after which parameter the circles are sorted, but I ask you: do you actually need that at all? You have the circles and now you are interested in each mid-point between the two closest circles. So, what you only need is to search for the nearest center of each circle.

std::vector<cv::Vec3f> circles;
cv::Mat edges;
GaussianBlur( img, img, cv::Size(9, 9), 3, 3 );
cv::Canny( img, edges, 50, 100, 3);
HoughCircles( edges, circles, CV_HOUGH_GRADIENT, 1, img.rows / 8, 80, 10, 25, 70 );
std::vector<bool> visited(circles.size(),false);

// search now for the nearest circle
for( size_t i =0; i < circles.size(); i++){
visited[i] = true;
float min_dist = std::numerical_limits<float>::max();
std::numeric_limits<float>::max();
// set nearest circle idx first to -1
int nearest_circle_idx = -1;
for( size_t k =0; k < circles.size(); k++){
if (visited[k]) continue;
// choose squared Eudlidian distance
float dist = (circles[i][0]-circles[k][0])*(circles[i][0]-circles[k][0])
+(circles[i][1]-circles[k][1])*(circles[i][1]-circles[k][1])
if( dist < min_dist) {
nearest_circle_idx = k;
min_dist = dist;
}
}
if ( nearest_circle_idx == -1) continue;

// we don't need to visit nearest circle any more
visited[ nearest_circle_idx ] = true;

// now compute half distance between circles:
int x_half = (circles[i][0]+circles[nearest_circle_idx][0]) / 2;
int y_half = (circles[i][1]+circles[nearest_circle_idx][1]) / 2;

// do whatever you actually wanted now to do with that point
// ...
cv::circle( img, cv::Point(x_half,y_half), 3, cv::Scalar(0,0,255), -1, 8, 0 );
}


My result image: