how to identify an object appears homogenously white - matlab

I have a segmented image. i need to verify the intensity variation of the ellipse like structure present in the image. I need to check whether that ellipse is homogeneously white
original image
ellipse like structure is inside the rectangle
my segmented image is
i want to compare the original image (which is homogeneous white) with the segmented region.

regionprops is perfect for this sort of task. You can pass it your segmented binary image, and your original image to retrieve a list of the pixels in each region (presuming each region is not connected, as shown in your sample image). These will be in the form of a n x 1 vector for each region, returned as a struct array.
stats = regionprops(BW, I, 'PixelValues');
(You may want to retrieve other values returned by regionprops, like BoundingBox or Centroid, to help identify which set of pixels belongs to which region more easily. Consult the documentation to see what options are available.).
You can then define some statistical function to show the variation within each region, for example, to calculate the variance and standard deviation for each:
for n = 1:length(stats)
stats(n).var = var(stats(n).PixelValues);
stats(n).std = std(stats(n).PixelValues);
end
If you have some other specific definition of "intensity variation" in mind, then you need to develop some function that calculates it, then just call that instead of a built in like var or std.

Related

Crop an image using multiple coordinates in Matlab

I used the "imfreehand" to crop an irregular shape and save its positions into a variable. This position variable is a 85*2 double matrix (85 points, X and Y coordinates). Now, I want to use the same position to crop another image (different layer of the image, but the location of the objects is the same). The functions I can find all requires rectangle positions (X1,X2,Y1,Y2). In my situation, I have 82 different (X,Y) coordinates, how can I use the position information to crop a new image?
From what I understand, you want to take the coordinates created by imfreehand(...) to create a cropable object on another image. You can use the function impoly(hparent,position) for this purpose.
The MathWorks page provides an example to guide you on its usage.

Deleting objects based on area calculation

I have a image with small objects. I have calculated their areas using
area=regionprops(CC,'Area');
CC is the connected components returned by
CC=bwconncomp(BW);
Now i need to remove objects with area less than 15 (set them to zero in the original image BW).
I know i can do this with a more simpler ways other than that from regionprops, but I need to do this from the output of regionprops, because I will extract other properties that is supported by regionprops and filter again the image according to these extracted features in a similar way. Can anyone help me with this task?
After the two commands you show,
CC=bwconncomp(BW);
area=regionprops(CC,'Area');
area is a struct array where area(ii).Area is the area for object ii. This corresponds to the connected component given by CC.PixelIdxList{ii}.
You can find the indices with a small area by
I = find([area.Area] < 15);
Then,
CC.PixelIdxList{I}
gives a comma-separated list of vectors with pixel indices. You can join these vectors into a single vector using cat:
pixels = cat(1,CC.PixelIdxList{I});
Now all that is left is setting those pixels to 0 in the input image:
BW(pixels) = 0;

Get the middle/center pixel of a segmentation

I have a segmented image. I wish to extract the middle pixel(s) of each segmentation. The goal is to extract the mean color from the middle pixel.
The following diagram illustrates what I mean by 'middle pixel':
The alternative middle pixels are also acceptable.
What algorithms/functions are available in Matlab to achieve something similar to this? Thanks.
If I'm understanding what you want correctly, you're looking for the centroid. MATLAB has the regionprops function which measures the properties of separate binary objects as long as the objects.
You can use the Centroid property. Assuming your image is stored in im and is binary, something like this will do:
out = regionprops(im, 'Centroid');
The output will be a structure array of N elements where N corresponds to the total number of objects found in the image. To access the ith object's centroid, simply do:
cen = out(i).Centroid;
If you wish to collect all centroids and place them perhaps in a N x 2 numeric array, something like this would work:
out = reshape([out.Centroid], 2, []).';
Each row would be the centroid of an object found in the image. Take note that an object is considered to be a blob of white pixels that are connected to each other.

Matlab: separate connected components

I was working on my image processing problem with detecting coins.
I have some images like this one here:
and wanted to separate the falsely connected coins.
We already tried the watershed method as stated on the MATLAB-Homepage:
the-watershed-transform-strategies-for-image-segmentation.html
especially since the first example is exactly our problem.
But instead we get a somehow very messed up separation as you can see here:
We already extracted the area of the coin using the regionprops Extrema parameter and casting the watershed only on the needed area.
I'd appreciate any help with the problem or even another method of getting it separated.
If you have the Image Processing Toolbox, I can also suggest the Circular Hough Transform through imfindcircles. However, this requires at least version R2012a, so if you don't have it, this won't work.
For the sake of completeness, I'll assume you have it. This is a good method if you want to leave the image untouched. If you don't know what the Hough Transform is, it is a method for finding straight lines in an image. The circular Hough Transform is a special case that aims to find circles in the image.
The added advantage of the circular Hough Transform is that it is able to detect partial circles in an image. This means that those regions in your image that are connected, we can detect them as separate circles. How you'd call imfindcircles is in the following fashion:
[centers,radii] = imfindcircles(A, radiusRange);
A would be your binary image of objects, and radiusRange is a two-element array that specifies the minimum and maximum radii of the circles you want to detect in your image. The outputs are:
centers: A N x 2 array that tells you the (x,y) co-ordinates of each centre of a circle that is detected in the image - x being the column and y being the row.
radii: For each corresponding centre detected, this also gives the radius of each circle detected. This is a N x 1 array.
There are additional parameters to imfindcircles that you may find useful, such as the Sensitivity. A higher sensitivity means that it is able to detect circular shapes that are more non-uniform, such as what you are showing in your image. They aren't perfect circles, but they are round shapes. The default sensitivity is 0.85. I set it to 0.9 to get good results. Also, playing around with your image, I found that the radii ranged from 50 pixels to 150 pixels. Therefore, I did this:
im = im2bw(imread('http://dennlinger.bplaced.net/t06-4.jpg'));
[centers,radii] = imfindcircles(im, [50 150], 'Sensitivity', 0.9);
The first line of code reads in your image directly from StackOverflow. I also convert this to logical or true black and white as the image you uploaded is of type uint8. This image is stored in im. Next, we call imfindcircles in the method that we described.
Now, if we want to visualize the detected circles, simply use imshow to show your image, then use the viscircles to draw the circles in the image.
imshow(im);
viscircles(centers, radii, 'DrawBackgroundCircle', false);
viscircles by default draws the circles with a white background over the contour. I want to disable this because your image has white circles and I don't want to show false contouring. This is what I get with the above code:
Therefore, what you can take away from this is the centers and radii variables. centers will give you the centre of each detected circle while radii will tell you what the radii is for each circle.
Now, if you want to simulate what regionprops is doing, we can iterate through all of the detected circles and physically draw them onto a 2D map where each circle would be labeled by an ID number. As such, we can do something like this:
[X,Y] = meshgrid(1:size(im,2), 1:size(im,1));
IDs = zeros(size(im));
for idx = 1 : numel(radii)
r = radii(idx);
cen = centers(idx,:);
loc = (X - cen(1)).^2 + (Y - cen(2)).^2 <= r^2;
IDs(loc) = idx;
end
We first define a rectangular grid of points using meshgrid and initialize an IDs array of all zeroes that is the same size as the image. Next, for each pair of radii and centres for each circle, we define a circle that is centered at this point that extends out for the given radius. We then use these as locations into the IDs array and set it to a unique ID for that particular circle. The result of IDs will be that which resembles the output of bwlabel. As such, if you want to extract the locations of where the idx circle is, you would do:
cir = IDs == idx;
For demonstration purposes, this is what the IDs array looks like once we scale the IDs such that it fits within a [0-255] range for visibility:
imshow(IDs, []);
Therefore, each shaded circle of a different shade of gray denotes a unique circle that was detected with imfindcircles.
However, the shades of gray are probably a bit ambiguous for certain coins as this blends into the background. Another way that we could visualize this is to apply a different colour map to the IDs array. We can try using the cool colour map, with the total number of colours to be the number of unique circles + 1 for the background. Therefore, we can do something like this:
cmap = cool(numel(radii) + 1);
RGB = ind2rgb(IDs, cmap);
imshow(RGB);
The above code will create a colour map such that each circle gets mapped to a unique colour in the cool colour map. The next line applies a mapping where each ID gets associated with a colour with ind2rgb and we finally show the image.
This is what we get:
Edit: the following solution is more adequate to scenarios where one does not require fitting the exact circumferences, although simple heuristics could be used to approximate the radii of the coins in the original image based on the centers found in the eroded one.
Assuming you have access to the Image Processing toolbox, try imerode on your original black and white image. It will apply an erosion morphological operator to your image. In fact, the Matlab webpage with the documentation of that function has an example strikingly similar to your problem/image and they use a disk structure.
Run the following code (based on the example linked above) assuming the image you submitted is called ima.jpg and is local to the code:
ima=imread('ima.jpg');
se = strel('disk',50);
eroded = imerode(ima,se);
imshow(eroded)
and you will see the image that follows as output. After you do this, you can use bwlabel to label the connected components and compute whatever properties you may want, for example, count the number of coins or detect their centers.

MATLAB. Inverse crop images.

I would like to crop an image but I want to retain the part of image that is outside of the rectangle. How can this can be done?
It seems that with imcrop only the part within the rectangle can be retained.
An image in Matlab is represented by a matrix, just like any other matrix, you can read more about representation forms here.
It seems that what you want to do is to take the area that you don't want and change the values of the corresponding cells in the matrix to the color that you want to put instead (each cell in the matrix is a pixel in the image). That is if you know the place where your unwanted data is.
If you don't know where it is, and want to use the tool given by imcrop to manually choose the "cropped" area, you can take the resulting matrix, and find the part of the original image which is an exact match with the cropped part, and to color it as you wish.
The code for doing this:
I=imread('img_9.tif');
I2=imcrop(I,[60,50,85,85]);
n_big=size(I);
n_small=size(I2);
for j1=1:(n_big(1)-n_small(1))
for j2=1:(n_big(2)-n_small(2))
Itest=I(j1:j1+n_small(1)-1,j2:j2+n_small(2)-1,:);
if ( Itest == I2)
I(j1:j1+n_small(1)-1,j2:j2+n_small(2)-1,:) = zeros(n_small(1),n_small(2),3);
end
end
end
figure(1);
imshow(I);
figure(2);
imshow(I2);
The results of my test were:
original:
cropped:
resulting image:
maybe what you want to do is first a mask with the inverse area of what you want to crop and save this result.