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.
Related
There are many ways to implement math morph on binary image like imerode and imdilate. Its also used to detect different object/shape using this simple operations on binary image but the problem that i am facing right now is to apply this simple operation i.e erode, dilate and many on grey scale image with out convert them into binary image.
Selement = strel('disk',5);//disk type element used in morphology
erodeimage = imerode(image,selement);//this is only implement on binary image
Above code is for binary math morph how do i implement same concept on grey scale image.
Note: If your have any resources regarding gray scale math morph kindly provide it or provide useful link
There should be a mathematical morphology (MM) library in MatLab. MM operations on binary images are shown as example/illustration but are performed most of the time as gray level.
I think that the fastest C++ library is SMIL, and you can call it from MatLab. An other fast one in C is that one (optimized opening/closing in a single pass).
But if you want to understand a dilation in gray level, here is how it works: for a given pixel p you analyze the value of all the pixels in its neighborhood (defined by the structuring element), and you affect to p the highest value in the neighborhood. You do it for each pixel in your image. See the formula.
That's in fact a rank filter like the median, but instead of taking the median value, you take the max (or min for the erosion). Obviously that the basic definition and it exits faster algorithms, like the one developed in the library I pointed.
need some help here on image processing. I'm using Matlab and try to segment the following figure based on the two major peaks (in yellow). The color yellow means higher value and blue means low value (on z-axis, or image color from 0 to 1 for your convenience). The ideal cut is roughly the line from point (1,75) to (120,105). But I want a systematic way to derive this rather than by observation.
My intuition was to first identify the two peaks (based on this), and then classify each point/pixel on this figure to the two peaks (the metric here is to compute the shortest Euclidean distance to the edge of the two peaks).
And I end up with the following fig.
As you can see, the cut is pretty much a straight line, which I'm not quite satisfied. Maybe I can use the orientation of the peak circle and somehow tilt the line.. but I'm not sure how to do so? Any clues? Thanks.
This is an Image segmentation problem.
you can use GMM Gaussian of Mixture Model to model the image.
in your case the number of components will be 2.
after you model the image by using this mixture, you can find the probability of each pixel P(pixel x belong to the first component or the second component)
check
http://www.mathworks.com/matlabcentral/newsreader/view_thread/272162
http://www.mathworks.com/help/stats/cluster-data-from-mixture-of-gaussian-distributions.html
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.
I have an image like this:
What I want to do is to find the outer edge of this cell and the inner edge in the cell between the two parts of different colors.
But this image contains to much detail I think, and is there any way to simplify this image, remove those small edges and find the edges I want?
I have tried the edge function provided by matlab. But it can only find the outer edge and disturbed by those detailed edges.
This is a very challenging work due to the ambiguous boundaries and tiny difference between red and green intensities. If you want to implement the segmentation very precisely and meet some medical requirements, Shai's k-means plus graph cuts may be one of the very few options (EM algorithm may be an alternative). If you have a large database that has many similar images, some machine learning methods might help. Otherwise, I just wrote a very simple code to roughly extract the internal red region for you. The boundary is not that accurate since some of the green regions are also included.
I1=I;
I=rgb2hsv(I);
I=I(:,:,1); % the channel with relatively large margin between green and red
I=I.*(I<0.25);
I=imdilate(I, true(5));
% I=imfill(I,'holes'); depends on what is your definition of the inner boundary
bw=bwconncomp(I);
ar=bw.PixelIdxList;
% find the largest labeled area,
n=0;
for i=1:length(ar)
if length(ar{i})>n
n=length(ar{i});
num=i;
end
end
bw1=bwlabel(I);
bwfinal(:,:,1)=(bw1==num).*double(I1(:,:,1));
bwfinal(:,:,2)=(bw1==num).*double(I1(:,:,2));
bwfinal(:,:,3)=(bw1==num).*double(I1(:,:,3));
bwfinal=uint8(bwfinal);
imshow(bwfinal)
It seems to me you have three dominant colors in the image:
1. blue-ish background (but also present inside cell as "noise")
2. grenn-ish one part of cell
3. red-ish - second part of cell
If these three colors are distinct enough, you may try and segment the image using k-means and Graph cuts.
First stage - use k-means to associate each pixels with one of three dominant colors. Apply k-means to the colors of the image (each pixel is a 3-vector in your chosen color space). Run k-means with k=3, keep for each pixel its distance to centroids.
Second stage - separate cell from background. Do a binary segmentation using graph-cut. The data cost for each pixel is either the distance to the background color (if pixel is labeled "background"), or the minimal distance to the other two colors (if pixel is labeled "foreground"). Use image contrast to set the pair-wise weights for the smoothness term.
Third stage - separate the two parts of the cell. Again do a binary segmentation using graph-cut but this time work only on pixels marked as "cell" in the previous stage. The data term for pixels that the k-means assigned to background but are labeled as cell should be zero for all labels (these are the "noise" pixels inside the cell).
You may find my matlab wrapper for graph-cuts useful for this task.
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