I have this project where I need (on iOS) to detect simple geometric shapes inside an image.
After searching the internet I have concluded that the best tool for this is OpenCV. The thing is that up until two hours ago I had no idea what OpenCV is and I have never even remotely did anything involving image processing. My main experience is JS/HTML,C#,SQL,Objective-C...
Where do I start with this?
I have found this answer that I was able to digest and by reading already other stuff, I understand that OpenCV should return an Array of shapes with the points/corners, is this true? Also how will it represent a circle or a half circle? Also what about the shape orientation?
Do you know of any Demo iOS project that can demonstrate a similar functionality?
Contours – convex contours and the Douglas-Peucker algorithm The first facility OpenCV offers to calculate the approximate bounding polygon of a shape is cv2. approxPolyDP. This function takes three parameters: A contour.
OpenCV has a bunch of pre-trained classifiers that can be used to identify objects such as trees, number plates, faces, eyes, etc. We can use any of these classifiers to detect the object as per our need.
If you have only these regular shapes, there is a simple procedure as follows :
approxPolyDP
function.Below is my example in Python:
import numpy as np import cv2 img = cv2.imread('shapes.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,127,255,1) contours,h = cv2.findContours(thresh,1,2) for cnt in contours: approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True) print len(approx) if len(approx)==5: print "pentagon" cv2.drawContours(img,[cnt],0,255,-1) elif len(approx)==3: print "triangle" cv2.drawContours(img,[cnt],0,(0,255,0),-1) elif len(approx)==4: print "square" cv2.drawContours(img,[cnt],0,(0,0,255),-1) elif len(approx) == 9: print "half-circle" cv2.drawContours(img,[cnt],0,(255,255,0),-1) elif len(approx) > 15: print "circle" cv2.drawContours(img,[cnt],0,(0,255,255),-1) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()
Below is the output:
Remember, it works only for regular shapes.
Alternatively to find circles, you can use houghcircles
. You can find a tutorial here.
Regarding iOS, OpenCV devs are developing some iOS samples this summer, So visit their site : www.code.opencv.org and contact them.
You can find slides of their tutorial here : http://code.opencv.org/svn/gsoc2012/ios/trunk/doc/CVPR2012_OpenCV4IOS_Tutorial.pdf
The answer depends on the presence of other shapes, level of noise if any and invariance you want to provide for (e.g. rotation, scaling, etc). These requirements will define not only the algorithm but also required pre-procesing stages to extract features.
Template matching that was suggested above works well when shapes aren't rotated or scaled and when there are no similar shapes around; in other words, it finds a best translation in the image where template is located:
double minVal, maxVal; Point minLoc, maxLoc; Mat image, template, result; // template is your shape matchTemplate(image, template, result, CV_TM_CCOEFF_NORMED); minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); // maxLoc is answer
Geometric hashing is a good method to get invariance in terms of rotation and scaling; this method would require extraction of some contour points.
Generalized Hough transform can take care of invariance, noise and would have minimal pre-processing but it is a bit harder to implement than other methods. OpenCV has such transforms for lines and circles.
In the case when number of shapes is limited calculating moments or counting convex hull vertices may be the easiest solution: openCV structural analysis
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With