function numCells = countCells(varargin), %NUMCELLS count number of cells in the image. % numCells = countCells(cellImage,cellCenters,cellDimension) counts number % of cells in the image. The Algorithm learns about what do you call a % cell from the examples of cells in the image. The user provides % position of the center for several cells (5-7 is usually enough) and % a typical cell dimension (in number of pixels that fits across a cell). % The Algorithm identifies and counts the cells via iterative process. % % cellImage is an image consisting of cells to be counted. cellImage % can be image of any class or a file name of the image to be % read by imread. See imread.m for file type specifics. % % cellCenters is a 2D numerical array of (x,y) location of the centers of % typical cells. The algorithm learns about what do you call % a cell based on these control cells. Make sure these cells % are visible clearly in the image and do not overlap with % other features. cellCenters has size % 2-by-numberOfControlCells. A typical number of control % cells should be 5-7. % % cellDimension is an avarage number of pixels that fit across a typical % cell. % % Example % ------- % cellImage = 'redBloodCells.jpg'; % cellCenters = [81 27;63 23;46 80;91 78;94 72;46 80]; % cellDimension = 7; % numCells = countCells(cellImage,cellCenters,cellDimension); % % with this image, the numCells should be 2610. % See also IMREAD. % Copyright 2004 Svetlana V. Panasyuk [aMatrix, aCell] = parse_inputs(varargin{:}); [len1 len2] = size(aMatrix); siz = size(aCell); num1 = -(siz(1)-3)/2:(siz(1)-3)/2; num2 = -(siz(2)-3)/2:(siz(2)-3)/2; cellCount = 0; x2 = 1;nn = 0;X2 =~ aMatrix; while sum(x2(:))>0, x1 = imfilter(aMatrix.*(aMatrix<-std(aMatrix(:))),aCell,'rep','same'); x2 = bwmorph(x1>max([max(x1(:))-3*std(x1(:)) 0.25]),'shrink'); cellCount = cellCount + sum(x2(:)); X2 = X2 + x2; [i j] = find(x2); for k = 1:length(i), aMatrix(min(max(i(k)+num1,1),len1),min(max(j(k)+num2,1),len2)) = 0; end aMatrix = aMatrix - mean(aMatrix(:)); nn(end+1) = sum(x2(:)); end numCells = sum(sum(X2)); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Function: parse_inputs function [aMatrix, aCell] = parse_inputs(varargin), % Outputs: aMatrix 2D numerical (double) array same as input image, but % scaled between 0 and 1 % aCell 2D numerical (double) array representing an image of a % typical cell and of the same size as a typical % cell. % nargchk(3,3,nargin); % First, check the image or its file & assign the image array if ischar(varargin{1}), aMatrix = imread(varargin{1}); elseif isnumeric(varargin{1}), aMatrix = varargin{1}; else error('first argument must be a filename string or an image array.'); end aMatrix = im2double(aMatrix(:,:,1)); aMatrix = (aMatrix - min(aMatrix(:)))/(max(aMatrix(:)) - min(aMatrix(:))); aMatrix = aMatrix - mean(aMatrix(:)); % Second, check & assign the typical cell info str = {'cellImage','cellCenters','cellDimension'}; for k = 2:3, if ~isnumeric([varargin{k}]), error(['The ' str{k} ' argument must be numeric.']); end end siz = size(varargin{2}); if isempty(find(siz==2)), error('Second argument must be X-by-2 or 2-by-X array.'); end cellCenters = permute(varargin{2},[find(siz==2),find(siz~=2)]); cellRad = ceil((varargin{3}-1)/2); num = -cellRad:cellRad; for k = 1:length(cellCenters(1,:)), aCell(:,:,k) = aMatrix(cellCenters(1,k)+num,cellCenters(2,k)+num); end aCell = mean(aCell,3) - mean(aCell(:));