I am trying to detect the objects in the following image and calculate the centroids and orientation of each object in the image.
My approach so far has been to remove the background from the image and isolate the objects. However, the segmentation is not precise.
What other approaches can I take? Will SURF detection, using reference images, be a more accurate approach?
My attempt:
I = imread('image.jpg');
figure, imshow(I)
background = imopen(I,strel('disk',15));
I2 = I - background;
figure, imshow(I2);
I3 = imadjust(rgb2gray(I2));
figure, imshow(I3);
level = graythresh(I3);
bw = im2bw(I3,level);
bw = bwareaopen(bw, 50);
figure, imshow(bw)
Nice start.
I would do the following:
1- pre process your image
apply some filters and some convolutions to remove noise; dilation and erosion for instance.
2- after calculating the thresholds, try to fill in the masks so that you closed "objects". I think imfill - http://www.mathworks.com/help/images/ref/imfill.html - will help you doing this.
Also take a look at - http://www.mathworks.com/help/images/image-enhancement-and-analysis.html -
Related
I have a series of images (*.bmp, in colour) depicting the evolution of the downstream meniscus during a slot-die coating process (see exemplary image in Figure 1).
Now I would like to fit curves to the respective downstream meniscus in every single image (ideally via some sort of batch processing) using Matlab. The purpose being
to obtain the equation of each of the fits in order to be able to
quantify the change in the shape of the meniscus
and to create a plot that includes all of the fit curves to illustrate the
changes in the shape of the meniscus graphically.
I have started working on a code that does that for a single image. This is how far I got:
I = imread('//ImagePath');
Icrop = imcrop(I);
subplot(2,2,1);
imshow(I);
title('Original Image');
subplot(2,2,2);
imshow(Icrop);
title('Cropped Image');
BW = im2bw(Icrop, graythresh(Icrop));
subplot(2,2,3);
imshow(BW);
title('Cropped BW Image');
[B,L] = bwboundaries(BW,'noholes');
subplot(2,2,4);
imshow(L);
title('Crop Image with Boundaries Detected');
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'r', 'LineWidth', 2)
end
Using this code, I currently get the results shown in Figure 2.
The questions I have are the following ones:
How can I avoid getting the straight horizontal / vertical part of
the red line?
How can I fit a curve to the red line following the
shape of the meniscus?
How do I do all of that for multiple images
at once? (they all have the same size and show the same content
besides the little variations in the shape of the meniscus)?
How can I then plot all the fit curves into one image?
I am fairly new to Matlab, so I would naturally appreciate any kind of hints / help / advice you can provide!
Thanks a lot! :)
P.S.: I know very well that the image quality is not the best.
I have this BW image:
And using the function RegionProps, it shows that some objetcs are connected:
So I used morphological operations like imerode to separte the objects to get their centroids:
Now I have all the centroids of each object separated, but to that I lost a lot of information when eroding the region, like you can see in picture 3 in comparison with picture 1.
So I was thinking if is there anyway to "dilate" the picture 3 till get closer to picture 1 but without connecting again the objects.
You might want to take a look at bwmorph(). With the 'thicken', inf name-value pair it will thicken the labels until they would overlap. It's a neat tool for segmentation. We can use it to create segmentation borders for the original image.
bw is the original image.
labels is the image of the eroded labels.
lines = bwmorph(labels, 'thicken', inf);
segmented_bw = bw & lines
You could also skip a few phases and achieve similiar results with a marker based watershed. Or even better, as the morphological seesaw has destroyed some information as seen on the poorly segmented cluster on the lower right.
You can assign each white pixel in the mask to the closest centroid and work with the resulting label map:
[y x]= find(bw); % get coordinates of mask pixels
D = pdist2([x(:), y(:)], [cx(:), cy(:)]); % assuming cx, cy are centers' coordinates
[~, lb] = min(D, [], 2); % find index of closest center
lb_map = 0*bw;
lb_map(bw) = lb; % should give you the map.
See pdist2 for more information.
I have an image like this. And I want to find the location of notes. What is the best way to find them ? (They are not circle and they are so small so circlefinder can't find them !)
Image of Notes !
Here is a bit of code to get you going...that's not perfect but it was a lof of fun haha.
What I did is to erode the image with a disk structuring element until what was left in the image was shapes the looked the most like circles. Then I eroded again but this time with a line structuring element oriented at an angle close to that of the notes; I figured it's about 15 degrees.
After that, call regionprops to get the centroids, and then plot them.
Code:
clear
clc
BW = im2bw(imread('Notes.png'));
BW = imclearborder(BW);
%//Erode the image with a disk structuring element to obtain circleish
%// shapes.
se = strel('disk',2);
erodedBW = imerode(BW,se);
Here erodedBW looks like this:
%// Erode again with a line oriented at 15 degrees (to ~ match orientation of major axis of notes...very approximate haha)
se2 = strel('line',5,15);
erodedBW2 = imerode(erodedBW,se2);
erodedBW2 looks like this:
Then find centroids and plot them
S = regionprops(erodedBW2,'Centroid');
figure;
imshow(BW)
hold on
for k = 1:numel(S)
scatter(S(k).Centroid(:,1), S(k).Centroid(:,2),60,'filled')
end
Output:
Empty notes are not detected but that's manageable using other morphological operations I guess.
Hope that helps!
I am trying to find and extract the boundary of a binary image in matlab, without using something like bwboundaries.
Is there a more manual way to do this, using loops maybe and changing the colour of the boundary pixels.
Any help would be appreciated.
Since it is binary so you can use two loop pairs.
-first ensure that image is binary.(just in case it is greyscale threshold it)
-use the first loop pair for height and one for width and trace any change i.e if a pixel is black and the next pixel is white draw that point onto a new mat.(i.e mark that point as 255 or of any colour you desire)
-Do the same for width and height and store it into another mat.
-Then add both the mats and average out the result.
This is the manual way and it may not be efficient.But it helps you modify the process to get you the exact edges.
(Source:I had used this technique for detecting perspective transformed rectangles containing bar code in java since canny edge used to give out too many edges due to bar code lines)
I don't understand what you mean by manual way. Is it mean pixel by pixel or anything else? Anyway try this example and fully explain your question that what you really want.
d1 = double(imread('cameraman.TIF'))./255; %# Load the image, scale from 0 to 1
subplot(2,2,1); imshow(d1); title('d1'); %# Plot the original image
d = edge(d1,'canny',.6); %# Perform Canny edge detection
subplot(2,2,2); imshow(d); title('d'); %# Plot the edges
ds = bwareaopen(d,40); %# Remove small edge objects
subplot(2,2,3); imshow(ds); title('ds'); %# Plot the remaining edges
iout = d1;
BW = ds;
iout(:,:,1) = iout; %# Initialize red color plane
iout(:,:,2) = iout(:,:,1); %# Initialize green color plane
iout(:,:,3) = iout(:,:,1); %# Initialize blue color plane
iout(:,:,2) = min(iout(:,:,2) + BW, 1.0); %# Add edges to green color plane
iout(:,:,3) = min(iout(:,:,3) + BW, 1.0); %# Add edges to blue color plane
subplot(2,2,4); imshow(iout); title('iout'); %# Plot the resulting image
you can also track boundary by using Blob method but it depend on your requirements.
I'm having trouble separating cells in microscope images. When I apply a watershed transform I end up cutting up cells into many pieces and not merely separating them at the boundary/minimum.
I am using the bpass filter from http://physics.georgetown.edu/matlab/code.html.
bp = bpass(image,1,15);
op = imopen(bp,strel('ball',10,700));
bw = im2bw(bp-op,graythresh(bp-op));
bw = bwmorph(bw,'majority',10);
bw = imclearborder(bw);
D = bwdist(~bw);
D = -D;
D(~bw) = -Inf;
L = watershed(D);
mask = im2bw(L,1/255);
Any ideas would be greatly appreciated! You can see that my cells are being split apart too much in the final mask.
Here is the kind of image I'm trying to watershed. It's a 16bit image so it looks like it is all black.
Starting fluorescent image
Final image mask:
I separated the cells manually here:
Finding the centers of the cells should be relatively straight-forward: finding a local maxima of the intensity. Using these points as seeds for the watershed, you might find this tutorial useful.
Some morphologcal operations you might find useful are:
- imimposemin - forcing a seed point to be a local min when computing the watershed transform.
- imregionalmax - finding local maxima of intensity image.