I have currently made an image that consists of black and green dots..... I made a print of it and then clicked it with my camera..... After that i made a program to scan th
Okay, I just tried with the HSV approach and with little trial and error I was able to find the range for which only the green region will appear. Once you obtain the image with white pixels showing the green circle's position you can call HoughCircles.
The range for HSV is (32,22,0) to (103,142,160)
I hope this solves the issues. :)
OpenCV has a function called InRange
(in C++ it would be cv2.InRange
, Java- Core.InRange
). In that function you provide two Scalar
objects: one is starting BGR color of the range of colors, the other is the ending. It will return you a mask of white pixels: white color is in range, black is not. More information HERE. I'd recommend you to call InRange
before HoughCircles
, it would be easier to determine which objects of green ones are circles, rather than which circles are green.
I've tried out this method for solving your issue:
Scalar(37, 38, 70)
and ending Scalar(85, 255, 200)
. Note that you are putting not RGB or BGR values in Scalar, it is HSV color (ranges from H (0-180), S(0-255), V(0-255), as written in THIS answer):As you see, there is one circle where it should not be, also the circles may be different in size on both pictures. I would highly suggest you to play with values of InRange function to improve color selection, making circles rounder and more perfect, and HoughCircles to avoid random and unnecessary circles as I got one in the middle of the last picture. Also, I would offer you to experiment with Canny algorythm (Canny edge detector) to clear centers of those objects, maybe your results will improve then.
The code is in Java, but you should easily understand it as your concern is mainly InRange function:
Mat src = new Mat();
Mat circles = new Mat();
Mat result;
Utils.bitmapToMat(Image, src);
Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2HSV);
Core.inRange(src, new Scalar(37, 38, 70), new Scalar(85, 255, 200), src);
Imgproc.HoughCircles(src, circles, Imgproc.CV_HOUGH_GRADIENT, 2, 30, 100, 22, 10, 17);
result = new Mat(src.rows(), src.cols(), CvType.CV_8UC1, new Scalar(0,0,0));
for (int i = 0; i < circles.cols(); i++)
{
double[] circle = circles.get(0, i);
if (circle == null) break;
Point center = new Point(Math.round(circle[0]), Math.round(circle[1]));
int radius = (int)Math.round(circle[2]);
Imgproc.circle(result, center, radius, new Scalar(255, 0, 0));
}
return result;
At last, this algorythm even with the right values may not be perfect. I think it is possible to produce a really great or perfect results with the proper values (I sadly did not had much time to find out them, so I leave it to you), but if you need perfect result I would suggest you to experiment in a wider spectre. For example, calling Canny function on coloured image (like you provided) may give you very accurate contours of circles and other objects. Then, for example, you could perform a HoughCircles function on those contours and having data of them, clear all the pixels outside of circles. Then with InRange you could check the colours of circles and sort out them... But this is just theoretical. Try everything what comes to your mind. This experimenting may provide you with result more correct that the updated current one. Good luck!