How to calculate radius of ring in MATLAB? - matlab

I have a stack of cortical bone images, high resolution and binarized. How do I go about calculating the mean inner and outer radii for each image? Here is an example of the kind of images I need to process:

This could be one approach -
%// Read in image and conert to binary
im = im2bw(imread('http://s9.postimg.org/aew1l7tvz/4_COPY_copy.png'));
figure, imshow(im), title('Original Image')
%// Fill holes giving us the "outer blob"
outer_blob = imfill(im,'holes');
outer_blob = biggest_blob(outer_blob); %// remove noise
figure, imshow(outer_blob), title('Outer Blob')
%// Get the inner filled blob by "removing" the original image from outer blob
inner_blob = outer_blob & ~im;
inner_blob = biggest_blob(inner_blob); %// remove noise
figure, imshow(inner_blob), title('Inner Blob')
%// Find the equivalent/mean inner and outer radii
inner_dia = regionprops(inner_blob,'Equivdiameter');
inner_radius = inner_dia.EquivDiameter/2
outer_dia = regionprops(outer_blob,'Equivdiameter');
outer_radius = outer_dia.EquivDiameter/2
Associated function code -
function out = biggest_blob(BW)
%// Find and labels blobs in the binary image BW
[L, num] = bwlabel(BW, 8);
%// Count of pixels in each blob, basically this should give the area of each blob
counts = sum(bsxfun(#eq,L(:),1:num));
%// Get the label(ind) cooresponding to blob with the maximum area
%// which would be the biggest blob
[~,ind] = max(counts);
%// Get only the logical mask of the biggest blob by comparing all labels
%// to the label(ind) of the biggest blob
out = (L==ind);
return;
Code run and debug images -
inner_radius =
211.4740
outer_radius =
267.8926

Related

Matlab - Plotting Specific Pixels (image treatment)

I'm currently struggling with an image treatment\ data plotting issue and was hoping to get some feedback from people with more experience than myself on this matter.
I'll try and breakdown the problem as to make it more understandable:
I have an original image (figureB - which is the blue chanel of the original image) of size NxM, from this image I select a specific area to study (NewfigureB), size 120x170;
I then divide this area into what I called macropixels which are 10x10 arrays of data points (pixels);
I then apply a mask to the selected area to select only the points meeting certain luminescence conditions;
So far so good. My problem comes when I try to plot a histogram of each of these macropixels when applying the luminescence mask. The final objective is to then find the peaks in these histograms.
so far this is what I've come up with. Any help would be greatly appreciated.
Many thanks
%Make the number of pixels in the matrix divisible
Macropixel = 10; %determine the size of the macropixel
[rows,columns] = size(figureB); %determine dimentions of the matrix used in the calculations
MacropixRows = floor(rows/Macropixel); %determine how many macropixels are in a row of the original matrix
MacropixColumn = floor(columns/Macropixel); %determine how many macropixels are in a column of the original matrix
%define new dim for the matrix
rows = MacropixRows * Macropixel;
columns = MacropixColumn * Macropixel;
NewfigureB = figureB(1:rows,1:columns); %divisible by the size of the macropixels created
%select area
NewfigureB = NewfigureB(1230:1349,2100:2269);
%create luminescence mask
Lmin=50;
hmax=80;
mask=false(size(NewfigureB));
mask(NewfigureB <Lmin)=true;
mask=mask & (NewfigureB<hmax);
%Apply mask
NewfigureB=NewfigureB(mask);
for jj = 1:Macropixel:120
for ii =1:Macropixel:170
histogram( NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1))
end
end'''
The code you have posted has too many issues.
I tried to correct it the best I could.
I modified some parameters to feat the sample image I used.
I couldn't find your sample image, so I used the following
Here is a corrected code (please read the comments):
I = imread('Nikon-D810-Image-Sample-7.jpg');
figureB = I(:,:,3);
%Make the number of pixels in the matrix divisible
Macropixel = 10; %determine the size of the macropixel
[rows,columns] = size(figureB); %determine dimentions of the matrix used in the calculations
MacropixRows = floor(rows/Macropixel); %determine how many macropixels are in a row of the original matrix
MacropixColumn = floor(columns/Macropixel); %determine how many macropixels are in a column of the original matrix
%define new dim for the matrix
rows = MacropixRows * Macropixel;
columns = MacropixColumn * Macropixel;
NewfigureB = figureB(1:rows,1:columns); %divisible by the size of the macropixels created
%select area
NewfigureB = NewfigureB(1230:1349,2100:2269);
%create luminescence mask
Lmin=90;%50; %Change to 90 for testing
hmax=200;%80; %Change to 200 for testing
mask=false(size(NewfigureB));
mask(NewfigureB > Lmin)=true; %I think it should be > Lmin. %mask(NewfigureB <Lmin)=true;
mask=mask & (NewfigureB<hmax);
%This is not the right way to apply a mask, because the result is a vector (not a matrix).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Apply mask
%NewfigureB=NewfigureB(mask);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Assuming there are no zeros in the image, you can set masked elements to zero:
NewfigureB(~mask) = 0;
for jj = 1:Macropixel:120
for ii =1:Macropixel:170
%Copy NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1) into temporary matrix MB:
MB = NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1);
%Remove the zeros from MB (zeros are masked elements).
%The result is a vector (not a matrix).
MB = MB(MB ~= 0);
%histogram( NewfigureB(jj:jj+Macropixel-1, ii:ii+Macropixel-1))
figure; %Open new figure for each histogram. (I don't know if it's a good idea).
histogram(MB); %Plot the histogram of vector MB.
end
end
It's probably not exactly matches intentions.
I hope it gives you a lead...

Getting whole line by combining its parts

I have an image and my aim is to get whole line which is shown with red line. I am working with matlab and I don't want to use IM2 = imdilate(IM,SE) function.
Is there any function or method to do that?
The image:
Note: Sorry for bad red line. I drew it with paint.
Edit:
The original image is below:
Here's what I have after using imdilate at an intermediate step -
%// Read in image and convert to a binary one
im = imread('Line.jpg');
bw = im2bw(im);
%// There seems to be a thin white boundary across the image, make it false(black)
bw1 = false(size(bw));
bw1(5:end-5,5:end-5) = bw(5:end-5,5:end-5);
bw1(biggest_blob(bw1)) = 0; %// remove biggest blob (bottom left corner one)
SE = strel('disk', 11, 8); %// structuring element for dilation
bw2 = imdilate(bw1,SE); %// dilate the image
bw3 = bwmorph(bw2,'thin',Inf); %// thin it
out = biggest_blob(bw3); %// out of many thinned lines, select the biggest one
Please remember that the motive behind removing the biggest blob at the start of the codes is that without that being removed, we would have gotten the biggest blob being attached to the island blobs that we were trying to connect/combine and thus would have messed up the desired output.
Associated function (taken from Select largest object in an image) -
function out = biggest_blob(BW)
%// Find and labels blobs in the binary image BW
[L, num] = bwlabel(BW, 8);
%// Count of pixels in each blob, basically this should give the area of each blob
counts = sum(bsxfun(#eq,L(:),1:num));
%// Get the label(ind) cooresponding to blob with the maximum area
%// which would be the biggest blob
[~,ind] = max(counts);
%// Get only the logical mask of the biggest blob by comparing all labels
%// to the label(ind) of the biggest blob
out = (L==ind);
return;
Result -

Filling blobs (shapes) with unique colors based on area

I have some shapes on an image that i've attempted to label according to their Area using a solution provided to me:
stats = regionprops(BW,'Area')
stats2 = regionprops(BW,'Centroid')
figure,imshow(BW)
for k = 1:numel(stats)
xy = stats2(k).Centroid
if (stats(k).Area>TH)
text(xy(1),xy(2),'L') %// Large Shape
else
text(xy(1),xy(2),'S') %// Small Shape
end
end
But it turns out the shapes are too small for the letters ( which would be too small even if I changed the font), I'm wondering if there's a way to do the thresholding to produce a colour code i.e change the filling of the shapes based on their area?
See if this is inspiring enough for you -
%// Input image. This one is chosen as it is available in MATLAB image library
img = imread('coins.png');
%// Convert to binary image
BW = im2bw(img,0.4); %// 0.4 as binary thresehold worked for this specific image
%// Get area and pixel-list stats
stats = regionprops(BW,'Area');
stats2 = regionprops(BW,'PixelIdxList');
s1 = struct2array(stats);
[v1,v2,v3] = unique(s1);
num_colors = numel(v1);
%// Pixel values per channel for creating color codes
pix_per_ch = linspace(0,255,ceil(power(num_colors,1/3)));
%// Unique 3 color codes
all_color_codes = allcomb(pix_per_ch,pix_per_ch,pix_per_ch);
%// allcomb is a MATLAB File-exchange tool avaiialble at -
%// http://www.mathworks.in/matlabcentral/fileexchange/10064-allcomb
%// Unique 3 color codes for the number of shapes available
color_codes = all_color_codes(randi(size(all_color_codes,1),num_colors,1),:);
%// Sort these uniques colors based on their grayscale intensities
[~,ind]=sort(rgb2gray(uint8(permute(color_codes,[1 3 2]))));
sorted_color_codes = color_codes(ind,:);
%// Pre-allocate for the ouput image
out = uint8(255.*BW(:,:,ones(1,3)));
%// Assign each shape a unique color based on their areas
for k = 1:numel(stats)
ind1 = stats2(k).PixelIdxList;
indx = bsxfun(#plus,ind1,[0:2].*size(img,1)*size(img,2));
color_code = sorted_color_codes(v3(k),:);
color_code_ext = color_code(ones(1,numel(ind1)),:);
out(indx) = color_code_ext;
end
%// Display input, output results
figure,
subplot(211),imshow(img),
title('Input Image')
subplot(212),imshow(out),
title('Output Image (Brighter colors represent larger shapes)')
Output -

Segmentation in an image with a single object in MATLAB

Here is the picture:
My goal is placing this bird in another image. I tried something with MATLAB, first rgb2gray then imhist to get the bird intensity, then I made a mask, but I always ended up with a mask which included the tree and the clouds.
Here is some code you can use for this task:
clear;
close all;
im = imread('~/Downloads/siraly_www.kepfeltoltes.hu_.jpg');
im = rgb2gray(im);
%// Manually crop the image
im = double(im(620:1619, 2150:3279));
%// Find edges
hedge = vision.EdgeDetector('Method', 'Sobel');
edges = step(hedge, im);
%// Dilate to close edges around object
edges = imdilate(edges, [0 1 0; 1 1 1; 0 1 0]);
%// Find boundary of object
bound = bwboundaries(edges);
bound = bound{1}; % Largest boundary is around object
%// Display image and object boundary
figure; imshow(im, []);
hold on;
plot(bound(:,2), bound(:,1), '.');
hold off;
%// Select all object pixels by filling the boundary
bwobject = false(size(im));
bwobject(sub2ind(size(im), bound(:,1), bound(:,2))) = true;
bwobject = imfill(bwobject, 'holes');
imobject = zeros(size(im));
imobject(bwobject) = im(bwobject);
figure; imshow(imobject, []);
The method used here is:
Manual cropping of the image.
Edge detection using the EdgeDetector object.
Morphological operations to retrieve the object pixels only using imdilate, bwboundaries and imfill.
Here are the object boundaries computed and plotted in the code:
And here is the object cropped from the image:

Compution of particle size distribution by matlab img processing

I need to calculate the perimeter of some micro sized particles which are in a photo I captured.
First I Processed the image and now I want to work on 2D processed image which the particles are white and background is black as you know.
So I need some methods & codes to calculate the perimeter & diameter of particles in pixel unit. any suggestions?!
Thanks in advance
The following code might help you understand -
%%// Input image
BW = imread('text.png'); %%// Available in the MATLAB image library
figure,imshow(BW)
%%// Get the scalar distances around the boundaries of the regions/blobs
P = regionprops(BW, 'Perimeter');
%%// Get scalar values that specifies the diameter of a circle with the same
%%// area as the regions/blobs
D = regionprops(BW, 'EquivDiameter');
%%// Get list of pixels based on their labeling.
%%// Basically the indices of the structs produced by regionprops refer to the labels.
pixel_list = regionprops(BW, 'PixelIdxList');
%%// Let us find out information about the first blob (blob that is labeled as 1)
%%// 1. List of pixel coordinates as linear indices
blob1_pixel_list = pixel_list(1).PixelIdxList;
%%// Create an image of the same size as the original one and showing the
%%blob labeled as 1
blob1 = false(size(BW));
blob1(blob1_pixel_list) = true;
figure,imshow(blob1)
%%// Perimter of blob -1
blob1_perimeter = P(1).Perimeter
%%// Equivalent diameter of blob -1
blob1_equivdiameter_values = D(1).EquivDiameter
%%// Get perimeter and diameter values for all the blobs
perimeter_values = struct2array(P)
diameter_values = struct2array(D)