How to efficiently represent blobs in binary image with ellipse? | OpenCV - c++

I want to represent blobs with oriented ellipse.
I have achieved this with findContours() in opencv. But I am thinking in real-time application contours or blob detector, which will perform better.
GaussianBlur(im, tempIm, Size(9, 9), 1, 1, BORDER_REFLECT);
findContours(tempIm, contours, hierarchy, RETR_TREE, CHAIN_APPROX_TC89_KCOS);
Also Blur extends the boundary of the blob, which is not-required.
Input Image
Output Image

Contours is the outline of an object and blob detector is an algorithm on top of findContours. Blob detector not only finds the boundaries, but also calculates the center and whether or not it matches certain shapes and sizes that you define. It is more heavy than findContours and you shouldn't use it if you care for performance and don't need these features.
You can use median blur instead of Gaussian, if you want to keep the image binary and do not extend contours. Also you can use dilate/erode/open/close operations and their combinations to denoise the binary image. These approaches are relatively comparable on binary images and you can test both for best performance and result and choose one for your task.
Tutorial code here describes how to represent the found contours with ellipses. cv::fitEllipse is used to create an ellipse for a contour. Then you can display it with cv::ellipse drawing function.

Related

C++ Biological Cell Counting with OpenCV

I'm relatively new to OpenCV and I do not have a strong image processing background. Currently I am working on a project to write a program to count all the biological cells from microscope in an image. I have tried various method from Internet sources to apply counting on the image, but none of them work well as expected.
Some of the methods I have used are:
Finding contours of the filtered image. (does not work well with cells that are close together)
Gaussian blur and find local maxima on the image. (same problem as 1)
Canny Edge detection (output result detect non cells segment)
This is an example of the image I need to count the total number of cells.
My current counting algorithm works better if the cells are not close together. For example like this:
However, the algorithm still fail to split apart the 3 cells that are sticked together in the center of the image.
So what could I do to detect total number of cells in an image with least false negative/positive?
Your approach is almost fine. However, it needs some additional steps.
You need something called Morphological Operations.
Filter your image in the way you thing is good.
Apply a threshold depending on color or convert it to gray then threshold it. P.S. from the examples you provided, it seems that your cell color is too saturated. So, you may convert it to HSV Space and then threshold it using the S channel (tell me if you need help here).
Apply the Opening Morphological Operators on the thresholded image. P.S. you may to try few kernal size and choose the best.
Take contours and do what you were doing.
Opening:
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(1, 1));
cv::morphologyEx(img, img, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1);

opencv: How to detect rectangle with the not-in-order points in contours

In OpenCV we can use the approxPolyDP to find the contours of an object. However, sometimes the output contours could be quite different when there are holes/blur in between the lines. For example, the actual object of the following two graphs is a rectangle but the output of approxPolyDP generates the contours that are not-in-order. Is there any well-known algorithm that can process the following points and detect a rectangular shape? If not, what is the best approach to deal with this situation?

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

How to calculate the gradients of an image?

The following code allows to calculate the gradients of an image using the Sobel operators, that are available in OpenCV.
IplImage* grad_x = cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
IplImage* grad_y = cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
cvSobel(image,grad_x,1,0,3);
cvSobel(image,grad_y,0,1,3);
How are the edges handled by the cvSobel() function? What is the difference between this function and this one this one? I read about available borderType options, however, I do not know which of these options would be better to use.
Moreover, what advantages could provide performing a smoothing filter before calculating the gradients of an image?
Finally, after calculating the gradients of an image, how to calculate the corresponding angles and magnitude?
If you are interested in edge maps, you should consider the Canny method in OpenCV. Sobel will return a gradient image, which you can then derive the edge map from via simple thresholding using threshold, or you can do something more complex like the Canny method.
Smoothing the image (e.g., via GaussianBlur or blur) will reduce the magnified noise levels which result from the Sobel operation.
I have a very similar answer located here, which shows how determine the magnitude and phase of the gradients.
Hope that helps!

Find the best Region of Interest after edge detection in OpenCV

I would like to apply OCR to some pictures of 7 segment displays on a wall. My strategy is the following:
Covert Img to Grayscale
Blur img to reduce false edges
Threshold the img to a binary img
Apply Canny Edge detection
Set Region of Interest (ROI) base on a pattern given by the silhouette of the number
Scale ROI and Template match the region
How to set a ROI so that my program doesn't have to look for the template through the whole image? I would like to set my ROI base on the number of edges found or something more useful if someone can help me.
I was looking into Cascade Classification and Haar but I don't know how to apply it to my problem.
Here is an image after being pre-processed and edge detected:
original Image
If this is representative of the number of edges you'll have to deal with you could try a nice naive strategy like sliding a ROI-finder window across the binary image which just sums the pixel values, and doesn't fire unless that value is above a threshold. That should optimise out all the blank surfaces.
Edit:
Ok some less naive approaches. If you have some a-priori knowledge, like you know the photo is well aligned (and not badly rotated or skewed), you could do some passes with a low-high-low-high grate tuned to capture the edges either side of a segment, using different scales in both x and y dimensions. A good hit in both directions will give clues not only about ROI but what scale of template to begin with (too large and too small grates won't hit both edges at once).
You could do blob detection, and then apply your templates to blobs in turn (falling back on merging blobs if the template matching score is below a threshold, in case your number segment is accidentally partitioned). The size of the blob might again give you some hint as to the scale of template to apply.
First of all, given that the original image has a LED display and so the illuminated region is has a higher intensity than the trest, I'd perform say a Yuv colour transformation on the original image and then work with the intensity plane (Y).
Next, if you know that the image is well aligned (i.e. not rotated) I would suggest applying separate horizontal and vertical edge detectors rather than a generic edge detector (you are not interested in diagonal lines). E.g.
sobelx = cv2.Sobel( img, cv2.CV_64F, 1, 0, ksize=5 )
sobely = cv2.Sobel( img, cv2.CV_64F, 0, 1, ksize=5 )
Otherwise you might use contour detection to find the bounds of the digits (though you may need to perform a dilate to close the gaps between LED segments.
Next I would construct horizontal and vertical histograms of the output from these edge or contour detections. These would help you to identify 'busy' regions of the image which contain many edges.
Finally, I'd threshold the Y plane and explore each of the ROIs with my template.