circle hough center co-ordinates - c++

In opencv, I am using Hough transform for circle finder here is the code
HoughCircles (diff, circles, CV_HOUGH_GRADIENT, 2, src.cols / 5, 200, 80, 20, 62);
for (size_t i = 0; i < circles.size(); i++ )
{
//if(circles[i][2]<62)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the green circle center
circle( src, center, 3, Scalar(0,255,255), -1, 8, 0 );
// draw the blue circle outline
circle(src, center, radius, Scalar(0,255,0), 3, 8, 0 );
}
}
The problem I am facing is that sometimes in case it found 3 circles, the third one center coordinates are fraction not integer as supposed to be also in case it found 4 circles it give this error
Unhandled exception at 0x75ebc41f in xyz.exe: Microsoft C++ exception:
cv::Exception at memory location 0x002df08c..
if I tried to cout the center co-ordinates.

Hmm this is interesting. I ran your code and filled-in the before and after and didn't have any problems. To be honest, I've only tested on a linux and mac machine. Here is my full length code, try that and see what happens. Also, check this solution here.
int main(int argc, char* argv[]) {
VideoCapture capture(0);
if (!capture.isOpened()) {
LOG(FATAL) << "COULD NOT OPEN CAPTURE";
}
Mat frame;
capture >> frame;
if (frame.empty()) {
LOG(FATAL) << "FRAME IS EMPTY!";
}
char key;
while ((int)key != 27) {
capture >> frame;
Mat gray;
cvtColor(frame, gray, CV_BGR2GRAY);
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.cols/5,200,80,20,62);
for (size_t i = 0; i < circles.size(); ++i) {
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the green circle center
circle(frame, center, 3, Scalar(0,255,255), -1, 8, 0 );
// draw the blue circle outline
circle(frame, center, radius, Scalar(0,255,0), 3, 8, 0 );
}
imshow("frame", frame);
key = waitKey(1);
}
return 0;
}

Related

Get one circle after Hough transform method

I use Hough transform method so I get 2 circles, how can I get just the zone of the big circle from the for loop?
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles;
HoughCircles(openImg, circles, CV_HOUGH_GRADIENT, 1,1,67, 17,35, 80);
/// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle(openImg, center, 1, Scalar(255, 255, 255), -1, 8, 0);
// circle outline
circle(openImg, center, radius, Scalar(255, 255, 255), 1, 4, 0);
}
/// Show your results
namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
imshow("Hough Circle Transform Demo", openImg);
The documentation of opencv states:
circles – Output vector of found circles. Each vector is encoded as a 3-element floating-point vector (x, y, radius)
https://docs.opencv.org/3.4.1/d3/de5/tutorial_js_houghcircles.html
You are reading the radius (int radius = cvRound(circles[i][2]);). That is actually the size of the circle.
So, you need to loop through your array circles and pick the circle with the biggest radius:
// remember biggest radius
float radiusBiggest = 0;
// remember the index of the biggest radius / circle
int indexBiggest = -1;
// loop through all circles
for (size_t i = 0; i < circles.size(); i++)
{
// get the radius
float radius = circles[i][2];
// check if this radius is bigger than any previous
if (radius > radiusBiggest)
{
// this radius/circle is the biggest so far. remember it
radiusBiggest = radius;
indexBiggest = i;
}
}
// if we found a circle then draw it
if (indexBiggest != -1)
{
Point center(cvRound(circles[indexBiggest][0]), cvRound(circles[indexBiggest][1]));
int radius = cvRound(circles[indexBiggest][2]);
// circle center
circle(openImg, center, 1, Scalar(255, 255, 255), -1, 8, 0);
// circle outline
circle(openImg, center, radius, Scalar(255, 255, 255), 1, 4, 0);
}

OpenCV C++: How to find all the circles in an image

Hi I am trying to find all the circles in the following image and Identify the defect.
this is my code:
static void findCircles2(const Mat& image)
{
vector<Vec3f> circles;
int thresh1 = 5;
Mat pyr, timg, gray0(image.size(), CV_8U), gray;
pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
pyrUp(pyr, timg, image.size());
for( int c = 0; c < 3; c++ )
{
int ch[] = {c, 0};
mixChannels(&timg, 1, &gray0, 1, ch, 1);
Canny(gray0, gray, 0, thresh1, 5);
//dilate(gray, gray, Mat(), Point(-1,-1));
gray = gray0 >= (1)*255/N;
gray = gray0 >= (2)*255/N;
gray = gray0 >= (6)*255/N;
namedWindow( "Hough Circle Transform Demo 1", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo 1", gray );
waitKey(0);
HoughCircles( gray, circles, CV_HOUGH_GRADIENT, 1, gray.rows/8, 200, 100, 0, 0 );
cout<<"size of circles: "<<circles.size()<<endl;
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle( gray, center, 3, Scalar(0,255,0), -1, 8, 0 );
circle( gray, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
/// Show your results
namedWindow( "Hough Circle Transform Demo 2", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo 2", gray );
waitKey(0);
}
}
Picture:
however the code is unable to find anything, I played arround with the thresholds but it doesnt help. please advise.
Development platform: VS2010, Opencv version: 2.4.10
Because the circles are so small and not that standard, so you cann't just do HoughCircles on the binary image.
An alternative method is to findContours, then filter the contours by ratio between the value of contourArea and the value of minEnclosingCircle.

Using Opencv and Hough Transform circle to detect circles (subscript error)

As right now is my school holiday, I decided to pick up some skills thus I'm attempting to learn how to use OpenCV features with visual studio c++ to detect how many cans is in the carton and had to group it 4 by 4.
I have tried various demo codes such as " opencv find:contour " , Template matching(doesn't work well as it cannot detect the rotation of the top lid)
The best method that I found out is that to combine Canny Edge Detection and Hough Transform Circle such that the output result of Canny Edge Detection can be the input image of the Hough Transform Circle,the result is as below.
Unfortunately, not all circles is detected and if i change the
for (int i = 0; i < circles.size(); i++) into
for (int i = 0; i < 24; i++) // 24 is the no. of cans
I will get a Expression: vector subscript out of range. I am not sure why it is only able to detect 21 circles
Source code as below:-
using namespace cv;
using namespace std;
Mat src, src_gray;
int main()
{
Mat src1;
src1 = imread("cans.jpg", CV_LOAD_IMAGE_COLOR);
namedWindow("Original image", CV_WINDOW_AUTOSIZE);
imshow("Original image", src1);
Mat gray, edge, draw;
cvtColor(src1, gray, CV_BGR2GRAY);
Canny(gray, edge,50, 150, 3);
//50,150,3
edge.convertTo(draw, CV_8U);
namedWindow("Canny Edge", CV_WINDOW_AUTOSIZE);
imshow("Canny Edge", draw);
imwrite("output.jpg", draw);
waitKey(500);
/// Read the image
src = imread("output.jpg", 1);
Size size(932, 558);//the dst image size,e.g.100x100
resize(src, src, size);//resize image
/// Convert it to gray
cvtColor(src, src_gray, CV_BGR2GRAY);
/// Reduce the noise so we avoid false circle detection
GaussianBlur(src_gray, src_gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles
HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8,200, 100, 0, 0);
/// Draw the circles detected
for (int i = 0; i < circles.size(); i++)
{
printf("are you um?\n");
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(src, center, radius, Scalar(255, 0, 255), 3, 8, 0);
}
// namedWindow("Hough Circle Transform Demo", CV_WINDOW_NORMAL);
imshow("Hough Circle Transform Demo", src);
line(src, Point(0, 288), Point(1024, 288), Scalar(225, 220, 225), 2, 8);
// middle line
line(src, Point(360, 0), Point(360, 576), Scalar(225, 220, 225), 2, 8);
//break cans into 4 by 4
line(src, Point(600, 0), Point(600, 576), Scalar(225, 220, 225), 2, 8);
// x, y
imshow("Lines", src);
imwrite("lineoutput.jpg", src);
waitKey(0);
return 0;
}
I had also manually typed out the coordinates for the lines to group them into 4 x 4.
What should I change in order for it not to have any subscript out of range error and able to detect all circles?
Okay solved my own question. Changed CV_BGR2GRAY to CV_RGB2GRAY,made the file ratio smaller, changing the circles min Radius and applying another threshold to get the circles.

to remove a semi-curved object from a binary image using opencv

I have a binary image:
I want to remove the bottom two crescent shapes(size and area may change with different images) from the image or at-least differentiate it from the rest.
I tried Hough circle transform to detect the curves as it resembles a portion of a circle, but that code was not working:
int main(int argc, char** argv)
{
Mat src, gray;
src = imread("446.bmp", 1);
namedWindow("src", 1);
imshow("src", src);
waitKey(0);
cvtColor(src, gray, CV_BGR2GRAY);
// Reduce the noise so we avoid false circle detection
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
// Apply the Hough Transform to find the circles
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 30, 100, 100, 0, 0);
// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);// circle center
circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);// circle outline
cout << "center : " << center << "\nradius : " << radius << endl;
}
// Show your results
namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
imshow("Hough Circle Transform Demo", src);
waitKey(0);
return 0;
}
But No circle is being drawn or the crescent moon shapes are not being detected at all. Any idea where I went wrong?
EDIT 1- I have added some other images too:
Edit-2 new image to try:-
i made some modification on the code posted for other question
you could try it
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
//! Compute the distance between two points
/*! Compute the Euclidean distance between two points
*
* #param a Point a
* #param b Point b
*/
static double distanceBtwPoints(const cv::Point2f &a, const cv::Point2f &b)
{
double xDiff = a.x - b.x;
double yDiff = a.y - b.y;
return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}
int main( int argc, char** argv )
{
Mat src,gray;
src = imread(argv[1]);
if(src.empty())
return -1;
cvtColor( src, gray, COLOR_BGR2GRAY );
gray = gray < 200;
vector<vector<Point> > contours;
findContours(gray.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
RotatedRect _minAreaRect;
for (size_t i = 0; i < contours.size(); ++i)
{
double contour_area = contourArea(contours[i]);
_minAreaRect = minAreaRect( Mat(contours[i]) );
Point2f pts[4];
_minAreaRect.points(pts);
double dist0 = distanceBtwPoints(pts[0], pts[1]);
double dist1 = distanceBtwPoints(pts[1], pts[2]);
double angle = 0;
//if(dist0 > dist1 *1.2)
angle =atan2(pts[0].y - pts[1].y,pts[0].x - pts[1].x) * 180.0 / CV_PI;
//if(dist1 > dist0 *1.2)
angle =atan2(pts[1].y - pts[2].y,pts[1].x - pts[2].x) * 180.0 / CV_PI;
if( fabs(angle) > 91 ) // you can try different values
{
if( contour_area < dist0 * dist1 /2 ) // you can try different values
{
//drawContours(src,contours,i,Scalar(0,0,0),-1); // try to uncomment this line
for( int j = 0; j < 4; j++ )
line(src, pts[j], pts[(j+1)%4], Scalar(0, 0, 255), 1, LINE_AA);
}
}
}
imshow("result", src);
waitKey(0);
return 0;
}
I don't think there is an easy solution here unfortunately.
What you might want to try is to detect and label each image component. From here you need to detect which set of pixels looks like a crescent and which does not : as a crescent can be described by a polynomial equations you only need to describe each component (i.e a set of points) as a mathematical equation (using regression methods such as RANSAC) and see if that might be a crescent equation.

Is there any way to detect adjacent circles in image using opencv

I am trying to detect adjacent circles in an image. these can be either 4 or 5. is there any way to detect it in opencv. i tried many ways, including hough circles method. but i am detecing extra circles too. if in any case i am able to detect circle than same parameters won't work with other images.
Please let me know of any thing possible to achieve this.
My code using Hough Circles is:
Mat img, gray;
img = imread("/Users/Development/Desktop/Images/IMG_0297.jpg");
cvtColor(img, gray, CV_BGR2GRAY);
// smooth it, otherwise a lot of false circles may be detected
GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows/16,80,100,30,50 );
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle center
circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the circle outline
circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
namedWindow( "circles", 1 );
imshow( "circles", img );
waitKey(0);
return 0;
sample image is
and i want to detect dials in this, that are adjacent to eachother
You can use partition to cluster circles adjacent circles, i.e. circles whose center distance is similar to the sim of their radii. You just need to define the appropriate equivalence predicate, here implemented in CirclesOnSameLine. You can eventually improve this predicate to consider as equal only circles that have similar radius.
The result of this clustering is something like (same color means same cluster):
With this approach, you can safely detect some circle, since you can then remove circles that don't belong to clusters with more than 4-5 circles.
Code:
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
struct CirclesOnSameLine
{
float _tolerance;
CirclesOnSameLine(float tolerance) : _tolerance(tolerance) {};
bool operator()(const Vec3f& lhs, const Vec3f& rhs)
{
// [0] = x
// [1] = y
// [2] = radius
float center_distance = sqrt((lhs[0] - rhs[0])*(lhs[0] - rhs[0]) + (lhs[1] - rhs[1])*(lhs[1] - rhs[1]));
float sum_radii = lhs[2] + rhs[2];
if (sum_radii > center_distance)
{
return (sum_radii / center_distance) < _tolerance;
}
return (center_distance / sum_radii) < _tolerance;
}
};
int main()
{
Mat3b img = imread("path_to_image");
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows / 16, 80, 100, 10, 100);
// Cluster circles near each other
vector<int> labels;
int n_labels = partition(circles, labels, CirclesOnSameLine(1.1f));
vector<Scalar> colors;
for (int i = 0; i < n_labels; ++i)
{
Scalar color(rand() & 255, rand() & 255, rand() & 255);
colors.push_back(color);
}
Mat3b adjacent = img.clone();
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle outline
circle(adjacent, center, radius, colors[labels[i]], 3, 8, 0);
}
// Remove small clusters
vector<int> count(labels.size(), 0);
for (size_t i = 0; i < labels.size(); ++i)
{
count[labels[i]]++;
}
Mat3b big_clusters = img.clone();
for (size_t i = 0; i < circles.size(); i++)
{
if (count[labels[i]] < 4) continue;
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// draw the circle outline
circle(big_clusters, center, radius, Scalar(0, 0, 255), 3, 8, 0);
}
imshow("Adjacent circles", adjacent);
imshow("Adjacent circles", big_clusters);
waitKey();
return 0;
}
You could chamfer match the circles for example and then check if the circle shares an edge with another circle or is close to it using edge detection and a scan of the image to see if the circles are close enough to be adjacent or not.
With this specific image you could probably do kmeans and connected components. Then chamfer match circles and see if a connected component is made up of multiple circles.