What coding techniques would allow me to to differentiate between circles, rectangles, and triangles in black and white image bitmaps?
You could train an Artificial Neural Network to classify the shapes :P
If noise is low enough to extract curves, approximations can be used: for each shape select parameters giving least error (he method of least squares may help here) and then compare these errors...
If the image is noisy, I would consider Hough transform - it may be used to detect shapes with small count of parameters, like circle (harder for rectangles and triangles).
just an idea off of the top of my head: scan the (pixel) image line-by-line, pixel-by-pixel. If you encounter the first white pixel (assuming it has a black background) you keep it's position as a starting point and look at the eight pixels surrounding it in every direction for the next white pixel. If you find an adjacent second pixel you can establish a directional vector between those two pixels.
Now repeat this until the direction of your vector changes (or the change is above a certain threshold). Keep the last point before the change as the endpoint of your first line and repeat the process for the next line.
Then calculate the angle between the two lines and store it. Now trace the third line. Calculate the angle between the 2nd and 3rd line as well.
If both angles are rectangular you probably found a rectangle, otherwise you probably found a triangle. If you can't find any straight line you could conclude that you found a circle.
I know the algorithm is a bit sketchy but I think (with some refinement) it could work if your image's quality is not too bad (too much noise, gaps in the lines etc.).
You are looking for the Hough Transform. For an implementation, try the AForge.NET framework. It includes circle and line hough transformations.
Related
I have image of robot with yellow markers as shown
The yellow points shown are the markers. There are two cameras used to view placed at an offset of 90 degrees. The robot bends in between the cameras. The crude schematic of the setup can be referred.
https://i.stack.imgur.com/aVyDq.png
Using the two cameras I am able to get its 3d co-ordinates of the yellow markers. But, I need to find the 3d-co-oridnates of the central point of the robot as shown.
I need to find the 3d position of the red marker points which is inside the cylindrical robot. Firstly, is it even feasible? If yes, what is the method I can use to achieve this?
As a bonus, is there any literature where they find the 3d location of such internal points which I can refer to (I searched, but could not find anything similar to my ask).
I am welcome to a theoretical solution as well(as long as it assures to find the central point within a reasonable error), which I can later translate to code.
If you know the actual dimensions, or at least, shape (e.g. perfect circle) of the white bands, then yes, it is feasible and possible.
You need to do the following steps, which are quite non trivial to do, and I won't do them here:
Optional but extremely suggested: calibrate your camera, and
undistort it.
find the equation of the projection of a 3D circle into a 2D camera, for any given rotation. You can simplify this by assuming the white line will be completely horizontal. You want some function that takes the parameters that make a circle and a rotation.
Find all white bands in the image, segment them, and make them horizontal (rotate them)
Fit points in the corrected white circle to the equation in (1). That should give you the parameters of the circle in 3d (radious, angle), if you wrote the equation right.
Now that you have an analytic equation of the actual circle (equation from 1 with parameters from 3), you can map any point from this circle (e.g. its center) to the image location. Remember to uncorrect for the rotations in step 2.
This requires understanding of curve fitting, some geometric analytical maths, and decent code skills. Not trivial, but this will provide a solution that is highly accurate.
For an inaccurate solution:
Find end points of white circles
Make line connecting endpoints
Chose center as mid point of this line.
This will be inaccurate because: choosing end points will have more error than fitting an equation with all points, ignores cone shape of view of the camera, ignores geometry.
But it may be good enough for what you want.
I have been able to extract the midpoint by fitting an ellipse to the arc visible to the camera. The centroid of the ellipse is the required midpoint.
There will be wrong ellipses as well, which can be ignored. The steps to extract the ellipse were:
Extract the markers
Binarise and skeletonise
Fit ellipse to the arc (found a matlab function for this)
Get the centroid of the ellipse
hsv_img=rgb2hsv(im);
bin=new_hsv_img(:,:,3)>marker_th; %was chosen 0.35
%skeletonise
skel=bwskel(bin);
%use regionprops to get the pixelID list
stats=regionprops(skel,'all');
for i=1:numel(stats)
el = fit_ellipse(stats(i).PixelList(:,1),stats(i).PixelList(:,2));
ellipse_draw(el.a, el.b, -el.phi, el.X0_in, el.Y0_in, 'g');
The link for fit_ellipse function
Link for ellipse_draw function
hi i want to detect fingertips point and valleypoint of hand by using hough transform.Simply the Question is what is the [H,theta,rho]=hough(BW) is good for extract these point.
the image is here:
https://www.dropbox.com/sh/n1lz7b5eedzbui7/AADwy5O1l7sWf5aOx7KWAmhOa?dl=0
tnx
The standard hough transformation is just for detecting straight lines. Not more and not less. The Matlab function hough (please see here) returns the so-called hough space H, a parametric space which is used to find these lines and the parametric representation of each line: rho = x*cos(theta) + y*sin(theta).
You will have to do more than this to detect your desired points. Since your fingers usually won't consist of straight lines, I think you should think of something else anyway, e.g. if you can assume such a perfect curve as the one in your image maybe this is interesting for you.
Another simple technique you might consider is to compare the straight line distance between two points on your hand line to the distance between those two points along the perimeter (geodesic distance). For this you would need an ordered list of points along the perimeter.
Along regions of high curvature, the straight line distance between two points will be smaller than the number of pixels between those two points along the perimeter.
For example, you could check perimeter pixels separate by 10 pixels. That is, you would search through the list and compare the point at index N and the point index N+10. (You'll need to loop back around to the beginning of the list as you approach the end.) If the straight line distance between these two points is nearly 10 pixels as well, then you know those points lie on a straight section of the perimeter. If the straight line distance is much smaller than 10, then you know the perimeter curves in some fashion between those points. Whether you check pixels that are 5, 10, 20, or 30 items apart in the list will depend on the resolution of your image and the curves you're looking for.
This technique is useful because it's simple and quick to implement. Maybe it would work well enough for your needs.
Yet another way: simplify the outline to small line segments, and then you can calculate the line-line angle between adjacent segments. To simplify the curves, implement the Ramer-Douglas-Puecker algorithm. A little experimentation will reveal what parameter settings will work for your application.
https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
Finally, you could look into piecewise curve fitting: a curve would be fitted to small segments of the outline. This can get very complicated, and researchers continue to find ways to decompose complex figures into a limited number of more basic shapes or curves. I recommend trying the simplest technique and then only adding complexity if you need it.
I have to calculate the area, or length of the objects present in the frame.
As i use the 2d camera, the distance from the camera can't be found.
In this case, i am planning to draw a constant(X CM) line in the back ground where its length is known in CM/M.
Please find the attachment for a sample input image. (Yellow Line is a Constant line)
Consider that a person or an object stands in front of a wall, where the constant line is drawn.
Is there any way to calculate the distance of other objects with reference to the constant line?
First, it isn't a line. It is a parcel. A line is non-physical. The parcel of pixels has both area and length. The natural unit of measurement of images is pixels. Units of length are both non-physical and require assumptions.
Second, you can do a thresholded 2-d convolution. PIV-sleuth uses 2d convolution. It can allow some faster, more accurate measurement in images. Peak intensity will tell you something about the length or area. You can also use row-sum and column sum very quickly to get ideas of lengths. It helps if the images are aligned to the pixel-axes in your image. Use of affine transformations can help you test various rotations for suitability.
I want to detect the edge only in the red marked region as shown in the image below:
A few suggestions. I assume that the red region is input by mouse and that you now have a mask of the region that you want to include in the edge search.
My proposed algorithm
1. Do Edge detection
2. Write your own Hough routine but only count edges if they should be included according to the mask.
3. Pick the edge with the best score in the Hough space.
Of course you don't need to run the edge detection on the complete image but if you don't make sure that you handle the border of your search area (so you don't get edges there). Simply mirroring the area might work.
Update
Okay, different approach:
Use the hough routines in matlab. houghlines, hough, houghpeaks are the relevant functions. If only one line intersects your region of interest, you are done. The line is the result you want.
If more than one line intersect the region of interest, you need to do a bit more. I'd suggest counting the number of pixels along the line that are within the ROI. So, if the line intersects the ROI for 10 pixels, that line's score is 10. Do this for all lines and then pick the line with the highest score.
Note that none of the approaches are optimized for speed. However, they are easy to understand.
I have a binary image, i want to detect/trace curves in that image. I don't know any thing (coordinates, angle etc). Can any one guide me how should i start? suppose i have this image
I want to separate out curves and other lines. I am only interested in curved lines and their parameters. I want to store information of curves (in array) to use afterward.
It really depends on what you mean by "curve".
If you want to simply identify each discrete collection of pixels as a "curve", you could use a connected-components algorithm. Each component would correspond to a collection of pixels. You could then apply some test to determine linearity or some other feature of the component.
If you're looking for straight lines, circular curves, or any other parametric curve you could use the Hough transform to detect the elements from the image.
The best approach is really going to depend on which curves you're looking for, and what information you need about the curves.
reference links:
Circular Hough Transform Demo
A Brief Description of the Application of the Hough
Transform for Detecting Circles in Computer Images
A method for detection of circular arcs based on the Hough transform
Google goodness
Since you already seem to have a good binary image, it might be easiest to just separate the different connected components of the image and then calculate their parameters.
First, you can do the separation by scanning through the image, and when you encounter a black pixel you can apply a standard flood-fill algorithm to find out all the pixels in your shape. If you have matlab image toolbox, you can find use bwconncomp and bwselect procedures for this. If your shapes are not fully connected, you might apply a morphological closing operation to your image to connect the shapes.
After you have segmented out the different shapes, you can filter out the curves by testing how much they deviate from a line. You can do this simply by picking up the endpoints of the curve, and calculating how far the other points are from the line defined by the endpoints. If this value exceeds some maximum, you have a curve instead of a line.
Another approach would be to measure the ratio of the distance of the endpoints and length of the object. This ratio would be near 1 for lines and larger for curves and wiggly shapes.
If your images have angles, which you wish to separate from curves, you might inspect the directional gradient of your curves. Segment the shape, pick set of equidistant points from it and for each point, calculate the angle to the previous point and to the next point. If the difference of the angle is too high, you do not have a smooth curve, but some angled shape.
Possible difficulties in implementation include thick lines, which you can solve by skeleton transformation. For matlab implementation of skeleton and finding curve endpoints, see matlab image processing toolkit documentation
1) Read a book on Image Analysis
2) Scan for a black pixel, when found look for neighbouring pixels that are also black, store their location then make them white. This gets the points in one object and removes it from the image. Just keep repeating this till there are no remaining black pixels.
If you want to separate the curves from the straight lines try line fitting and then getting the coefficient of correlation. Similar algorithms are available for curves and the correlation tells you the closeness of the point to the idealised shape.
There is also another solution possible with the use of chain codes.
Understanding Freeman chain codes for OCR
The chain code basically assigns a value between 1-8(or 0 to 7) for each pixel saying at which pixel location in a 8-connected neighbourhood does your connected predecessor lie. Thus like mention in Hackworths suggestions one performs connected component labeling and then calculates the chain codes for each component curve. Look at the distribution and the gradient of the chain codes, one can distinguish easily between lines and curves. The problem with the method though is when we have osciallating curves, in which case the gradient is less useful and one depends on the clustering of the chain codes!
Im no computer vision expert, but i think that you could detect lines/curves in binary images relatively easy using some basic edge-detection algorithms (e.g. sobel filter).