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 this image in opencv. Here is the image:
This is the code
image = imread("ImageTryse.jpg", 1); // Read the image
cv::resize(image, image, Size(800, 800), 0, 0, cv::INTER_CUBIC);
Mat image_gray = IncreaseContrast(image);
cvtColor(image_gray, image_gray, CV_BGR2GRAY);
vector<vec3f> circles1;
HoughCircles(image_gray, circles1, CV_HOUGH_GRADIENT, 2, 10, 100, 22, 10, 17);
I am able to scan circles with this code and run a loop through each of them.... But now i want to know weather the circle is green or black.... I don't know how i can do that.... I tried converting it to hsv but it was showing different colors on the side having light..... Please help me to solve this problem....
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!