I have the image includes circular, elipsoidal, square objects and somethings like these. I want to get only circual objects. I applyed a filter by using Solidity and Enccentricity levels of objets but I could not remove square objects. Square objects which have not sharp corners have nearly same Solidity and Enccentricity level with circular objects.
My question is that is there any other parameter or way to detect square objects?
You can compare the area of the mask to its perimeter using the following formula
ratio = 4 * pi * Area / ( Perimeter^2 )
For circles this ration should be very close to one, for other shapes it should be significantly lower.
See this tutorial for an example.
The rationale behind this formula: circles are optimal in their perimeter-area ratio - max area for given perimeter. Given Perimeter, you can estimate radius of equivalent circle by Perimeter = 2*pi*R, using this estimated R you can compute the "equivalent circle area" using eqArea = pi*R^2. Now you only need to check the ratio between the actual area of the shape and the "equivalent area" computed.
Note: since Area and Perimeter of objects in mask are estimated based on the pixel-level discretization these estimates may be quite crude especially for small shapes. Consider working with higher resolution masks if you notice quantization/discretization errors.
There exists a Hough transform (imfindcircles) in order to find circles within an image which is what you needed in the first place.
Related
I am currently taking my first steps in the field of computer vision and image processing.
One of the tasks I'm working on is finding the center coordinates of (overlapping and occluded) circles.
Here is a sample image:
Here is another sample image showing two overlapping circles:
Further information about the problem:
Always a monochrome, grayscale image
Rather low resolution images
Radii of the circles are unknown
Number of circles in a given image is unknown
Center of circle is to be determined, preferably with sub-pixel accuracy
Radii do not have to be determined
Relative low overhead of the algorithm is of importance; the processing is supposed to be carried out with real-time camera images
For the first sample image, it is relatively easy to calculate the center of the circle by finding the center of mass. Unfortunately, this is not going to work for the second image.
Things I tried are mainly based on the Circle Hough Transform and the Distance Transform.
The Circle Hough Transform seemed relatively computationally expensive due to the fact that I have no information about the radii and the range of possible radii is large. Furthermore, it seems hard to identify the (appropriate) pixels along the edge because of the low resolution of the image.
As for the Distance Transform, I have trouble identifying the centers of the circles and the fact that the image needs to be binarized implies a certain loss of information.
Now I am looking for viable alternatives to the aforementioned algorithms.
Some more sample images (images like the two samples above are extracted from images like the following):
Just thinking aloud to try and get the ball rolling for you... I would be thinking of a Blob, or Connected Component analysis to separate out your blobs.
Then I would start looking at each blob individually. First thing is to see how square the bounding box is for each blob. If it is pretty square AND the centroid of the blob is central within the square, then you have a single circle. If it is not square, or the centroid is not central, you have more than one circle.
Now I am going to start looking at where the white areas touch the edges of the bounding box for some clues as to where the centres are...
As you may have already noticed, in the newer versions of matlab the
boundary function (which computes the boundary for a set of 2d or 3d points) has been improved.
Now it is possible to give the function a parameter called 'shrink factor'. If the shrink factor is 0, then the boundary traced is the traditional convex hull. The boundary is more shrinked when the shrink parameter is bigger. The default value for the shrink factor is 0.5, in case you don't specify any value.
So, I understand its use and what it does (actually I've already used the function in a project), but I don't know how it works. What are the geometrical principles of this shrink factor?
Thanks!
Found your question while loooking for the answer myself. Hope you've solved it by now. I've figured it out and in case someone else finds this question, here's my understanding of the boundary() function.
The boundary function is an implementation of alpha shapes. Using alpha shapes, a set of points can be assigned a polygon by using a set of circles of a specific radius:
imagine an arbitrary shape drawn around the points and proceed to remove as much of this shape as possible using circles of a specific radius. Continue as long as possible, without enclosing any points. A small radius will mean more "material" can be removed, a larger radius means less "removal", i.e. a small radius creates a close cropped shape whereas an infinite radius recreates a convex hull of the set. The points determined to be edge points are then conencted with straight edges. This can create hollow areas inside the point set.
See e.g. http://doc.cgal.org/latest/Alpha_shapes_2/index.html
MATLAB has an alphashape() function which calculates alphashapes with all possible alpha radii giving different shapes. This is used in the boundary function.
boundary() workflow:
(1) Create alphashape
(2) Find critical alpha radius, needed to create a single region for alpha shape
(3) Extract all alphavalues that create unique shapes above this critical value
(4) Use the shrink factor, S, to select a single alpha value to use.
Example: with S=0.25, use alpha radius with index (1-.25)*numel(alphavalues>=alpha_crit). This creates an alpha shape
using the 75th smallest alpha radius giving rise to a single region
(for S=0.25).
If S=1 (max shrink), gives the lowest alpha-radius that gives a single
region for the alpha-shape.
If S=0 (no shrink), gives the maximum alpha-radius that gives a unique
shape. (Incraesing alpha radius further has no effect).
(5) set the threshold for filling in holes in the alphashape to be the same as the alphashape's area, i.e. fill in all holes
(6) Return the indices of the original point cloud correspocing to the vertices of this alphashape.
The relevant section of the boundary.m file (lines 79-86)
Acrit = shp.criticalAlpha('one-region'); %alpha-radius required for single region
spec = shp.alphaSpectrum();%all alphavalues
idx = find(spec==Acrit);
subspec = spec(1:idx);%alphavalues up to criticalAlpha
subspec = flipud(subspec);%reverse order
idx = max(ceil((1-S)*numel(subspec)),1); %find index from shrink factor
alphaval = subspec(idx);
shp.Alpha = alphaval; %set alpha value of alpha shape
shp.HoleThreshold = areavol; % remove holes in interior
Hope this is clear enough and useful to someone.
I use MATLAB R2014b
YiraDati's answer provides great details.
You can also type "open boundary" in command windows, and then all procedures are written in boundary function. And all subfunctions shown in boundary function are accessible using matlab documentation, like area(), criticalAlpha(), alphaSpectrum(), etc...
I have two images – mannequin with and without garment.
Please refer sample images below. Ignore the jewels, footwear on the mannequin, imagine the second mannequin has only dress.
I want to extract only the garment from the two images for further processing.
The complexity is that there is slight displacement in the position of camera when taking the two pictures. Due to this simple subtraction to generate the garment mask will not work.
Can anyone tell me how to handle it?
I think I need to do registration between the two images so that I can extract only the garment from the image?
Any references to blogs, articles and codes is highly appreciated.
--
Thanks
Idea
This is an idea of how you could do it, I haven't tested it but my gut tells me it might work. I'm assuming that there will be slight differences in the pose of the manequin as well as the camera attitude.
Let the original image be A, and the clothed image be B.
Take the difference D = |A - B|, apply a median filter that is proportional to the largest deviation you expect from pose and camera attitude error: Dmedian = Median(D, kernelsize).
Quantize Dmedian into a binary mask Dmask = Q(Dmedian, threshold) using appropriate threshold values to obtain an approximate mask for the garment (this will be smaller than the garment itself due to the median filter). Reject any shapes in Dmedian that have too small area by setting their pixels to 0.
Expand the shape(s) in Dmask proportionally to the size of the median kernel into Emask=expand(Dmask, k*kernelsize). Then construct the difference in the masks Fmask=|Dmask - Emask| which now contains areas of pixels where the garment edge is expected to be. For every pixel in Fmask which is in this area, find the correlation Cxy between A and B using a small neighbourhood, store the correlations into an image C=1.0 - Corr(A,B, Fmask, n).
Your final garment mask will be M=C+Dmask.
Explanation
Since your image has nice and continuous swatches of colour, the difference between the two similar images will be thin lines and small gradients where the pose and camera attitude is different. When taking a median filter of the difference image over a sufficiently large kernel, these lines will be removed because they are in a minority of the pixels.
The garment on the other hand will (hopefully) have a significant difference from the colors in the unclothed version. And will generate a bigger difference. Thresholding the difference after the median filter should give you a rough mask of the garment that is undersized dues to some of the pixels on the edge being rejected due to their median values being too low. You could stop here if the approximation is good enough for you.
By expanding the mask we obtained above we get a probable region for the "true" edge. The above process has served to narrow our search region for the true edge considerably and we can apply a more costly correlation search between the images along this edge to find where the garment is. High correlation means no carment and low correlation means garment.
We use the inverted correlation as an alpha value together with the initially smaller mask to obtain a alpha valued mask of the garment that can be used for extracting it.
Clarification
Expand: What I mean by "expanding the mask" is to find the contour of the mask region and outsetting/growing/enlarging it to make it larger.
Corr(A,B,Fmask,n): Is just an arbitrarily chosen correlation function that gives correlation between pixels in A and B that are selected by the mask Fmask using a region of size n. The function returns 1.0 for perfect match and 0.0 for anti-match for each pixel tested. A good function is this pseudocode:
foreach px_pos in Fmask where Fmask[px_pos] == 1
Ap = subregion(A, px_pos, size) - mean(mean(A));
Bp = subregion(B, px_pos, size) - mean(mean(B))
Cxy = sum(sum(Ap .* Bp))*sum(sum(Ap .* Bp)) / (sum(sum(Ap.*Ap))*sum(sum(Bp.*Bp)))
C[px_pos] = 1.0 - Cxy;
end
where subregion selects a region of size size around the pixel with position px_pos.
You can see that if Ap == Bp then Cxy=1
I would like to be able to process a close-up image of a mango tree so that I can identify and count the mangoes. A mango is roughly an oval or ellipse shape that is uniquely different from the leaves and branches in the image. I would like to be able to count mangos that might be 20% covered by other objects (but still obvious to the human eye.) I believe there is an algorithm in MatLab that could do this and I would appreciate any help or suggestions.
I think that the more robust solution for that problem is to segment by color the mangoes from the background (i.e. tree leaves) and count the number of connected components in the resulting binary image. As btown pointed out, you can get the connected components of a binary image by using the bwconncomp and labelmatrix functions.
To segment the mangoes by color, first convert the image to HSV color space and then perform a binarization using the hue component. I believe that the hue component from the mangoes will be different from other parts of the image. This blog post gives some insight on how to do that in Matlab.
Perhaps you could:
Pre process the image (greyscale/threshold etc.).
Extract all the countours/connected components from the binary image.
Calculate the area and perimeter of each contour/connected component.
Calculate the shape factor/roundness using:
Shape Factor – (4 * PI * Area) / (Perimeter^2). This gives an
indication as to the objects shape. Circles have the greatest area to
perimeter ratio and this formula will approach a value of 1 for a
perfect circle. Squares are around 0.78. A thin thread-like object
would have the lowest shape factor approaching 0.
Roundness – (Perimeter^2) / 4 * PI * Area). This gives the
reciprocal value of Shape Factor for those that are used to using it.
A circle will have a value slightly greater than or equal to 1. Other
shapes will increase in value.
So you could approximate a shape factor for an "ideal" mango and see if any of the components lie inside the approximation?
See this for more details.
I created some MATLAB code, that find somes shapes in an image
using regionpros and bwbounaries functions.
I have:
STATS = regionprops(L, 'all');
and from STATS I could easily find all my shapes Area and Perimeter.
My problem is the following: I want to find the "square" shapes and I do
in all shapes the following calculation 16 * area / (perimeter * perimeter),
if this value is near one then I "may" have a square. But other shapes too like
circles or rectangles are near one too. (Also some squares could be rotated
in the image).
Is there a better way to distinguish the shapes (like circles, triangles ...)?
Matlab has a function
procrustes(X,Y)
which will compute distance between two shapes based on the types of transformations it would take to move the points defined by X onto the points defined by Y. For many shape classification tasks, minimizing this distance is a useful way of categorizing noisy instances of shapes. If your problem has 'perfect' shapes, this should work extremely well. Just have Y fixed as a perfect square, and any time that the linear transformation from X to Y is a pure scaling, then you know X is also a square. You could do some simple logical checking to select only shapes satisfying this sort of property.