Commit e6b28637 authored by Andrew Cohen's avatar Andrew Cohen

Merge branch 'msLoG'

parents 9864ff4b 0a990728
......@@ -5,7 +5,7 @@ function rgDistance=ccDistance(CONSTANTS,srcCells,dstCells,newCellIDs)
rgDistance=[];
VMAX = 3; % fraction of RMAX moved in one time frame
NDISTANCES=5; % max # out edges per node
NDISTANCES=3; % max # out edges per node
if ~exist('newCellIDs','var')
newCellIDs=[];
else
......
function bw=aiAreaOpen(bw,min_radius_pixels)
if ~is3D(bw)
% 2d - use pi*r^2 approximation
radius=min_radius_pixels(1);
area = radius^2 * pi;
area=round(area);
bw=bwareaopen(bw,area);
return;
end
% if ~is3D(bw)
% % 2d - use pi*r^2 approximation
% radius=min_radius_pixels(1);
% area = radius^2 * pi;
% area=round(area);
% bw=bwareaopen(bw,area);
% return;
% end
maskRadius=0.5*min_radius_pixels;
maskRadius=max(maskRadius,[1,1,1]);
if ~is3D(bw)
maskRadius(3)=0;
end
ee=HIP.MakeEllipsoidMask(maskRadius);
bwSeeds=imerode(bw,ee);
bw=imreconstruct(bwSeeds,bw);
% bw=imreconstruct(bwSeeds,bw);
% faster by 2x compared to imreconstruct...
idx=find(bwSeeds);
cc=bwconncomp(bw);
L=labelmatrix(cc);
idxIntersect=cellfun(@(x) intersect(x,idx),cc.PixelIdxList,'UniformOutput',false);
idxDelete=cellfun(@isempty,idxIntersect);
bw(vertcat(cc.PixelIdxList{idxDelete}))=0;
function [L,num,bwBoundary]=allocateShake(bw,bw2,min_radius_pixels,segParams)
bwBoundary=assignShake(bw,bw2,true);
bwReduce=Segment.aiAreaOpen(bwBoundary,min_radius_pixels);
% any components that were not big enough?
if find(bwBoundary & ~bwReduce,1,'first')
% "re-absorb" components too small to exist on their own
% allow disconnected components in case whole CC was removed
bwBoundary=assignShake(bwReduce,bw2,false);
bwBoundary=Segment.aiAreaOpen(bwBoundary,min_radius_pixels);
end
% now, the boundary has been resent, label that and done
[L,num]=bwlabeln(bwBoundary);
return
function bwBoundary=assignShake(bw,bw2,bNoDisconnected)
d=bwdist(bw);
L=watershed(d);
L(~bw2)=0;
bwBoundary=logical(L); % cell image with boundaries set to 0
% don't allow disconnected components
[LX,nx]=bwlabeln(bwBoundary);
idx=unique(LX(bw));
% the boundary image, remove the connected components not from bw (e.g.
% bw2 only)
bwBoundary=bwBoundary&ismember(LX,idx);
% now, the boundary has been resent, label that and done
[L,num]=bwlabeln(bwBoundary);
return
if bNoDisconnected
[LX,nx]=bwlabeln(bwBoundary);
idx=unique(LX(bw));
% the boundary image, remove the connected components not from bw (e.g.
% bw2 only)
bwBoundary=bwBoundary&ismember(LX,idx);
end
......@@ -119,17 +119,6 @@ else
rp=[];
end
d=bwdist(~logical(L));
area_min=2*min_area_pixels;
if segParams.isPhase
dmin=min(min_radius_pixels)*1.5;
elseif segParams.bCytoplasmic
dmin=min(min_radius_pixels)/4;
area_min=min_area_pixels/2;
else
dmin=0.75*min(min_radius_pixels);
end
% final CC pass
if ~is3D(im)
bounds=bwboundaries(bwBoundary,'noholes');
......@@ -140,9 +129,6 @@ end
CC=bwconncomp(L);
for n=1:num
idx=CC.PixelIdxList{n};
if length(idx)<area_min && max(d(idx))<dmin
continue
end
if is3D(im)
newCell=Segment.frameSegment_create_3D(idx,size(bw),chan,t);
else
......@@ -186,7 +172,7 @@ if bEnsemble
end
tElapsed=toc;
sz=sprintf('segmented frame %d found %d hulls, useCuda=%d, time=%f\n',t,length(Cells),USE_CUDA,tElapsed);
sz=sprintf('segmented frame %d found %d hulls, useCuda=%d, minRadius=%f time=%f\n',t,length(Cells),USE_CUDA,segParams.minimumRadius_um,tElapsed);
ljsLog(sz,3);
if DRAW
title([num2str(tElapsed,'%0.0f') 'seconds']);
......
......@@ -30,8 +30,7 @@ if is3D(im)
return
end
if USE_CUDA
logRadius=min_radius_pixels.*(1/sqrt(3));
imLog=HIP.LoG(im,logRadius,[]);
imLog=msLog(im,min_radius_pixels);
else
% use difference of gaussian approximation
logRadius=min_radius_pixels;
......@@ -42,10 +41,7 @@ if is3D(im)
else
% 2D
if USE_CUDA
logRadius=(1/sqrt(2)).*min_radius_pixels;
logRadius(2)=logRadius(1);
logRadius(3)=0;
imLog=HIP.LoG(im,logRadius,[]);
imLog=msLog(im,[min_radius_pixels(1:2),0]);
else
if length(min_radius_pixels)>1
logRadius=0.5*min(min_radius_pixels(1:2));
......@@ -118,3 +114,25 @@ if length(size(im))==3
else
b3D=false;
end
function imLog=msLog(im,min_radius_pixels)
logScale=[0.25:0.25:1.25];
imLogCombined=[];
if length(min_radius_pixels)==3 && min_radius_pixels(3)>0
% 3d
logRadius=((1/sqrt(3)).*min_radius_pixels);
nDim=4;
else
% 2d
logRadius=((1/sqrt(2)).*min_radius_pixels);
nDim=3;
end
for i=1:length(logScale)
lrad=logScale(i).*logRadius;
imf=HIP.LoG(im,lrad,[]);
imLogCombined=cat(nDim,imLogCombined,imf);
end
imLog=max(imLogCombined,[],nDim);
4;
\ No newline at end of file
......@@ -24,6 +24,13 @@ for i=1:length(names)
segParams=setfield(segParams,names{i},fv);
end
end
% convert to row vectors for easier readability
if isfield(segParams,'minimumRadius_um')
segParams.minimumRadius_um=segParams.minimumRadius_um(:)';
end
if isfield(segParams,'NLM')
segParams.NLM=segParams.NLM(:)';
end
......
......@@ -13,9 +13,10 @@ else
end
%
bwOut=bw;
nIter=100; %10*max(min_radius_pixels);
nIter=pi*max(min_radius_pixels)/2;
for nDilate=1:nIter
bwKernels=bwOut&~bwLog;
bwKernels=imfill(bwKernels,'holes');
bwKernels=Segment.aiAreaOpen(bwKernels,0.5*min_radius_pixels);
L=bwlabeln(bwKernels);
......
......@@ -21,34 +21,25 @@ if sensitivity>1 && round(sensitivity)==sensitivity
return;
end
if is3D(im)
nsz=2*floor(size(im)/16)+1;
T=adaptthresh(imLog,0.5,'NeighborhoodSize',nsz,'statistic','gaussian');
bwLog=imbinarize(imLog,T);
bwLog=Segment.aiAreaOpen(bwLog,min_radius_pixels);
nsz=4*floor(size(im)/16)+1;
T=adaptthresh(im,sensitivity,'NeighborhoodSize',nsz,'statistic','gaussian');
bw=imbinarize(im,T);
bw=Segment.aiAreaOpen(bw,min_radius_pixels);
if segParams.isPhase
[bw,bwLog]=phaseThreshold(im,bwLog,min_radius_pixels,segParams,...
sensitivity,medianMask);
return;
end
% else (not 3d)
nsz=4*floor(size(im)/16)+1;
T=adaptthresh(imLog,0.5,'NeighborhoodSize',nsz,'statistic','gaussian');
bwLog=imbinarize(imLog,T);
bwLog=Segment.aiAreaOpen(bwLog,2*min_radius_pixels);
if segParams.isPhase
[bw,bwLog]=phaseThreshold(im,bwLog,min_radius_pixels,segParams,...
sensitivity,medianMask);
return;
if is3D(im)
% lower density (generally?) use smaller radius
nsz=2*floor(size(im)/16)+1;
else
% use 2x the default nhood size
T=adaptthresh(im,sensitivity,'NeighborhoodSize',4*floor(size(im)/16)+1,'statistic','gaussian');
bw=imbinarize(im,T);
nsz=4*floor(size(im)/16)+1;
end
T=adaptthresh(im,sensitivity,'NeighborhoodSize',nsz,'statistic','gaussian');
bw=imbinarize(im,T);
bw=Segment.aiAreaOpen(bw,min_radius_pixels);
4;
......
function ljsPath=getLeverjsPath(file)
thisFile=mfilename('fullpath');
[thisFolder,~,~]=fileparts(thisFile);
ljsPath=fullfile(thisFolder,'..','leverjs',file);
\ No newline at end of file
if isdeployed()
thisFolder=fullfile(pwd(),'matlab');
else
thisFile=mfilename('fullpath');
[thisFolder,~,~]=fileparts(thisFile);
end
ljsPath=fullfile(thisFolder,'..','leverjs',file);
if ~exist(ljsPath,'file')
ljsPath=fullfile(thisFolder,'..',file);
end
if ~exist(ljsPath,'file')
ljsPath=fullfile(thisFolder,file);
end
if ~exist(ljsPath,'file')
fprintf(2,'getLeverjsPath:: could not locate file in %s in folder %s\n',file,thisFolder);
ljsPath=[];
end
......@@ -8,23 +8,20 @@ end
if ~isempty(timerVal)
elapsedTime=toc(timerVal);
end
if isempty(timerVal) || isempty(configLevel) || elapsedTime>10
% read from config
if exist('../config.js','file')
fname='../config.js';
elseif exist('./config.js','file')
fname='./config.js';
else
fname=[];
end
fname=getLeverjsPath('config.js');
configLevel=1;
if ~isempty(fname)
fid=fopen(fname,'r');
jsConfig=fscanf(fid,'%s\n');
fclose(fid);
jsConfigLevel=regexp(jsConfig,'logLevel=\d*[^;]','match');
if ~isempty(jsConfigLevel)
configLevel=str2double(jsConfigLevel{1}(length('logLevel=')+1));
fid=fopen(fname,'r');
if fid~=-1
jsConfig=fscanf(fid,'%s\n');
fclose(fid);
jsConfigLevel=regexp(jsConfig,'logLevel=\d*[^;]','match');
if ~isempty(jsConfigLevel)
configLevel=str2double(jsConfigLevel{1}(length('logLevel=')+1));
end
end
end
end
......
......@@ -13,6 +13,8 @@ fprintf(1,'matlabPollDB pid=%d\n',pid);
AddSQLiteToPath();
hipCheckSetRegistry();
ljsLog(['matlabPollDB:: HIP mutex from OS: ' getenv('HYDRA_ENABLE_MUTEX')],1);
warning('off','all');
if nargin>1
......
No preview for this file type
......@@ -34,7 +34,7 @@ open this link: <https://leverjs.net/download/>. click on the latest (windows --
you can download sample image data from the link as well, as well as a zip file of a recent git archive (better to see "INSTALLING FROM SOURCE" below)
Finally, (sort of optionally, you really will want this) **install the matlab 2017b runtime (v9.3)** so analysis and image import to work: https://www.mathworks.com/products/compiler/matlab-runtime.html. If you have matlab 2017b installed (including database toolkit) you can skip this step.
Finally, (sort of optionally, you really will want this) **install the matlab 2019b runtime (v9.7)** so analysis and image import to work: https://www.mathworks.com/products/compiler/matlab-runtime.html. If you have matlab 2019b installed (including database toolkit) you can skip this step.
<h1>INSTALLING FROM SOURCE</h1>
......@@ -46,7 +46,7 @@ Finally, (sort of optionally, you really will want this) **install the matlab 20
1. install python 2.7 (and make sure it's on your path!). from the node.js command prompt, type 'python' to be sure. NOTE I did not need to do this explicitly on the mac.
2. if you want to analyze the images, and you don't have **matlab 2017b runtime** installed, download and and run the mcr installer from here: https://www.mathworks.com/products/compiler/matlab-runtime.html
2. if you want to analyze the images, and you don't have **matlab 2019b runtime** installed, download and and run the mcr installer from here: https://www.mathworks.com/products/compiler/matlab-runtime.html
3. install git lfs support from https://git-lfs.github.com/
......@@ -102,7 +102,7 @@ some users have reported trouble with npm not installing electron (once on a Mac
<h3>notes</h3>
a. you will need to have matlab2017b installed, or the runtime. download the runtime from https://www.mathworks.com/products/compiler/matlab-runtime.html
a. you will need to have matlab2019b installed, or the runtime. download the runtime from https://www.mathworks.com/products/compiler/matlab-runtime.html
b. the software works on windows, unix and mac. for unix and mac, the matlab path in cmdloop.js is hardcoded (see CmdLoop.js.getMCRpath()). for mac, the path to the nodejs binary is also hardcoded in the importer (matlab/+Import/leverImport.m) as /usr/local/bin/node. this is because matlab on mac doesn't seem to pick up the system path variable...
......@@ -133,6 +133,34 @@ b. it is possible to open the .LEVER file directly using e.g. the DB Browser sql
c. to debug matlab process, edit config.js and set 'debugMatlab' to true. start the image window renderer program, pick your algorithms and select reseg all (or next). then start matlab. run matlabpollDB('\path\to\leverFile.LEVER'). Or, just run matlabPollDB and it usually finds the right LEVER file automagically (from lever.state tidbit left by CmdLoop.js).
<h1>interactive use</h1>
leverjs can be used interactively from any image analysis environment. MATLAB has the most helper code.
prerequisites,
(1) add to your path: hydra-image-processor/source/src/matlab and leverUtilities/src/matlab
(2) run AddSQLiteToPath();
now, some useful tidbits:
```
strDB='\path\to\your\leverFile.LEVER';
[conn,CONSTANTS,segParams]=openDB(strDB);
```
conn is the database connection to your lever file. it is used in almost all the MATLAB entry points.
segParams are the segmentation settings on your file. these need to be set first. if you want to debug
your segmentation (i.e. Segment.frameSegment()) be sure segParams.minimumRadius_um is set to a scalar
(not an ensemble segmentation).
```
% segment time t
cx=Segment.frameSegment(conn,t,CONSTANTS,segParams);
% write results into database for visualization - most useful for 3-d viewing
% be sure there are not already objects at time t in the database
Write.CreateCells(conn,cx);
```
<h1>scripting and image capture for visualization</h1>
see the scripting tab in the electron (stand-alone) image window for more details...there is now a matlab/+MovieMaker folder with two examples.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment