circle detection: parameters for houghcricles - c++

I want to detect an object and I tried using the Houghcirles function from OpenCV, but I could not achieve the better parameters for all the images and but by doing threasholding I could filter out for the circle. Code I have used is
int main()
{
// Load an image
src = imread("occupant/cam_000569.png");
threshold(src,binary,52,255,0);
imwrite("binary.png",binary);
canny(src,canny,50,200,3);
houghcircles(canny,circles,CV_HOUGH_GRADIENT,1,src.gray.rows/8,7,24,28);
After thresholding, I get the below image and even though there is disturbance included but for a threshold value of 52 I could see the same for all the other images where the object is clear.
After using the canny and houghcircles function with the parameters mentioned the code. I could detect the object required.
But the problem is when I use the next images the same thresholding value is applicable but using the same parameters for canny and houghcircles I am unable detect the object.
So my question is how to choice the parameters for the houghcircle or is it possible to detect the object with different OpenCV function?

I think the main problem here is lighting. Try histogram equalization followed by some smoothing, before you apply the canny edge detector. You will have to take a number of images and estimate the canny and Hough parameters that work well for most of them. It is impossible to find values that result in a 100% detection rate.
Another option is to train an object detector for the object that you want to recognize, using Haar or LBP features. This just seems kind of overkill if the object is a circle.

The better solution for this detection is use of blob detection in C++ or regionprops in MATLAB and filter out based on area and circularity calculation.

Related

OpenCV edge based object detection C++

I have an application where I have to detect the presence of some items in a scene. The items can be rotated and a little scaled (bigger or smaller). I've tried using keypoint detectors but they're not fast and accurate enough. So I've decided to first detect edges in the template and the search area, using Canny ( or a faster edge detection algo ), and then match the edges to find the position, orientation, and size of the match found.
All this needs to be done in less than a second.
I've tried using matchTemplate(), and matchShape() but the former is NOT scale and rotation invariant, and the latter doesn't work well with the actual images. Rotating the template image in order to match is also time consuming.
So far I have been able to detect the edges of the template but I don't know how to match them with the scene.
I've already gone through the following but wasn't able to get them to work (they're either using old version of OpenCV, or just not working with other images apart from those in the demo):
https://www.codeproject.com/Articles/99457/Edge-Based-Template-Matching
Angle and Scale Invariant template matching using OpenCV
https://answers.opencv.org/question/69738/object-detection-kinect-depth-images/
Can someone please suggest me an approach for this? Or a code snipped for the same if possible ?
This is my sample input image ( the parts to detect are marked in red )
These are some software that are doing this and also how I want it should be:
This topic is what I am actually dealing for a year on a project. So I will try to explain what my approach is and how I am doing that. I assume that you already did the preprocess steps(filters,brightness,exposure,calibration etc). And be sure you clean the noises on image.
Note: In my approach, I am collecting data from contours on a reference image which is my desired object. Then I am comparing these data with the other contours on the big image.
Use canny edge detection and find the contours on reference
image. You need to be sure here about that it shouldn't miss some parts of
contours. If it misses, probably preprocess part should have some
problems. The other important point is that you need to find an
appropriate mode of findContours because every modes have
different properties so you need to find an appropriate one for your
case. At the end you need to eliminate the contours which are okey
for you.
After getting contours from reference, you can find the length of
every contours using outputArray of findContours(). You can compare
these values on your big image and eliminate the contours which are
so different.
minAreaRect precisely draws a fitted, enclosing rectangle for
each contour. In my case, this function is very good to use. I am
getting 2 parameters using this function:
a) Calculate the short and long edge of fitted rectangle and compare the
values with the other contours on the big image.
b) Calculate the percentage of blackness or whiteness(if your image is
grayscale, get a percentage how many pixel close to white or black) and
compare at the end.
matchShape can be applied at the end to the rest of contours or you can also apply to all contours(I suggest first approach). Each contour is just an array so you can hold the reference contours in an array and compare them with the others at the end. After doing 3 steps and then applying matchShape is very good on my side.
I think matchTemplate is not good to use directly. I am drawing every contour to a different mat zero image(blank black surface) as a template image and then I compare with the others. Using a reference template image directly doesnt give good results.
OpenCV have some good algorithms about finding circles,convexity etc. If your situations are related with them, you can also use them as a step.
At the end, you just get the all data,values, and you can make a table in your mind. The rest is kind of statistical analysis.
Note: I think the most important part is preprocess part. So be sure about that you have a clean almost noiseless image and reference.
Note: Training can be a good solution for your case if you just want to know the objects exist or not. But if you are trying to do something for an industrial application, this is totally wrong way. I tried YOLO and haarcascade training algorithms several times and also trained some objects with them. The experiences which I get is that: they can find objects almost correctly but the center coordinates, rotation results etc. will not be totally correct even if your calibration is correct. On the other hand, training time and collecting data is painful.
You have rather bad image quality very bad light conditions, so you have only two ways:
1. To use filters -> binary threshold -> find_contours -> matchShape. But this very unstable algorithm for your object type and image quality. You will get a lot of wrong contours and its hard to filter them.
2. Haarcascades -> cut bounding box -> check the shape inside
All "special points/edge matching " algorithms will not work in such bad conditions.

OpenCv Shape Dectection

I am using Opencv to detect shapes and size of material( like disc, washers, nuts and bolts of different size) on that will be held on running belt. what function would be best to distinguish between them.
I am planing to use cvFindContours( to find the shapes) and cvArcLength & cvContourArea to get their area.
Any better approach ?
This is a simple approach to shape matching:
Convert to grayscale
Smoothen the image.
Apply some morphological operations (if necessary).
Edge detect
Find contours (the same you mentioned). The contour function is hierarchical. Hence, segmenting the required (outer in most cases) contour(s) should be easy. Disc and washers can be distinguished by the hole in the contour hierarchy.
Use ApproxPolyDP to get your contour to a rough regular shape. You might be able to distinguish the shapes based on the vertex count in the contour.
Use moments to distinguish the shapes if ApproxPolyDP is not sufficient.
It works for most cases. Always provide sample images to help us assess the complexity of the problem :D.
Check for haar cascade object detection technique in opencv
here are some links....
http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
http://www.technolabsz.com/2011/08/how-to-do-opencv-haar-training.html
For working with haar cascade u need haar kit for traing purpose..
http://kineme.net/files/haar.zip

Dynamic background separation and reliable circle detection with OpenCV

I am attempting to detect coloured tennis balls on a similar coloured background. I am using OpenCV and C++
This is the test image I am working with:
http://i.stack.imgur.com/yXmO4.jpg
I have tried using multiple edge detectors; sobel, laplace and canny. All three detect the white line, but when the threshold is at a value where it can detect the edge of the tennis ball, there is too much noise in the output.
I have also tried the Hough Circle transform but as it is based on canny, it isn't effective.
I cannot use background subtraction because the background can move. I also cannot modify the threshold values as lighting conditions may create gradients within the tennis ball.
I feel my only option is too template match or detect the white line, however I would like to avoid this if possible.
Do you have any suggestions ?
I had to tilt my screen to spot the tennisball myself. It's a hard image.
That said, the default OpenCV implementation of the Hough transform uses the Canny edge detector, but it's not the only possible implementation. For these harder cases, you might need to reimplement it yourself.
You can certainly run the Hough algorithm repeatedly with different settings for the edge detection, to generate multiple candidates. Besides comparing candidates directly, you can also check that each candidate has a dominant texture (after local shading corrections) and possibly a stripe. But that might be very tricky if those tennisballs are actually captured in flight, i.e. moving.
What are you doing to the color image BEFORE the edge detection? Simply converting it to gray?
In my experience colorful balls pop out best when you use the HSV color space. Then you would have to decide which channel gives the best results.
Perhaps transform the image to a different feature space might be better then relying on color. Maybe try LBP which responds to texture. Then do PCA on the result to reduce the feature space to 1 single channel image and try Hough Transform on that.

OpenCV: Prevent HoughCircles method from using Canny Detection

I am using HoughCircles to detect a ball in real-time, but running Canny on my gray-scale image stream isn't creating all of the edges as it should. To remedy that, I am splitting the rgb image into it's separate channels, performing Canny on each one, then using bitwise or to merge the edges together. This is working quite well, but if I feed that edge image to HoughCircles, it will perform Canny again on the edge image. Is there a way to prevent this, or to forgo the rgb split Canny detection that I am performing while still catching all of the edges?
Indeed! Canny is executed internally by HoughCircles and there's no way to call cv::HoughCircles() and prevent it from invoking Canny.
However, if you would like to stick with your current approach, one alternative is to copy the implementation of cv::HoughCircles() available on OpenCV's source code and modify it to suit your needs. This will allow you to write your own version of cv::HoughCircles().
If you follow this path, it's important to realize that the C++ API of OpenCV is built upon the C API. That means that cv::HoughCircles() is just a wrapper around cvHoughCircles(), which is implemented at opencv-2.4.7/modules/imgproc/src/hough.cpp after line 1006.
Take a look at this function (line 1006) and notice the call done to icvHoughCirclesGradient() at line 1064. This is the function responsible for invoking cvCanny(), which is done at line 817.
Another approach, if the ball is single-colored, could be implemented by using cv::inRange() to isolate a specific color, and this will provide a much faster detection. Also, this subject has been extensively discussed on this forum. One very interesting thread is:
Writing robust (color and size invariant) circle detection with OpenCV (based on Hough Transform or other features)
For people who are looking for using a custom edge detection with circle detection in Python, you can use OpenCV's Canny edge detection function and pass it to scikit-image's (skimage) hough_circle function (http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.hough_circle).
Skimage's hough_circle function doesn't internally perform Canny edge detection, thus giving you a chance to implement your own. Below is an example:
hough_results = hough_circle(cv2.Canny(IMAGE, LOWER_THRESHOLD, UPPER_THRESHOLD), np.arrange(MIN_RADIUS, MAX_RADIUS,1))

Thresholding Images and noise

I'm doing a binary thresholding on an image using opencv, while moving or animating for example a circle on a binary image, there are few noise that appears around the moveable object. An image to illustrate what I mean is attached. How can I get rid of those artifacts?
You could try to apply several cycles of the erosion algorithm (until there is only one object left) followed by same number of cycles of the dilation algorithm (the erosion/dilation pair is called opening)
See here: http://en.wikipedia.org/wiki/Mathematical_morphology
If you want to get rid of object that are non circles, you can filter contours according to several metrics this seems to be a good starting link.
In your case, you could find all contours and keep only the ones with a high circularity and a small aspect ratio.
You can go further and calculates metrics such as area/area_of_the_convex_hull. This one should be one for your circle.
Good luck
ps: this pdf seems more exhaustive.