Skip to content
Snippets Groups Projects
Commit dd63bc79 authored by BehnazP's avatar BehnazP
Browse files

add files to git

parent ce5b6e31
No related branches found
No related tags found
No related merge requests found
Copyright 2018 Vedrana Andersen Dahl, vand@dtu.dk
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
File added
function [U,cmap,cbar] = color_skeleton(B,S,D)
%COLOR_SKELETON Colorize binarization, skeletonization and distances
% [U,CMAP,CBAR] = COLOR_SKELETON(B,S,D) produces an indexed
% image and a corresponding colormap for visualization of binarization,
% skeletonization and distances.
%
% B - binary volume (zero outsice, one inside)
% S - binary volume for skeleton of both inside and outside
% D - signed distance field (negative for inside, positive for outside)
% U - indexed uint8 image
% CMAP - associated colormap
% CBAR - struct containing inputs for associated colorbar
%
% Example:
% [U,cmap,cbar] = color_skeleton(B,S,D);
% imagesc(U)
% colormap(cmap)
% colorbar(cbar{:})
%
% Copyright 2018 Vedrana Andersen Dahl, vand@dtu.dk
% Colormap values correspond to
% 0 - outside (black)
% 1 - inside (white)
% 2--128 positive (outside) distance (127 colors from winter colormap)
% 129--255 negative (inside) distance (127 colors from autumn colormap)
U = uint8(B);
ds = D(S);
minmax = [min(ds),max(ds)]; % min should be negative
ds(ds>0) = 2+126*(minmax(2)-ds(ds>0))/minmax(2); % flipping for symmetry
ds(ds<0) = 129+126*ds(ds<0)/minmax(1);
U(S) = ds;
cmap = [0 0 0; 1 1 1; autumn(127);flip(winter(127))];
cbtl = round(10*[minmax(2),0,-minmax(1)])/10; % colorbar tick labels
cbar = {'Limits',[2,255],'Ticks',[2,128.5,255],'TickLabels',cbtl};
function area = compute_area(B)
%COMPUTE_AREA Area of the binarized object
% AREA = COMPUTE_AREA(B)
Ax = B(2:end,:,:)~=B(1:end-1,:,:);
Ay = B(:,2:end,:)~=B(:,1:end-1,:);
Az = B(:,:,2:end)~=B(:,:,1:end-1);
area = sum(Ax(:))+sum(Ay(:))+sum(Az(:));
\ No newline at end of file
function measures = fit_distribution(r,show_histogram)
% FIT_DISTRIBUTION Fits lognormal distribution to data
% MEASURES = FIT_DISTRIBUTION(R,SHOW_HISTOGRAM)
% R is a vector of data
% SHOW_HISTOGRAM is a flag idicating whether plot should be produced
% MEASURES are valuses extracted from fitted distribution: median
% (geometric mean), geometric standard deviation, mean, variance and mode
%
% Copyright 2018 Vedrana Andersen Dahl, vand@dtu.dk
measures = NaN(1,5);
if numel(r)>1
pd = fitdist(r(:),'lognormal'); % pd.mu and pd.sigma are mean and standard deviation of the associated normal distribution
measures(1) = exp(pd.mu); % median of the fitted distribution (geometric mean)
measures(2) = exp(pd.sigma); % geometric standard deviation of the fitted distribution
measures(3) = exp(pd.mu+pd.sigma.^2/2); % mean of lognormal distribution
measures(4) = (exp(pd.sigma.^2)-1)*measures(3).^2; % variance of the lognormal distribution
measures(5) = exp(pd.mu-pd.sigma.^2); % mode of the lognormal distribution
end
if nargin>1 && show_histogram && numel(r)>1
h = histfit(r(:),ceil(max(r(:))),'lognormal'); hold on
x = h(2).XData;
y = h(2).YData;
title({['mean = ',num2str(measures(3)),', std = ',num2str(sqrt(measures(4)))],...
['median = ',num2str(measures(1)),', gstd = ',num2str(measures(2))],...
['mode = ',num2str(measures(5))]})
l(1) = plot(measures(5)*[1,1],[0,interp1(x,y,measures(5))],'c--');
l(2) = plot(measures(1)*[1,1],[0,interp1(x,y,measures(1))],'g--');
l(3) = plot(measures(3)*[1,1],[0,interp1(x,y,measures(3))],'m--');
xlim([0,max(x)])
xlabel('radius (pixels)'), ylabel('count')
legend(l,{'mode','median (geometric mean)','mean'},'Location','NE')
end
function show_matvol(V,clim)
% SHOW_MATVOL Shows volumetric data
% show_matvol(V,clim)
% Inputs: volume, grayscale color limits (optional)
% Copyright 2018 Vedrana Andersen Dahl, vand@dtu.dk
figure('Units','Normalized','Position',[0.1 0.3 0.5 0.6],...
'KeyPressFcn',@key_press);
dim = size(V);
if nargin<2 || isempty(clim)
clim = [min(double(V(:))),max(double(V(:)))];
end
z = round(0.5*(dim(3)+1));
%update_drawing
i = imagesc(V(:,:,z),clim);
title(['slice ',num2str(z),'/',num2str(dim(3))]), axis image ij
colormap gray, drawnow
%%%%%%%%%% CALLBACK FUNCTIONS %%%%%%%%%%
function key_press(~,object)
% keyboard commands
switch object.Key
case 'uparrow'
z = min(z+1,dim(3));
case 'downarrow'
z = max(z-1,1);
case 'rightarrow'
z = min(z+10,dim(3));
case 'leftarrow'
z = max(z-10,1);
case 'pagedown'
z = min(z+50,dim(3));
case 'pageup'
z = max(z-50,1);
end
update_drawing
end
%%%%%%%%%% HELPING FUNCTIONS %%%%%%%%%%
function update_drawing
set(i,'CData',V(:,:,z))
title(['slice ',num2str(z),'/',num2str(dim(3))])
drawnow
end
end
% Copyright 2018 Vedrana Andersen Dahl, vand@dtu.dk
clear
close all
addpath functions
load bonesub
gray_th = 3*10^4;
div = [0.5 30.5,70.5,100.5,130.5,170.5 size(V,3)+0.5]; % layer divisions
midlayer = floor(0.5*(div(1:end-1) + div(2:end))); % middle slice of a layer
%% volume inspection -- use arrows
show_matvol(permute(V,[3,2,1]))
hold on, plot([1;size(V,2)]*ones(1,5),[1;1]*div(2:end-1),'r','LineWidth',2)
text(size(V,2)/2*ones(1,6),midlayer,num2cell(1:6),'Color','r','FontSize',20)
show_matvol(V)
%% still figures
x = 100;
figure, imagesc(squeeze(V(x,:,:))'); axis image, colormap gray
hold on, plot([1;size(V,2)]*ones(1,5),[1;1]*div(2:end-1),'r','LineWidth',2)
text(size(V,2)/2*ones(1,6),midlayer,num2cell(1:6),'Color','r','FontSize',20)
title(['Longitudinal slice, x=',num2str(x)]), xlabel('y'), ylabel('z')
figure
for i=1:numel(midlayer)
subplot(2,3,i), imagesc(V(:,:,midlayer(i))), axis image, colormap gray
title(['Region ' num2str(i), ', z=',num2str(midlayer(i))])
xlabel('y'), ylabel('x')
end
%% binarization
B = medfilt3(medfilt3(V,[3,3,3])>gray_th,[3,3,3]);
show_matvol(B)
%% still figures
figure, imagesc(squeeze(B(x,:,:))'); axis image, colormap gray
hold on, plot([1;size(B,2)]*ones(1,5),[1;1]*div(2:end-1),'r','LineWidth',2)
text(size(V,2)/2*ones(1,6),midlayer,num2cell(1:6),'Color','r','FontSize',20)
title(['Longitudinal slice, x=',num2str(x)]), xlabel('y'), ylabel('z')
figure
for i=1:numel(midlayer)
subplot(2,3,i), imagesc(B(:,:,midlayer(i))), axis image, colormap gray
title(['Region ' num2str(i), ', z=',num2str(midlayer(i))])
xlabel('y'), ylabel('x')
end
%% distance transform
distances = bwdist(~B) - bwdist(B) - B + 0.5; % distance from voxel center to interface
show_matvol(distances)
%% skeletonization of fibres and air
% criterium: local maxima in any of the 3 planes for larger number of sceleton points)
conn = cat(3,zeros(3,3),[0 1 0; 1 1 1; 0 1 0],zeros(3,3));
skeleton = ((imregionalmax(distances,conn) | imregionalmax(distances,permute(conn,[2 3 1]))...
| imregionalmax(distances,permute(conn,[3 1 2]))) & B)...
| (imregionalmin(distances,conn) | imregionalmin(distances,permute(conn,[2 3 1]))...
| imregionalmin(distances,permute(conn,[3 1 2]))) & ~B;
% alternative with 3D local maxima, which yields less points
% conn = cat(3,[0 0 0; 0 1 0; 0 0 0],[0 1 0; 1 1 1; 0 1 0],[0 0 0; 0 1 0; 0 0 0]);
% skeleton = (imregionalmax(distances,conn) & B) | (imregionalmax(distances,conn) & ~B);
% cleaning
% skeleton = skeleton & abs(distances)>1;
skeleton([1,end],:,:) = false; skeleton(:,[1,end],:) = false; skeleton(:,:,[1,end]) = false;
%% visualizing single slice with a special colormap
z = 100; % and only a slice
[U,cmap,cbar] = color_skeleton(B(:,:,z),skeleton(:,:,z),distances(:,:,z));
figure, imagesc(U), colormap(cmap), axis image, title(['Slice z=',num2str(z)])
colorbar(cbar{:})
[U,cmap,cbar] = color_skeleton(squeeze(B(x,:,:))',squeeze(skeleton(x,:,:))',squeeze(distances(x,:,:))');
figure, imagesc(U), colormap(cmap), axis image,
title(['Longitudinal slice, x=',num2str(x)]), xlabel('y'), ylabel('z')
colorbar(cbar{:})
%% visualizing multiple slices using special colormap
[U,cmap,cbar] = color_skeleton(B,skeleton,distances);
figure
for i=1:numel(midlayer)
subplot(2,3,i), imagesc(U(:,:,midlayer(i)),[0,255]), axis image, colormap(cmap)
title(['region ' num2str(i), ', z=',num2str(midlayer(i))])
xlabel('y'), ylabel('x')
end
%% volume slicing using special colormap
show_matvol(U,[0,255]), colormap(cmap); % full volume
colorbar(cbar{:})
%% measuring porosity for a whole volume
volume_all = sum(B(:))/numel(B); % phase volume per block volume
area_all = compute_area(B)/numel(B); % phase surface per block volume
% measures from distance fields
figure
inside_all = fit_distribution(distances(skeleton & B),true);
a = gca; title([{'Thickness for a whole sample'};a.Title.String])
xlim([0 30]), xlabel('Radius (pixels)'), ylabel('Count')
figure
outside_all = fit_distribution(-distances(skeleton & ~B),true);
a = gca; title([{'Spacing for a whole sample'};a.Title.String])
xlim([0 30]), xlabel('Radius (pixels)'), ylabel('Count')
%% performing layered collection of measures
volume_layer = zeros(numel(midlayer),1);
area_layer = zeros(numel(midlayer),1);
inside_layer = zeros(numel(midlayer),5);
outside_layer = zeros(numel(midlayer),5);
fig_in = figure;
fig_out = figure;
for i = 1:numel(midlayer)
range = ceil(div(i)):floor(div(i+1));
B_layer = B(:,:,range);
distances_layer = distances(:,:,range);
skeleton_layer = skeleton(:,:,range);
volume_layer(i) = sum(B_layer(:))/numel(B_layer);
area_layer(i) = compute_area(B_layer)/numel(B_layer);
% measures from distance fields
figure(fig_in), subplot(2,3,i)
inside_layer(i,:) = fit_distribution(distances_layer(skeleton_layer & B_layer),true);
legend off, xlim([0 25])
title(['Thickness for region ' num2str(i)])
figure(fig_out), subplot(2,3,i)
outside_layer(i,:) = fit_distribution(-distances_layer(skeleton_layer & ~B_layer),true);
legend off, xlim([0 25])
title(['Separation for region ' num2str(i)])
end
%% saving results
% fid = fopen('results.tex','w');
% fprintf(fid, 'Measure & Sample & Region 1 & Region 2 & Region 3 & Region 4 & Region 5 & Region 6 \\\\\\hline\n');
% fprintf(fid, 'Bone volume & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[volume_all; volume_layer]);
% fprintf(fid, 'Area & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[area_all; area_layer]);
% fprintf(fid, 'Area per bone volume & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[area_all; area_layer]./[volume_all; volume_layer]);
% fprintf(fid, 'Thickness, mode & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[inside_all(5); inside_layer(:,5)]);
% fprintf(fid, 'Thickness, median & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[inside_all(1); inside_layer(:,1)]);
% fprintf(fid, 'Thickness, mean & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[inside_all(3); inside_layer(:,3)]);
% fprintf(fid, 'Separation, mode & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[outside_all(5); outside_layer(:,5)]);
% fprintf(fid, 'Separation, median & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[outside_all(1); outside_layer(:,1)]);
% fprintf(fid, 'Separation, mean & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f & %.2f \\\\\n',[outside_all(3); outside_layer(:,3)]);
% fclose(fid);
%
% for savefig = [3,4,6,7,9,10,11,13,14,15,16]
% set(savefig,'Units','Normalized','Position',[0.1 0.1 0.6 0.8])
% saveas(savefig,['Figure_',num2str(savefig),'.eps'],'epsc');
% end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment