function output = colonycount(filepath)
%COLONYCOUNT Automatically count bacterial colonies on a Petri dish
%   COLONYCOUNT(FILEPATH) counts the colonies on a picture of a bacterial
%   plate saved as a JPEG and returns the number. FILEPATH should be in 
%   string form, and can either be the full file path to the image 
%   (i.e. 'S:\2010\matlab\picture.jpg') or the relative path from the 
%   current directory ('matlab\picture.jpg' if already in the '2010' 
%   directory)
%
%   BASIC INSTRUCTIONS:____________________________________________________
%   COLONYCOUNT initially outlines all objects it counts within the 
%   specified area of interest, then allows a round of adding colonies and 
%   a round of removing colonies. It is beneficial to select a slightly
%   smaller, more centered area, rather than larger area, as stray colonies
%   can be selected after the autocount and undesirable noise is avoided. 
%   After both rounds have occurred, a total estimate is printed above the 
%   image, as well as on the command prompt. Please note the addition and 
%   removal of colonies are tallied by internal counters and do not 
%   actually alter the original image.
%
%   STEP BY STEP INSTRUCTIONS:_____________________________________________
%   1. Drag the cursor to create a box around the Petri dish. You can 
%   reposition the box after creating it. Double click inside box when
%   satisfied. This zooms the program into the most relevant part of the 
%   picture, the dish itself.
%   
%   2. Drag the cursor again, this time to create a circle. You can resize
%   the circle after initially creating it. Use the circle to surround as 
%   much area inside the Petri dish WITHOUT GETTING TOO CLOSE TO THE INSIDE
%   EDGE OF THE DISH ITSELF. Getting too close to the edges will result in 
%   the edges being counted as many, many colonies, making the final number
%   completely irrelevant. YOU CAN ADD COLONIES THAT ARE VERY CLOSE TO THE 
%   EDGE TO THE COUNT LATER. If the edge of the inside of the Petri dish
%   is highlighted after you've progressed past this point, just exit the
%   program and restart. Double click inside the circle to continue.
%   
%   3. At this point, colonies that were counted should be outlined in red.
%   Select any additional colonies now. This includes colonies that 
%   were too close to the edge of the dish to be included inside the circle,
%   colonies that were too small to be seen by the program, colonies that
%   are visibly overlapping each other (only one of the two would have been
%   counted, so add one of them to the count). Where you actually click 
%   isn't vital, as the program uses a simple counter to keep track. Click
%   to the left of the image to "undo" a wrong click, which will fade out
%   the wrong point. Click above the image once you're satisfied with your
%   choice of extra colonies.
% 
%   4. Same method as above, except this time you should select any objects
%   that ARE NOT colonies, such as flashes of light, imperfections in the
%   agar, spots of dust, etc.
% 
%   5. The number of colonies is displayed both within the program and on
%   the command line. The display in the program tells you how many
%   colonies were automatically counted, and how many were manually added
%   or subtracted in steps 3 and 4.
% 
%   6. That's it, you're done! Now rinse and repeat for the 20 other plates
%   you have. Here's a cute ASCII kitty I found on the interwebs for your
%   trouble.
%          .       .         
%          \`-"'"-'/
%           } 6 6 {    
%          =.  Y  ,=   
%            /^^^\  .
%           /     \  )           
%          (  )-(  )/ 
%           ""   ""     
% 
%   KNOWN ISSUES:__________________________________________________________
%   - Writing on the plate leads to incorrect "colonies" being marked in the 
%     area around the words. ENSURE PLATES ARE ONLY MARKED ON THE SIDES if
%     you plan to use this program.
%   - Flashes of light are often incorrectly marked as colonies, so it is 
%     important to take pictures with FLASH OFF
%   - If the area of interest spills over onto the edges of the Petri dish,
%     these edges are often incorrectly counted as multiple colonies
%   - Images that are very dim will result in fewer colonies being
%     automatically counted
%   - Pictures where the colonies are darker than the background will
%     produce variable results
%   - The initial picture that pops up will likely output a warning to
%     the command line that "Image is too big to fit on screen; displaying
%     at x%". This is expected and accounted for in the program, and is NOT
%     an error.
%
% Sevile's off-the-shelf-now version 7
% 3/7/2012
% author: Naveen Ponnappa, BE '12

%read and show
Ii = imread(filepath);
set(figure,'Color','k');
Iinit = imshow(Ii);
title('Drag the cursor around the entire petri dish to zoom. {\color{red}Double click} inside the box to continue.','Color','g');
xlabel('You can resize all of the shapes used to select a region in this program.','Color','g');
ylabel('Use {\color{green}help} command for tutorial.','Color','r');
%zoom & resize
Icrop = imcrop;
Isize = size(Icrop);
%largest dimension is 700 pixels
if(Isize(2)>Isize(1))
    I = imresize(Icrop, [NaN 700]);
else
    I = imresize(Icrop, [700 NaN]);
end
close;
set(figure,'Color','k');
Ia=imshow(I);

%determine dimensions
res=size(I);
start=min(res(1:2));
%choose region of interest
C=imellipse(gca,[.25*start .25*start start/2 start/2]);
title('Drag cursor handles of the circle inside the petri dish.','Color','g');
xlabel('The circle should be smaller than and centered within the petri dish, without touching its inner edges. {\color{green}Double click} inside the box to continue.','Color','r')
wait(C);
mask = createMask(C,Ia);

%remove background noise
I2 = imtophat(I,strel('disk',6));%adjustable
green = I2(:,:,2);
g3 = imopen(green,strel('disk',1')); %adjustable

% figure,imshow(green)
% figure,imshow(g3)
%convert to black and white, focus only on region of interest
bw = im2bw(g3,.03);%adjustable
% figure,imshow(bw)
bw2 = bw & mask;

%draw outlines on original image
bwp = bwperim(bw2);
ro = I(:,:,1);
go = I(:,:,2);
bo = I(:,:,3);
ro(bwp) = 255;
go(bwp) = 0;
bo(bwp) = 0;
I3 = cat(3, ro, go, bo);
set(figure,'Color','k'),imshow(I3);

%count
pr3 = regionprops(bw2,'Centroid');
pr3 = numel(pr3);

%add additional colonies that were not initially counted
title(['Click on the image to select additional colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '})'],'Color','g');
ylabel('Click {\color{red}HERE} to undo previous selections. Previous selections will turn dark.','Color','g');
xlabel('If the inner edges of the petri dish have been selected as colonies, exit and restart the program.','Color','r');
counter = 0;
colonies = [];
i = 1;
j = 1;
while j>=0 
    [i,j] = ginput(1);
    if j<0
        break;
    elseif i<0
        r = rectangle('Curvature',[1 1],'Position',[colonies(counter,1) colonies(counter,2) 2 2]);
        set(r,'FaceColor',[.2 .2 .2],'EdgeColor',[0 .7 .7]);
        counter = counter - 1;
        title(['Click on the image to select additional colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '} {\color{cyan}+ ' num2str(counter) '})']);
    else
        x = round(i);
        y = round(j);
        r = rectangle('Curvature',[1 1],'Position',[x y 2 2]);
        set(r,'FaceColor',[0 1 1],'EdgeColor',[0 0 0]);
        counter = counter + 1;
        colonies(counter,1:2)=[x,y];
        title(['Click on the image to select additional colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '} {\color{cyan}+ ' num2str(counter) '})']);
    end
end

%remove objects that should not have been counted as colonies
title(['Click on the image to select wrongly auto-marked colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '} {\color{cyan}+ ' num2str(counter) '})'],'Color','g');
ylabel('Click {\color{red}HERE} to undo previous selections. Previous selections will turn dark.','Color','g');
counter2 = 0;
colonies = [];
i = 1;
j = 1;
while j>=0 
    [i,j] = ginput(1);
    if j<0
        break;
    elseif i<0
        r = rectangle('Curvature',[1 1],'Position',[colonies(counter2,1) colonies(counter2,2) 2 2]);
        set(r,'FaceColor',[0 0 0],'EdgeColor',[.6 .3 .6]);
        counter2 = counter2 - 1;
        title(['Click on the image to select wrongly auto-marked colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '} {\color{cyan}+ ' num2str(counter) '} {\color{magenta}- ' num2str(counter2) '})']);
    else
        x = round(i);
        y = round(j);
        r = rectangle('Curvature',[1 1],'Position',[x y 2 2]);
        set(r,'FaceColor',[1 .2 1],'EdgeColor',[0 0 0]);
        counter2 = counter2 + 1;
        colonies(counter2,1:2)=[x,y];
        title(['Click on the image to select wrongly auto-marked colonies. Click {\color{red}HERE} when done. (# of colonies = {\color{white}' num2str(pr3) '} {\color{cyan}+ ' num2str(counter) '} {\color{magenta}- ' num2str(counter2) '})']);
    end
end

%display numbers onscreen, output is total colonies after adjusting
title(['Estimate: ' num2str(pr3+counter-counter2) ' ({\color{white}' num2str(pr3) ' autocounted} {\color{cyan}+ ' num2str(counter) ' colonies} {\color{magenta}- ' num2str(counter2) ' noncolonies})'],'Color','g');
ylabel('');
xlabel('');
output = pr3 + counter - counter2;