-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcell_finder.m
143 lines (116 loc) · 3.74 KB
/
cell_finder.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
%CELL_FINDER
%
% [ cells ] = cell_finder( image, pixel_size, border_width,...
% minimum_size, maximum_size, eccentricity, solidity,...
% max_brightness )
%
% Takes an image of cells and finds all the cells that it can that
% conform to a given set of limits. The form of the output is an array of
% ColiCell objects.
%
% Cells are filtered by:
%
% Minimum area - given in nm^2
% Maximum area - given in nm^2
%
% Eccentricity (ratio of major to minor axis) - must be greater than 1
%
% Solidity (proportion of area taken up by cell in convex hull) - between
% 0 and 1.
%
% Max brightness - maximum mean brightness of cell
%
%
% Pixel size gives the size of each pixel, in nm/px (normally on the
% order of 160
%
% Border width gives the exclusion border around the edge of the image,
% in nm
%
function [ cells ] = cell_finder( image_loc, pixel_size, border_width,...
minimum_size, maximum_size, eccentricity,...
solidity, max_brightness )
load('errors.mat');
% Input validation
% Check for correct number of inputs
error( nargchk( 8, 8, nargin ) );
image = imread( image_loc );
% Ensure image is two dimensional
if ~( numel( image ) > 1 && ndims( image ) == 2 )
error( 'Image must be two dimensional' )
end
imageSize = size( image );
% Convert filters to correct units
minimumSize = minimum_size / ( pixel_size ^ 2 );
maximumSize = maximum_size / ( pixel_size ^ 2 );
borderWidth = ceil( border_width / pixel_size );
% Find cell edges
cellEdges = edge(...
imfilter( image, fspecial( 'gaussian', 10, 15 ) ),...
'canny' );
borderMask = zeros( size( image ) );
borderMask( borderWidth + 1:size( image, 1 ) - borderWidth - 1,...
borderWidth + 1:size( image, 2 ) - borderWidth - 1 ) = 1;
%{
cellsMask = imopen(...
bwmorph(...
imfill(...
bwmorph(...
bwmorph( cellEdges & borderMask, 'thicken' ),...
'close' ),...
'holes' ),...
'thin' ),...
strel( 'disk', 4 ) );
%}
cellsMask = imopen(...
imfill(...
bwmorph( cellEdges & borderMask, 'close' ),...
'holes' ),...
strel( 'disk', 4 ) );
checks = { 'Image', 'BoundingBox', 'MeanIntensity' };
if check_arg( minimum_size ) || check_arg( maximum_size )
checks( size( checks, 2 ) + 1 ) = { 'Area' };
end
if check_arg( solidity )
checks( size( checks, 2 ) + 1 ) = { 'Solidity' };
end
if check_arg( eccentricity )
checks( size( checks, 2 ) + 1 ) = { 'MajorAxisLength' };
checks( size( checks, 2 ) + 1 ) = { 'MinorAxisLength' };
end
rp = regionprops( cellsMask, image, checks );
cells = cell( 1, numel( rp ) );
for i = 1:numel( rp )
valid = 0;
if check_arg( minimum_size )
if rp(i).Area < minimumSize
valid = TOO_SMALL;
end
end
if check_arg( maximum_size )
if rp(i).Area > maximumSize
valid = TOO_BIG;
end
end
if check_arg( eccentricity )
if rp(i).MajorAxisLength / rp(i).MinorAxisLength < eccentricity
valid = TOO_ROUND;
end
end
if check_arg( solidity )
if rp(i).Solidity < solidity
valid = TOO_BENT;
end
end
if check_arg( max_brightness )
if rp(i).MeanIntensity > max_brightness
valid = TOO_BRIGHT;
end
end
cells{i} = ColiCell( rp(i).Image, rp(i).BoundingBox(1),...
rp(i).BoundingBox(2), rp(i).MeanIntensity, valid, imageSize );
end
end
function ok = check_arg( arg )
ok = isa( arg, 'double' ) && numel( arg ) == 1 && arg > 0;
end