├── file_proc-toolbox ├── README.md ├── get_predirs.m ├── imfiles2giffile.m └── get_dirs.m ├── demo ├── count_openset_num.m ├── calculate_area_2022_0725.m ├── calculate_area_2023_2002.m ├── count_cell_num.m └── bone_shape_reconstruct_from_dcm_220831.m ├── img_proc-toolbox ├── lab2ind.m ├── keep_remove_ranked_vol.m ├── serial_dilate_erode_vol.m ├── vol_rot_gif.m ├── sub2ind_nd.m ├── ind2lab.m └── sub2lab.m ├── evaluate_metrics-toolbox ├── lap_conv3d.m ├── hausforff_dist.m ├── centroid_dist.m ├── avg_surf_dist.m ├── det_jacob.m └── get_thickness_map.m ├── README.md └── LICENSE /file_proc-toolbox/README.md: -------------------------------------------------------------------------------- 1 | # file_processing -------------------------------------------------------------------------------- /demo/count_openset_num.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianqingzheng/image_processing/HEAD/demo/count_openset_num.m -------------------------------------------------------------------------------- /demo/calculate_area_2022_0725.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianqingzheng/image_processing/HEAD/demo/calculate_area_2022_0725.m -------------------------------------------------------------------------------- /demo/calculate_area_2023_2002.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianqingzheng/image_processing/HEAD/demo/calculate_area_2023_2002.m -------------------------------------------------------------------------------- /img_proc-toolbox/lab2ind.m: -------------------------------------------------------------------------------- 1 | function [ind,pnd]=lab2ind(lab,thresh) 2 | if nargin<2 3 | thresh=0.1; 4 | end 5 | img_sz=size(lab); 6 | ind=find(lab>thresh); 7 | pnd=[]; 8 | id=ind; 9 | for s=img_sz 10 | coord=mod(id,s); 11 | pnd=[pnd,coord]; 12 | id=floor(id/s); 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/lap_conv3d.m: -------------------------------------------------------------------------------- 1 | function out_vol=lap_conv3d(vol) 2 | % lap_k1=[]; 3 | lap_k0=[0,0,0; 4 | 0,-1,0; 5 | 0,0,0]; 6 | lap_k2=[0,-1,0; 7 | -1,6,-1; 8 | 0,-1,0]; 9 | lap_kernel=cat(3,lap_k0,lap_k2,lap_k0); 10 | out_vol=convn(double(vol),lap_kernel,'same'); 11 | end 12 | -------------------------------------------------------------------------------- /img_proc-toolbox/keep_remove_ranked_vol.m: -------------------------------------------------------------------------------- 1 | function out_vol=keep_remove_ranked_vol(vol,rank_nums) 2 | out_vol=vol>0.5; 3 | if ndims(vol)>2 4 | L = bwconncomp(vol,26);% 5 | else 6 | L = bwconncomp(vol,8);% 7 | end 8 | stats = regionprops(L,'Area'); 9 | Ar = cat(1, stats.Area); 10 | [~,ind]=sort(Ar,'descend'); 11 | LM = labelmatrix(L); 12 | % out_vol(find(LM==ind(remove_vol_rank)))=0;% 13 | if rank_nums(1)>0 14 | out_vol(~ismember(LM,ind(rank_nums)))=0;% 15 | else 16 | rank_nums=-1.*rank_nums; 17 | out_vol(ismember(LM,ind(rank_nums)))=0;% 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /file_proc-toolbox/get_predirs.m: -------------------------------------------------------------------------------- 1 | function [predirs,foldernames]=get_predirs(dirs_in,layernumber) 2 | predirs=dirs_in; 3 | predirs_temp=predirs; 4 | for i=0:layernumber 5 | if i==layernumber 6 | foldernames_temp=cell(size(dirs_in)); 7 | end 8 | for j=1:numel(predirs) 9 | [predir,foldername,~]=fileparts(predirs_temp{j}); 10 | if i==layernumber 11 | foldernames_temp{j}=foldername; 12 | else 13 | predirs_temp{j}=predir; 14 | end 15 | end 16 | end 17 | if layernumber>0 18 | predirs=predirs_temp; 19 | 20 | end 21 | foldernames=foldernames_temp; 22 | end -------------------------------------------------------------------------------- /file_proc-toolbox/imfiles2giffile.m: -------------------------------------------------------------------------------- 1 | function []=imfiles2giffile(imdirs,giffile,delay,loopnumb) 2 | if nargin<4 3 | loopnumb=inf; 4 | if nargin<3 5 | delay=0.001; 6 | end 7 | end 8 | % im_dirs_temp=get_dirs(Label_path,'.obj',[Label_path,'/',sprintf('P%02d',p)]); 9 | for i=1:numel(imdirs) 10 | img=imread(imdirs{i}); 11 | drawnow 12 | f=getframe; 13 | f=frame2im(f); 14 | [X,map]=rgb2ind(img,256); 15 | if i==1 16 | imwrite(X,map,giffile,'gif','LoopCount',loopnumb,'DelayTime',delay); 17 | else 18 | imwrite(X,map,giffile,'WriteMode','Append','DelayTime',delay); 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /img_proc-toolbox/serial_dilate_erode_vol.m: -------------------------------------------------------------------------------- 1 | function out_vol=serial_dilate_erode_vol(vol,dilate_erode_rates,growing_msk,min_area,se_type) 2 | if nargin<5 3 | se_type='sphere'; 4 | if nargin<4 5 | min_area=0; 6 | if nargin<3 7 | growing_msk=1; 8 | end 9 | end 10 | end 11 | for r= dilate_erode_rates 12 | se=strel(se_type,abs(r)); 13 | % se=strel('cube',abs(r)); 14 | if r>0 15 | vol=imdilate(vol,se); 16 | else 17 | vol=imerode(vol,se); 18 | end 19 | vol=vol.*growing_msk; 20 | if min_area>0 21 | vol=bwareaopen(vol,min_area); 22 | end 23 | end 24 | out_vol=vol; 25 | end -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/hausforff_dist.m: -------------------------------------------------------------------------------- 1 | function hd=hausforff_dist(vol1,vol2,side_idx) 2 | if nargin<3 3 | side_idx=0; 4 | end 5 | v1=lap_conv3d(vol1)>0.5; 6 | v2=lap_conv3d(vol2)>0.5; 7 | [~,coord1]=img2ind(v1); 8 | [~,coord2]=img2ind(v2); 9 | if side_idx==1 || side_idx==2 10 | dist_mat=pdist2(coord1,coord2,"euclidean"); 11 | hd=max(min(dist_mat,[],side_idx)); 12 | else 13 | [hd]=HausdorffDist(coord1,coord2); 14 | end 15 | end 16 | 17 | function [ind,pnd]=img2ind(img,thresh) 18 | if nargin<2 19 | thresh=0.000000001; 20 | end 21 | img_sz=size(img); 22 | ind=find(img>thresh); 23 | pnd=[]; 24 | id=ind; 25 | for s=img_sz 26 | coord=mod(id,s); 27 | pnd=[pnd,coord]; 28 | id=floor(id/s); 29 | end 30 | end -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/centroid_dist.m: -------------------------------------------------------------------------------- 1 | function cd=centroid_dist(vol1,vol2) 2 | s = regionprops3(vol1,"Centroid","PrincipalAxisLength"); 3 | coord1 = s.Centroid; 4 | s = regionprops3(vol2,"Centroid","PrincipalAxisLength"); 5 | coord2 = s.Centroid; 6 | % v1=lap_conv3d(vol1)>0.5; 7 | % v2=lap_conv3d(vol2)>0.5; 8 | % volshow(v2); 9 | % [~,coord1]=img2ind(v1); 10 | % [~,coord2]=img2ind(v2); 11 | dist_mat=pdist2(coord1,coord2,"euclidean"); 12 | cd=mean(min(dist_mat,[],1)); 13 | 14 | end 15 | 16 | function [ind,pnd]=img2ind(img,thresh) 17 | if nargin<2 18 | thresh=0.000000001; 19 | end 20 | img_sz=size(img); 21 | ind=find(img>thresh); 22 | pnd=[]; 23 | id=ind; 24 | for s=img_sz 25 | coord=mod(id,s); 26 | pnd=[pnd,coord]; 27 | id=floor(id/s); 28 | end 29 | end -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/avg_surf_dist.m: -------------------------------------------------------------------------------- 1 | function asd=avg_surf_dist(vol1,vol2,side_idx,sample_rate) 2 | if nargin<4 3 | sample_rate=1; 4 | if nargin<3 5 | side_idx=1; 6 | end 7 | end 8 | % % lap_k1=[]; 9 | % lap_k0=[0,0,0; 10 | % 0,-1,0; 11 | % 0,0,0]; 12 | % lap_k2=[0,-1,0; 13 | % -1,6,-1; 14 | % 0,-1,0]; 15 | % lap_kernel=cat(3,lap_k0,lap_k2,lap_k0); 16 | % v1=convn(double(vol1),lap_kernel,'same')>0.5; 17 | % v2=convn(double(vol2),lap_kernel,'same')>0.5; 18 | v1=lap_conv3d(vol1)>0.5; 19 | v2=lap_conv3d(vol2)>0.5; 20 | % volshow(v2); 21 | [~,coord1]=img2ind(v1); 22 | [~,coord2]=img2ind(v2); 23 | dist_mat=pdist2(coord1(1:sample_rate:end,:),coord2(1:sample_rate:end,:),"euclidean"); 24 | asd=mean(min(dist_mat,[],side_idx)); 25 | 26 | end 27 | 28 | function [ind,pnd]=img2ind(img,thresh) 29 | if nargin<2 30 | thresh=0.000000001; 31 | end 32 | img_sz=size(img); 33 | ind=find(img>thresh); 34 | pnd=[]; 35 | id=ind; 36 | for s=img_sz 37 | coord=mod(id,s); 38 | pnd=[pnd,coord]; 39 | id=floor(id/s); 40 | end 41 | end -------------------------------------------------------------------------------- /img_proc-toolbox/vol_rot_gif.m: -------------------------------------------------------------------------------- 1 | function []=vol_rot_gif(fig_id,gif_file,cam_angles) 2 | if nargin<3 3 | rot_num=5; 4 | % cam_angles=[[0:rot_num:360]+90;zeros(1,360/rot_num+1)+5]; 5 | cam_angles=[zeros(1,360/rot_num+1)+90;[0:rot_num:360]+90]; 6 | if nargin<2 7 | gif_file=['vol_rot_gif','.gif']; 8 | end 9 | end 10 | if nargin>=1 11 | fig=figure(fig_id); 12 | end 13 | loopnumb=Inf; 14 | delay=0.1; 15 | 16 | for ang_id=1:size(cam_angles,2) 17 | view(double(cam_angles(:,ang_id))'); 18 | camlight;% 19 | ax = gca; 20 | % ax.Units = 'pixels'; 21 | % ti = ax.TightInset; 22 | % pos=ax.Position; 23 | % rect = [0, 0, floor(pos(3)), floor(pos(4))]; 24 | axis vis3d 25 | drawnow 26 | f=getframe(ax.Parent); 27 | img=frame2im(f); 28 | delete(findall(gcf,'Type','light'));% 29 | [X,map]=rgb2ind(img,256); 30 | if ang_id==1 31 | imwrite(X,map,gif_file,'gif','LoopCount',loopnumb,'DelayTime',delay); 32 | else 33 | imwrite(X,map,gif_file,'WriteMode','Append','DelayTime',delay); 34 | end 35 | end 36 | end 37 | 38 | -------------------------------------------------------------------------------- /img_proc-toolbox/sub2ind_nd.m: -------------------------------------------------------------------------------- 1 | function ind = sub2ind_nd( tensor_sz, subs ) 2 | % sub2ind_nd - Get the index number using the given subscript coordinates 3 | % and the tensor size 4 | %-------------------------------------------------------------------------- 5 | % [ind] = sub2ind_nd( tensor_sz, subs ) 6 | % 'ind' - the output index numbers 7 | % 'tensor_sz' - the size of the required tensor 8 | % 'sub' - the given subscript corrdinates 9 | %-------------------------------------------------------------------------- 10 | % Examples: 11 | % >> ind = sub2ind_nd([5,5],[3,5;2,3]) 12 | % 13 | % ind = 14 | % 23 15 | % 12 16 | % 17 | % >> ind = sub2ind_nd([3,3,3],[1,3,1;1,2,2]) 18 | % 19 | % ind = 20 | % 7 21 | % 13 22 | %-------------------------------------------------------------------------- 23 | % MATLAB Ver R2019a 24 | %-------------------------------------------------------------------------- 25 | % $ Author: Jachin (Jianqing Zheng) $ 26 | % $ Revision: 1.0 $ $ Date: 2023/04/05$ 27 | %-------------------------------------------------------------------------- 28 | % See also: 'sub2lab', 'ind2sub' 29 | 30 | %-------------------------------------------------------------------------- 31 | subs=round(subs); 32 | ndims=size(subs,2); 33 | ind=1; 34 | tensor_sz=[1,tensor_sz]; 35 | for i=1:ndims 36 | ind=ind+(subs(:,i)-1).*prod(tensor_sz(1:i)); 37 | end 38 | end -------------------------------------------------------------------------------- /img_proc-toolbox/ind2lab.m: -------------------------------------------------------------------------------- 1 | function lab=ind2lab(ind,lab_sz) 2 | % ind2lab - Get a binary volume (label) with one values at the indexed 3 | % position and zero at the others 4 | %-------------------------------------------------------------------------- 5 | % [lab] = ind2lab(ind,lab_sz) 6 | % 'lab' - output binary volume with one values at the required locations 7 | % 'ind' - the given indexed location 8 | % 'lab_sz'- the size of the required volume 9 | %-------------------------------------------------------------------------- 10 | % Examples: 11 | % >> lab = ind2lab([2,6],[3,3]) 12 | % 13 | % lab = 14 | % 0 0 0 15 | % 1 0 0 16 | % 0 1 0 17 | %-------------------------------------------------------------------------- 18 | % MATLAB Ver R2019a 19 | %-------------------------------------------------------------------------- 20 | % $ Author: Jachin (Jianqing Zheng) $ 21 | % $ Revision: 1.0 $ $ Date: 2023/04/05$ 22 | %-------------------------------------------------------------------------- 23 | % See also: 'sub2lab', 'lab2ind', 'sub2ind_nd' 24 | 25 | %-------------------------------------------------------------------------- 26 | ind_tmp=round(ind); 27 | ind_tmp(any(ind_tmp<1,2),:)=[]; 28 | ind_tmp(ind_tmp>prod(lab_sz))=[]; 29 | lab=zeros(lab_sz);% 30 | if isempty(ind_tmp) 31 | disp('is empty'); 32 | else 33 | lab(ind_tmp)=1; 34 | end 35 | end 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /demo/count_cell_num.m: -------------------------------------------------------------------------------- 1 | close all 2 | clear 3 | %% Directory 4 | 5 | subfolder_names=["20220831 irradiation BM chimera C57 HTP"]; 6 | 7 | folder_path=fullfile('data'); 8 | paths={'D:\Users\JachinZ\Documents\MATLAB\bio_image_process\data\cells\123.jpg'}; 9 | % path={'/Users/LengHoufu/Desktop/baf 1_T001 copy.tif'}; 10 | % '/Users/LengHoufu/Desktop/baf 1_T001 copy.tif', 11 | % '/Users/LengHoufu/Desktop/baf 1_T001 copy.tif' 12 | % }; 13 | 14 | % paths=get_dirs(folder_path,'.jpg'); 15 | 16 | %% Parameter setting 17 | thresh0=0.08; % 18 | thresh1=0.4; % 19 | erode_rate=6; % 20 | sigma0=0.4; % 21 | sigma1=1.2; % 22 | min_area0=50; % 23 | min_area1=400; % 24 | 25 | k_size=701; 26 | 27 | 28 | %% For loop calculation 29 | k=-ones(k_size,k_size); 30 | m=-sum(sum(k))-1; 31 | k((k_size-1)/2,(k_size-1)/2)=m; 32 | kernel=k./m; 33 | areas=cell(numel(paths),3); 34 | for i=1:numel(paths) 35 | img=imread(paths{i}); 36 | % figure(1); 37 | % imshow(img,[]); 38 | R=img(:,:,1); 39 | B=img(:,:,3); 40 | Z=zeros(size(R)); 41 | % imshow(cat(3,Z,Z,B),[]); 42 | B=double(B)./256; 43 | 44 | figure(i) 45 | BM=imgaussfilt(B,sigma0); 46 | BM=conv2(BM,kernel,'same'); 47 | % B=reshape(normalize(reshape(B,[1024*1024,1]),'scale','std'),[1024,1024]); 48 | BM=double(BM>thresh0); 49 | % se = strel('ball',dilation_rate,dilation_rate); 50 | % B=imdilate(double(B>thresh),se); 51 | BM=imgaussfilt(BM,sigma1)>thresh1; 52 | BM=double(BM); 53 | % BM=conv2(BM,kernel,'same'); 54 | BM=bwareaopen(BM,min_area0); 55 | se = strel('cube',erode_rate); 56 | BM=imerode(BM,se); 57 | 58 | BM=bwareaopen(BM,min_area1); 59 | imshow(cat(3,BM./4,Z,B),[]); 60 | 61 | lb_bw=bwlabel(BM,8); 62 | num=max(max(max(lb_bw))) 63 | 64 | end 65 | -------------------------------------------------------------------------------- /img_proc-toolbox/sub2lab.m: -------------------------------------------------------------------------------- 1 | function lab=sub2lab(sub,lab_sz) 2 | % sub2lab - Get a binary volume (label) with one values at the subcript 3 | % position and zero at the others 4 | %-------------------------------------------------------------------------- 5 | % [lab] = sub2lab(sub,lab_sz) 6 | % 'lab' - output binary volume with one values at the required locations 7 | % 'sub' - the given subscript corrdinates 8 | % 'lab_sz'- the size of the required volume 9 | %-------------------------------------------------------------------------- 10 | % Examples: 11 | % >> lab = sub2lab([1,1;2,2],[3,3]) 12 | % 13 | % lab = 14 | % 1 0 0 15 | % 0 1 0 16 | % 0 0 0 17 | % 18 | % >> lab = sub2lab([1,1,1;2,2,2],[3,3,3]) 19 | % 20 | % lab(:,:,1) = 21 | % 1 0 0 22 | % 0 0 0 23 | % 0 0 0 24 | % 25 | % lab(:,:,2) = 26 | % 0 0 0 27 | % 0 1 0 28 | % 0 0 0 29 | % 30 | % lab(:,:,3) = 31 | % 0 0 0 32 | % 0 0 0 33 | % 0 0 0 34 | %-------------------------------------------------------------------------- 35 | % MATLAB Ver R2019a 36 | %-------------------------------------------------------------------------- 37 | % $ Author: Jachin (Jianqing Zheng) $ 38 | % $ Revision: 1.0 $ $ Date: 2023/04/05$ 39 | %-------------------------------------------------------------------------- 40 | % See also: 'ind2lab', 'lab2ind', 'sub2ind_nd', 'ind2sub' 41 | 42 | %-------------------------------------------------------------------------- 43 | sub_tmp=round(sub); 44 | for d=1:numel(lab_sz) 45 | sub_tmp(any(sub_tmp(d)<1,2),:)=[]; 46 | sub_tmp(any(sub_tmp>lab_sz(d),2),:)=[]; 47 | end 48 | lab=zeros(lab_sz);% 49 | if isempty(sub_tmp) 50 | disp('is empty'); 51 | else 52 | lab(sub2ind_nd(lab_sz,sub_tmp))=1; 53 | end 54 | end 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image_processing toolbox 2 | This repo provides the implementation of several image processing techniques implemented via matlab. 3 | 4 | Relative Paper list: 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
Technique nameScript(s)Paper id
Bone shape reconstructionimage_processing/demo/bone_shape_reconstruct_from_dcm.mLeng2025.05.02.651799
17 | 18 | # Demos 19 | 20 | # Usage 21 | ## Setup 22 | ``` 23 | [$DOWNLOAD_DIR]/image_processing/ 24 | ├── data/[$task_name]/ 25 | 26 | ├── image_proc-toolbox/ 27 | ├── ind2lab.m 28 | ├── keep_remove_ranked_vol.m 29 | ├── lab2ind.m 30 | ├── serial_dilate_erode_vol.m 31 | ├── sub2ind_nd.m 32 | ├── vol_rot_gif.m 33 | 34 | ├── file_proc-toolbox/ 35 | ├── get_dirs.m 36 | ├── get_predirs.m 37 | ├── imfiles2giffiles.m 38 | 39 | ``` 40 | 41 | # For the citation 42 | The usage of the bone reconstruction script should cite: 43 | ```bibtex 44 | @article {Leng2025.05.02.651799, 45 | author = {Leng, Houfu and jiang, jiahao and Gassner, Katja and Midha, Swati and Justo-Mendez, Raquel and Zheng, Jianqing and Hall, Timothy and Luo, Lin and West, Suzanne D and Vincent, Tonia L. and Wann, Angus and Patel, Kashyap A and Poulton, Joanna and O{\textquoteright}Callaghan, Chris A. and Lechuga-Vieco, Ana Victoria and Simon, Anna Katharina}, 46 | title = {Mitochondrial heterogeneity disrupts osteoclast differentiation and bone resorption by impairing respiratory complex I}, 47 | elocation-id = {2025.05.02.651799}, 48 | year = {2025}, 49 | doi = {10.1101/2025.05.02.651799}, 50 | publisher = {Cold Spring Harbor Laboratory}, 51 | URL = {https://www.biorxiv.org/content/early/2025/05/02/2025.05.02.651799}, 52 | eprint = {https://www.biorxiv.org/content/early/2025/05/02/2025.05.02.651799.full.pdf}, 53 | journal = {bioRxiv} 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/det_jacob.m: -------------------------------------------------------------------------------- 1 | function D=det_jacob(ddf,lab) 2 | % DETJAC Calculates the determinants of the Jacobian matrices of a 3 | % deformation field. 4 | % D = DETJAC(J) calculates the determinants of the Jacobian matrices of 5 | % the deformation field J, where J is a matrix with size M-by-N-by-2-by-2. 6 | % The output D is a matrix with size M-by-N. 7 | % lab_sz=size(lab,4); 8 | D=zeros(size(lab)); 9 | for lab_id=1:size(lab,4) 10 | J=cal_jac_vol(ddf.*lab(:,:,:,lab_id)); 11 | % Calculate the determinants of the Jacobian matrices 12 | a = J(:,:,:,1,1); 13 | b = J(:,:,:,1,2); 14 | c = J(:,:,:,1,3); 15 | d = J(:,:,:,2,1); 16 | e = J(:,:,:,2,2); 17 | f = J(:,:,:,2,3); 18 | g = J(:,:,:,3,1); 19 | h = J(:,:,:,3,2); 20 | i = J(:,:,:,3,3); 21 | D(:,:,:,lab_id) = (a.*e.*i)+(b.*f.*g)+(c.*d.*h)-(g.*e.*c)-(h.*f.*a)-(i.*d.*b); 22 | end 23 | 24 | end 25 | 26 | 27 | 28 | function [ind,pnd]=img2ind(img,thresh) 29 | if nargin<2 30 | thresh=0.000000001; 31 | end 32 | img_sz=size(img); 33 | ind=find(img>thresh); 34 | pnd=[]; 35 | id=ind; 36 | for s=img_sz 37 | coord=mod(id,s); 38 | pnd=[pnd,coord]; 39 | id=floor(id/s); 40 | end 41 | end 42 | 43 | 44 | function jacob=cal_jac_vol(vol) 45 | vol_sz=size(vol); 46 | % jacob=zeros([vol_sz,vol_sz(end)]) 47 | jacob=[]; 48 | for v=1:vol_sz(end) 49 | [Gx, Gy, Gz] = imgradientxyz(vol(:,:,:,v)); 50 | G=cat(4,Gx,Gy,Gz); 51 | jacob=cat(5,jacob,G); 52 | end 53 | % jacob=cat(5,Gx,Gy,Gz); 54 | for i = 1:vol_sz(end) 55 | jacob(:,:,:,i,i)=jacob(:,:,:,i,i)+1; 56 | end 57 | end 58 | 59 | % 60 | % def eval_detJ_lab(vol1=None,vol2=None,disp=None,thresh=0.5): 61 | % ndims=3 62 | % label=vol1>thresh 63 | % label=label*(ndimage.laplace(label) < 0.1) 64 | % # label=vol2[...,0]>thresh 65 | % # label=np.ones_like(vol2[...,0]) 66 | % # a=np.stack(np.gradient(disp,axis=[-2,-3,-4]),-1) 67 | % # b=np.sum(label) 68 | % # rescale_factor=2 69 | % rescale_factor=1 70 | % # label=zoom(label, [1./rescale_factor]*ndims+[1], mode='nearest') 71 | % label=label[...,::rescale_factor,::rescale_factor,::rescale_factor] 72 | % # disp=zoom(disp, [rescale_factor]*ndims+[1], mode='nearest') 73 | % # label=zoom(label, rescale_factor, mode='nearest') 74 | % # a=np.stack(np.gradient(disp,axis=[-2,-3,-4]),-1) 75 | % # b = np.linalg.det(a) 76 | % Jacob=np.stack(np.gradient(disp,axis=[-4,-3,-2]),-1) 77 | % Jacob[..., 0, 0] = Jacob[..., 0, 0] + 1 78 | % Jacob[..., 1, 1] = Jacob[..., 1, 1] + 1 79 | % Jacob[..., 2, 2] = Jacob[..., 2, 2] + 1 80 | % return np.sum((np.linalg.det(Jacob)<0)*label) -------------------------------------------------------------------------------- /file_proc-toolbox/get_dirs.m: -------------------------------------------------------------------------------- 1 | function [dirs_out]=get_dirs(folder,dirPattern,commonstr,dirs_in) 2 | % get_dirs - Get the directories for required files in one folder and its subfolders 3 | %-------------------------------------------------------------------------- 4 | % get_dirs(folder,dirPattern,commonstr,dirs_in) is a recursive function, 5 | % which returns a cell including the directories of all the required 6 | % files. 7 | %-------------------------------------------------------------------------- 8 | % [dirs_out] = get_dirs(folder,dirPattern,commonstr,dirs_in) 9 | % 'dirs_out' - output cell of the directories of all the required files. 10 | % 'folder' - a dir string of the folder to search. 11 | % 'dirPattern'- a string of required files' pattern. 12 | % 'commonstr' - a string required in the dirs of those selected files. 13 | % 'dirs_in' - a cell of dirs for recursion 14 | %-------------------------------------------------------------------------- 15 | % Examples: 16 | % % Before starting recursion: 17 | % >> folder='/data/someone/Aneurysm_Seg' 18 | % >> dirPat='.jpg' 19 | % >> commonstr={'epoch_1','_2'} 20 | % >> dirs_out=get_dirs(folder,dirPat,commonstr) 21 | % 22 | % % after completing recursion 23 | % dirs_out = 24 | % 25 | % 12×1 cell array 26 | % 27 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_10_2.jpg' 28 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_11_2.jpg' 29 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_12_1.jpg' 30 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_12_2.jpg' 31 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_13_2.jpg' 32 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_14_2.jpg' 33 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_15_2.jpg' 34 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_16_2.jpg' 35 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_17_2.jpg' 36 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_18_2.jpg' 37 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_19_2.jpg' 38 | % '/data/someone/Aneurysm_Seg//Trained_1/prediction/epoch_1_2.jpg' 39 | %-------------------------------------------------------------------------- 40 | % MATLAB Ver >= R2016b 41 | %-------------------------------------------------------------------------- 42 | % $ Author: Jachin $ 43 | % $ Revision: 2.1 $ $ Date: 2018/03/13 22:24 $ 44 | %-------------------------------------------------------------------------- 45 | % See also: 'fileparts', 'contains' 46 | 47 | %-------------------------------------------------------------------------- 48 | 49 | %% parameter transfer 50 | if nargin<4 51 | dirs_in={}; 52 | if nargin<3 53 | commonstr=''; 54 | if nargin<2 55 | dirPattern=''; 56 | end 57 | end 58 | end 59 | %% verify and append 60 | [~,~,pattern]=fileparts(folder); 61 | if (strcmp(pattern,dirPattern)||isempty(dirPattern)) 62 | if ~isempty(commonstr) 63 | if iscell(commonstr) 64 | result=0; 65 | for i=1:size(commonstr,1) 66 | temp=1; 67 | for j=1:size(commonstr,2) 68 | temp=temp&contains(folder,commonstr{i,j}); 69 | end 70 | result=result|temp; 71 | end 72 | else 73 | result=contains(folder,commonstr); 74 | end 75 | else 76 | result=1; 77 | end 78 | if result 79 | dirs_out=[dirs_in;folder]; 80 | else 81 | dirs_out=dirs_in; 82 | end 83 | else 84 | dirs_out=dirs_in; 85 | end 86 | %% recursion 87 | dirs_recur=dirs_out; 88 | files=dir(folder); 89 | % if contains(folder,'/') 90 | % slash='/'; 91 | % else 92 | slash='\'; 93 | % end 94 | for i=3:size(files,1) 95 | fn=files(i).name; 96 | folder_recur=sprintf('%s%s%s', folder,slash, fn); 97 | dirs_out=get_dirs(folder_recur,dirPattern,commonstr,dirs_recur); 98 | dirs_recur=dirs_out; 99 | end 100 | 101 | end 102 | -------------------------------------------------------------------------------- /demo/bone_shape_reconstruct_from_dcm_220831.m: -------------------------------------------------------------------------------- 1 | close all 2 | clear 3 | % set directory 4 | vox_folder=fullfile('data'); 5 | subfolder_names=["20220831 irradiation BM chimera C57 HTP"]; 6 | 7 | %% set parameters 8 | % rot_axis = [1,0,0; ]; 9 | rotx_axis = [1,0,0 ]; 10 | roty_axis = [0,1,0 ]; 11 | 12 | angs= [0,0; 13 | 0,0; 14 | ]; 15 | sec_locs= [0,350;]; 16 | 17 | vol_id=1; 18 | subfolder_id=1; 19 | filter_flag=1; 20 | intensity_bias=[0,0,-100,0,400,100,0,0]; 21 | thresh_bone0=800+4000+intensity_bias(subfolder_id); 22 | thresh_bone1=1900+4000+intensity_bias(subfolder_id); 23 | thresh_bone2=800+4000+intensity_bias(subfolder_id); 24 | sec_bias=180; 25 | min_area1=100; 26 | remove_small_vol=1; 27 | remove_vol_rank=2; 28 | 29 | sigma=4; 30 | sigma_vol=6; 31 | erode_iter=2; 32 | erode_sz=1; 33 | dilate_iter=12; 34 | % dilate_iter=20; 35 | dilate_sz=4; 36 | % dilate_sz=3; 37 | ang=[0,0]; 38 | 39 | %% for loop 40 | dirinfo = dir(fullfile(vox_folder,subfolder_names(subfolder_id))); 41 | dirinfo= dirinfo(3:end); 42 | % dcmfiles = cell(length(dirinfo),1); 43 | dcmfiles = cell(0); 44 | for K = 1 : length(dirinfo) 45 | thisdir = dirinfo(K).name; 46 | if ~all(ismember('.png',char(thisdir))) 47 | dcmfiles =[dcmfiles;fullfile(vox_folder,subfolder_names(subfolder_id),thisdir)]; 48 | end 49 | end 50 | 51 | for pth_id =1:1:numel(dcmfiles) 52 | pth_id 53 | close all; 54 | [img,spatial,dim] = dicomreadVolume(dcmfiles{pth_id}); 55 | img=img(:,:,:); 56 | % if pth_id>size(sec_locs,1) 57 | % ang=angs(end,:); 58 | % sec_loc=sec_locs(end,:); 59 | % else 60 | % sec_loc=sec_locs(pth_id,:); 61 | % ang=angs(pth_id,:); 62 | % end 63 | 64 | img=imrotate3(img,ang(1),rotx_axis); 65 | img=imrotate3(img,ang(2),roty_axis); 66 | %% section 67 | [~,~,z_coord]=ind2sub(size(img),find(img>thresh_bone1)); 68 | sec_loc(2)=max(z_coord)-sec_bias; 69 | sec_loc(1)=sec_loc(2)-100; 70 | % sec_loc(1)=0; 71 | 72 | img(:,:,sec_loc(2):size(img,1))=[]; 73 | img(:,:,1:sec_loc(1))=[]; 74 | 75 | %% thresholding 76 | vol_shape0=(img>thresh_bone0); 77 | vol_shape0=bwareaopen(vol_shape0,min_area1./10); 78 | if filter_flag 79 | vol_shape1=(imgaussfilt3(img,sigma)>thresh_bone1); 80 | vol_shape1=bwareaopen(vol_shape1,min_area1); 81 | vol_shape2=(img>thresh_bone2); 82 | vol_shape2=bwareaopen(vol_shape2,min_area1./5); 83 | end 84 | 85 | %% filter0 86 | if remove_small_vol 87 | vol_shape0=keep_remove_ranked_vol(vol_shape0,[-remove_vol_rank]); 88 | end 89 | 90 | if filter_flag %%%%%% 91 | if remove_small_vol 92 | vol_shape2=keep_remove_ranked_vol(vol_shape2,[-remove_vol_rank]); 93 | end 94 | 95 | %% filter1 96 | vol_shape1 = serial_dilate_erode_vol(vol_shape1,kron([-erode_sz,erode_sz],ones(1,erode_iter)),vol_shape0,min_area1); 97 | vol_shape1=imgaussfilt3(double(vol_shape1),sigma_vol)>0.3; 98 | vol_shape1 = serial_dilate_erode_vol(vol_shape1,kron([erode_sz],ones(1,7)),vol_shape0,min_area1); 99 | vol_shape2=fill_slide_centroid(vol_shape2); 100 | vol_shape2 = serial_dilate_erode_vol(vol_shape2,kron([dilate_sz],ones(1,dilate_iter)),1,0,'cube'); 101 | vol_shape2=imgaussfilt3(double(vol_shape2),sigma_vol)>0.1; 102 | vol_shape2 = serial_dilate_erode_vol(vol_shape2,kron([-dilate_sz],ones(1,dilate_iter)),1,min_area1*200,'cube'); 103 | end 104 | 105 | %% select volume 106 | % calculate the ratio of cancellous bone divided by the volume inside the 107 | % cortical bone. 108 | vol_shape=vol_shape0; 109 | if filter_flag 110 | vol_shape=vol_shape.*(vol_shape2); 111 | vol_low_density=sum(sum(sum(vol_shape0.*vol_shape2))); 112 | vol_total=sum(sum(sum(vol_shape2))); 113 | ratio=vol_low_density./vol_total 114 | end 115 | 116 | %% plot 117 | figure(pth_id); 118 | vol_shape(:,:,1)=0; 119 | % vol_shape(:,:,end)=0; 120 | vs=volshow(double(vol_shape)); 121 | set(vs,'Renderer', 'Isosurface'); 122 | vs.BackgroundColor='w'; 123 | vs.IsosurfaceColor=[1.,1.,1.]; 124 | vs.Isovalue=.5; 125 | vs.CameraTarget=[-0.1,-0.1,0]; 126 | vs.CameraViewAngle=10; 127 | vs.CameraPosition = [-1.5098 0.4677 3.5471]; 128 | vs.CameraUpVector= [-0.1328 -0.0914 0.9869]; 129 | 130 | print(dcmfiles(pth_id)+'_view0'+'.png', '-dpng', '-r900'); 131 | end 132 | 133 | %% function 134 | function [out_vol]=fill_slide_centroid(in_vol) 135 | vol_sum3=sum(sum(in_vol,2),1); 136 | [Y,X,Z]=meshgrid(1:size(in_vol,2),1:size(in_vol,1),1:size(in_vol,3)); 137 | cX=sum(sum(X.*in_vol,1),2)./vol_sum3; 138 | cY=sum(sum(Y.*in_vol,1),2)./vol_sum3; 139 | cZ=sum(sum(Z.*in_vol,1),2)./vol_sum3; 140 | out_vol=in_vol; 141 | idx=round(permute(sub2ind(size(out_vol),cX,cY,cZ),[3,1,2])); 142 | out_vol(idx)=1; 143 | end 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /evaluate_metrics-toolbox/get_thickness_map.m: -------------------------------------------------------------------------------- 1 | function D = get_thickness_map(matrix) 2 | % matrix is a 3D matrix representing the volume 3 | % with the thin plate defined by a boundary value of 1 4 | 5 | % Calculate the distance transform of the boundary points 6 | bvol=matrix>0.5; 7 | bvol_lap=lap_conv3d(bvol)>0.5; 8 | 9 | D = (2 *bwdist(bvol_lap)).*bvol; 10 | map_msk=lap_conv3d(D)>2.0; 11 | D = D.*map_msk.*(D>1.0) ; 12 | % D = bwdist(bvol).*bvol; 13 | % Find the maximum distance along each axis 14 | % p1=find_max_coordinate(D); 15 | % p2=find_closest_point_to_volume(p1, bvol_lap); 16 | % 17 | % % D=find_max_projection_and_set_to_zero(D,p1-p2); 18 | % d=max_intensity_projection(D, p1-p2); 19 | 20 | max_dist = max(max(max(D))); 21 | 22 | % Calculate the thickness of the plate 23 | thickness = max_dist; 24 | end 25 | 26 | %% 27 | 28 | function [proj, proj_coords] = max_intensity_projection(volume, normal) 29 | % Find the two axes that lie in the plane 30 | [~, axis1] = max(abs(normal)); 31 | axis2 = mod(axis1, 3) + 1; 32 | 33 | % Get the dimensions of the projection 34 | proj_dims = size(volume); 35 | proj_dims(axis1) = []; 36 | proj_dims(axis2) = []; 37 | 38 | % Project the volume onto the plane 39 | proj = zeros(proj_dims); 40 | [proj_coords1, proj_coords2] = ndgrid(1:proj_dims(1), 1:proj_dims(2)); 41 | proj_coords = zeros([numel(proj_coords1), 3]); 42 | proj_coords(:, axis1) = proj_coords1(:); 43 | proj_coords(:, axis2) = proj_coords2(:); 44 | proj_coords(:, 3) = dot(normal, bsxfun(@minus, proj_coords, [1, 1, 1]), 2) ./ dot(normal, [0,0,1]'); 45 | 46 | % Find the maximum intensity projection 47 | proj_coords = round(proj_coords); 48 | for i = 1:proj_dims(1) 49 | for j = 1:proj_dims(2) 50 | proj(i,j) = max(volume(proj_coords(i,j,1),:,proj_coords(i,j,3))); 51 | end 52 | end 53 | end 54 | 55 | 56 | 57 | 58 | % function [MIP, MIP_coords] = max_intensity_projection(volume, normal) 59 | % % volume: 3D volume 60 | % % normal: normal vector of the 2D plane 61 | % normal=normal./norm(normal); 62 | % % Find the two axes that lie in the plane 63 | % [~, axis1] = max(abs(normal)); 64 | % axis2 = mod(axis1, 3) + 1; 65 | % 66 | % % Calculate the coordinates of the projection 67 | % [x, y] = meshgrid(1:size(volume, axis2), 1:size(volume, axis1)); 68 | % proj_coords = zeros([numel(x), 3]); 69 | % proj_coords(:, axis1) = reshape(y, [], 1); 70 | % proj_coords(:, axis2) = reshape(x, [], 1); 71 | % proj_coords(:, 3) = round((normal* proj_coords' - dot(normal, [1,1,1]')) ./ dot(normal, [0,0,1]')); 72 | % 73 | % % Clip coordinates outside the volume 74 | % valid_indices = all(proj_coords > 0, 2) & all(proj_coords <= repmat(size(volume), [numel(x), 1]), 2); 75 | % proj_coords = proj_coords(valid_indices, :); 76 | % 77 | % % Compute the maximum intensity projection 78 | % MIP = zeros(size(volume, axis1), size(volume, axis2)); 79 | % MIP_coords = zeros(size(MIP, 1), size(MIP, 2), 3); 80 | % for i = 1:size(proj_coords, 1) 81 | % x = proj_coords(i, axis2); 82 | % y = proj_coords(i, axis1); 83 | % z = proj_coords(i, 3); 84 | % intensity = volume(y, x, z); 85 | % if intensity > MIP(y, x) 86 | % MIP(y, x) = intensity; 87 | % MIP_coords(y, x, :) = [y, x, z]; 88 | % end 89 | % end 90 | % end 91 | 92 | 93 | function coords = get_voxel_coords(size) 94 | % Helper function to compute the coordinates of all voxels in a volume 95 | [x, y, z] = ndgrid(1:size(1), 1:size(2), 1:size(3)); 96 | coords = [x(:), y(:), z(:)]; 97 | end 98 | 99 | function R = get_rot(u, v) 100 | % Calculate the cross product of u and v 101 | w = cross(u, v); 102 | 103 | % Calculate the angle between u and v 104 | theta = acos(dot(u, v)); 105 | 106 | % Check if the vectors are parallel and handle the special case 107 | if theta < eps 108 | R = eye(3); 109 | else 110 | % Calculate the rotation matrix using the axis-angle representation 111 | w_skew = [0, -w(3), w(2); w(3), 0, -w(1); -w(2), w(1), 0]; 112 | R = eye(3) + w_skew*sin(theta) + w_skew^2*(1-cos(theta)); 113 | end 114 | end 115 | 116 | function max_proj_volume = find_max_projection_and_set_to_zero(volume, direction) 117 | 118 | direction = direction / norm(direction); 119 | 120 | % Compute the maximum intensity projection of the volume in the direction vector 121 | projection = sum(volume .* repmat(direction', size(volume)), 4); 122 | [max_projection, idx] = max(projection, [], 'all', 'linear'); 123 | 124 | % Set all voxels in the volume that are not in the projection plane to 0 125 | [xx, yy, zz] = ind2sub(size(volume), idx); 126 | [~, ~, V] = svd(normal); 127 | x_range = 1:size(volume, 1); 128 | y_range = 1:size(volume, 2); 129 | z_range = 1:size(volume, 3); 130 | x_range(xx) = []; 131 | y_range(yy) = []; 132 | z_range(zz) = []; 133 | [X, Y, Z] = ndgrid(x_range, y_range, z_range); 134 | coords = [X(:), Y(:), Z(:)]; 135 | projection_plane = [xx*ones(size(coords, 1), 1), yy*ones(size(coords, 1), 1), zz*ones(size(coords, 1), 1)]; 136 | coords_on_plane = coords - projection_plane; 137 | coords_on_plane_rot = (V' * coords_on_plane')'; 138 | max_dist = max(abs(coords_on_plane_rot), [], 2); 139 | mask = max_dist < 1e-3; % tolerance for numerical errors 140 | volume(~mask) = 0; 141 | 142 | % Display the maximum intensity projection 143 | figure; 144 | imshow(max_projection, []); 145 | 146 | 147 | 148 | 149 | 150 | % volume is the 3D matrix representing the volume 151 | % direction is a 3-element vector specifying the direction 152 | direction = direction./sqrt(sum((direction.^2))); 153 | std_vec=[1,0,0]; 154 | R=get_rot(std_vec,direction); 155 | 156 | % % Determine the direction of the parallel view 157 | % view_direction = [1, 0, 0]; % for example, this is the x-axis direction 158 | 159 | % Calculate the maximum 2D projection in the specified direction 160 | max_proj = max(volume, [], find(direction)); 161 | 162 | % Create a binary mask of the max projection 163 | max_proj_mask = max_proj > 0; 164 | 165 | % Set all voxels in the volume that are not in the max projection to 0 166 | volume(~max_proj_mask) = 0; 167 | 168 | % Display the max projection 169 | imshow(max_proj); 170 | 171 | 172 | 173 | % Compute the dot product between each coordinate and the direction vector 174 | [X, Y, Z] = ndgrid(1:size(volume,1), 1:size(volume,2), 1:size(volume,3)); 175 | coords = [X(:) Y(:) Z(:)]; 176 | proj_coords = coords * direction(:); 177 | 178 | % Reshape the projection coordinates into a 3D matrix 179 | proj_coords = reshape(proj_coords, size(volume)); 180 | 181 | % Compute the maximum value projection along the appropriate dimension 182 | [max_proj, idx] = max(proj_coords, [], 'all', 'linear'); 183 | [max_proj_i, max_proj_j, max_proj_k] = ind2sub(size(volume), idx); 184 | 185 | % Create a binary mask of voxels that are part of the maximum projection 186 | max_proj_mask = zeros(size(volume)); 187 | max_proj_mask(max_proj_i, max_proj_j, max_proj_k) = 1; 188 | % max_proj_mask(max_proj_j, max_proj_i, max_proj_k) = 1; 189 | 190 | % Set all voxels that are not part of the maximum projection to zero 191 | max_proj_volume = volume .* max_proj_mask; 192 | 193 | end 194 | 195 | % % Create a random 3D matrix of size 10x10x10 196 | % volume = rand(10, 10, 10); 197 | % 198 | % % Specify the direction as a unit vector 199 | % direction = [1, 1, 1] / sqrt(3); 200 | % 201 | % % Find the maximum value projection along the direction vector and set all other voxels to zero 202 | % max_proj_volume = find_max_projection_and_set_to_zero(volume, direction); 203 | % 204 | % % Display the resulting volume using the maximum value as the colormap limit 205 | % max_val = max(max_proj_volume(:)); 206 | % figure; 207 | % sliceViewer(max_proj_volume, [], [], [], [], [], [], max_val); 208 | % This code creates a random 3D matrix of size 10x10x10, specifies the direction as a unit vector, and computes the maximum value projection in the volume along that direction using the find_max_projection_and_set_to_zero function. The resulting volume is then displayed using the sliceViewer function from the Image Processing Toolbox, with the maximum value as the colormap limit. 209 | 210 | 211 | 212 | 213 | 214 | 215 | function max_coord = find_max_coordinate(volume) 216 | % volume is the 3D matrix representing the volume 217 | 218 | % Find the maximum value and its index in the volume 219 | [max_value, max_idx] = max(volume(:)); 220 | 221 | % Convert the 1D index to 3D coordinates 222 | [x, y, z] = ind2sub(size(volume), max_idx); 223 | max_coord = [x, y, z]; 224 | end 225 | 226 | function [closest_point, distance] = find_closest_point_to_volume(point, volume, voxel_size) 227 | if nargin<3 228 | voxel_size=[1,1,1]; 229 | end 230 | % point is a 3-element vector representing the query point 231 | % volume is a 3D matrix representing the volume 232 | % voxel_size is a 3-element vector representing the size of a voxel in each dimension 233 | 234 | % Compute the coordinates of all voxels in the volume 235 | [x, y, z] = ndgrid(1:size(volume, 1), 1:size(volume, 2), 1:size(volume, 3)); 236 | voxel_coords = [x(:), y(:), z(:)]; 237 | 238 | % Compute the physical coordinates of each voxel 239 | phys_coords = bsxfun(@times, voxel_coords - 1, voxel_size(:)') + voxel_size(:)'/2; 240 | 241 | % Compute the distances between the query point and each voxel 242 | distances = sqrt(sum((phys_coords - point(:)').^2, 2)); 243 | 244 | % Find the index of the closest voxel 245 | [~, idx] = min(distances); 246 | 247 | % Convert the index to voxel coordinates 248 | [x, y, z] = ind2sub(size(volume), idx); 249 | 250 | % Compute the physical coordinates of the closest voxel 251 | closest_voxel = bsxfun(@times, [x, y, z] - 1, voxel_size(:)') + voxel_size(:)'/2; 252 | 253 | % Compute the distance between the query point and the closest voxel 254 | distance = sqrt(sum((closest_voxel - point(:)').^2)); 255 | 256 | % Return the physical coordinates of the closest point 257 | closest_point = closest_voxel; 258 | 259 | end 260 | 261 | 262 | % function closest_point = find_closest_point_to_volume(point, volume) 263 | % % point is the 3D coordinate of the specific point 264 | % % volume is a 3D matrix representing the volume 265 | % 266 | % % Compute the distance from the point to each point in the volume 267 | % distances = sqrt(sum((volume - repmat(point, size(volume(:), 1), 1)).^2, 2)); 268 | % 269 | % % Find the point with the smallest distance to the point 270 | % [~, idx] = min(distances); 271 | % 272 | % % Convert the 1D index to 3D coordinates 273 | % [x, y, z] = ind2sub(size(volume), idx); 274 | % closest_point = [x, y, z]; 275 | % 276 | % % Check if the closest point is inside the volume 277 | % if volume(closest_point(1), closest_point(2), closest_point(3)) == 1 278 | % % The point is inside the volume, return the point 279 | % return 280 | % end 281 | % 282 | % % Find the boundary of the volume 283 | % boundary = zeros(size(volume)); 284 | % boundary(1,:,:) = 1; 285 | % boundary(end,:,:) = 1; 286 | % boundary(:,1,:) = 1; 287 | % boundary(:,end,:) = 1; 288 | % boundary(:,:,1) = 1; 289 | % boundary(:,:,end) = 1; 290 | % 291 | % % Project the closest point onto the boundary 292 | % distances = sqrt(sum((boundary - repmat(closest_point, size(boundary(:), 1), 1)).^2, 2)); 293 | % [~, idx] = min(distances); 294 | % [x, y, z] = ind2sub(size(volume), idx); 295 | % closest_point = [x, y, z]; 296 | % end 297 | 298 | 299 | 300 | % % Create a 3D matrix with a thin plate of arbitrary orientation 301 | % matrix = zeros(10, 10, 10); 302 | % [x,y,z] = meshgrid(1:10); 303 | % matrix(sqrt((x-5).^2 + (y-5).^2 + (z-5).^2) <= 3) = 1; 304 | % 305 | % % Calculate the thickness of the plate 306 | % thickness = plate_thickness(matrix); 307 | % disp(thickness); 308 | 309 | 310 | 311 | 312 | % 313 | % 314 | % 315 | % function asd=avg_surf_dist(vol1,vol2,side_idx,sample_rate) 316 | % if nargin<4 317 | % sample_rate=1; 318 | % if nargin<3 319 | % side_idx=1; 320 | % end 321 | % end 322 | % % % lap_k1=[]; 323 | % % lap_k0=[0,0,0; 324 | % % 0,-1,0; 325 | % % 0,0,0]; 326 | % % lap_k2=[0,-1,0; 327 | % % -1,6,-1; 328 | % % 0,-1,0]; 329 | % % lap_kernel=cat(3,lap_k0,lap_k2,lap_k0); 330 | % % v1=convn(double(vol1),lap_kernel,'same')>0.5; 331 | % % v2=convn(double(vol2),lap_kernel,'same')>0.5; 332 | % v1=lap_conv3d(vol1)>0.5; 333 | % v2=lap_conv3d(vol2)>0.5; 334 | % % volshow(v2); 335 | % [~,coord1]=img2ind(v1); 336 | % [~,coord2]=img2ind(v2); 337 | % dist_mat=pdist2(coord1(1:sample_rate:end,:),coord2(1:sample_rate:end,:),"euclidean"); 338 | % asd=mean(min(dist_mat,[],side_idx)); 339 | % 340 | % end 341 | % 342 | % function [ind,pnd]=img2ind(img,thresh) 343 | % if nargin<2 344 | % thresh=0.000000001; 345 | % end 346 | % img_sz=size(img); 347 | % ind=find(img>thresh); 348 | % pnd=[]; 349 | % id=ind; 350 | % for s=img_sz 351 | % coord=mod(id,s); 352 | % pnd=[pnd,coord]; 353 | % id=floor(id/s); 354 | % end 355 | % end --------------------------------------------------------------------------------