function WebcamMouse()
import java.awt.Robot;

clc
clear all

disp('Starting up...');

% Define frame rate
NumberFrameDisplayPerSecond=1000;
 
% Open figure
hFigure=figure(1);
 
% Set-up webcam video input
try
   % For windows
   vid = videoinput('winvideo', 1,'RGB24_640x480');
catch
   try
      % For macs.
      vid = videoinput('macvideo', 1);
   catch
      errordlg('No webcam available');
   end
end
 
% Set parameters for video
disp('Setting up video object...');
% Acquire only one frame each time
set(vid,'FramesPerTrigger',1);
% Go on forever until stopped
set(vid,'TriggerRepeat',Inf);
% Get a RGB image
set(vid,'ReturnedColorSpace','RGB');
triggerconfig(vid, 'Manual');

% Set up the COM port for serial communication
disp('Setting up serial communication...');
% Determine which COM port is for microcontroller and change
s = serial('COM4','Parity','none','FlowControl','none','BaudRate',9600);
% Open serial COM port for communication
fopen(s);

% Set up Robot object for mouse control
mouse = Robot;

set(s,'Timeout',2);

% set up timer object
disp('Setting up timer object...');
TimerData=timer('TimerFcn', {@MouseControl,vid,s,mouse},'Period',1/NumberFrameDisplayPerSecond,'ExecutionMode','fixedRate','BusyMode','drop');

% Start video and timer object
disp('Tracking object and controlling mouse...');
start(vid);
start(TimerData);
 
% We go on until the figure is closed
uiwait(hFigure);

% Close and delete serial comm object
fclose(s);
delete(s);
clear s;

% Clean up everything
stop(TimerData);
delete(TimerData);
stop(vid);
delete(vid);
clear persistent variables
clear functions;


% This function is called by the timer to display one frame of the figure 
function MouseControl(obj,event,vid,s,mouse)
import java.awt.event.*;

persistent IM;
persistent handlesRaw;
persistent handlesPlot;
persistent state;

trigger(vid);
IM=getdata(vid,1,'uint8');

% Set state variable to state if not initialized
if isempty(state)
   state = 0;
end

% Get snapshot of current frame and flip along y-axis
data = flipdim(getsnapshot(vid),2);

% Extract red components from image by subtracting red component from gray
diff_im = imsubtract(data(:,:,1), rgb2gray(data));
% Median filter to remove the noise
diff_im = medfilt2(diff_im, [5 5]);
% Convert the grayscale image to binary image
diff_im = im2bw(diff_im,0.2);
% Create connected components and remove all with area less than 16 sq px
diff_im = bwareaopen(diff_im,16);
% Label all connected components
bw = bwlabel(diff_im, 8);
% Get the centroid of objects
stats = regionprops(bw, 'BoundingBox', 'Centroid');

% Display the frame
imshow(data)

hold on

% Serial communication with MCU and mouse control
if (~isempty(stats))
    bb = stats(1).BoundingBox;
    bc = stats(1).Centroid;
    
    % Draw bounding box and centroid of red object in frame
    rectangle('Position',bb,'EdgeColor','r','LineWidth',2)
    plot(bc(1),bc(2), '-m+')
    
    % Send x- and y- coordinates of centroid
    fprintf(s,'%d %d\n\r',[round(bc(1)) round(bc(2))]);
    
    % Receive and unpack packet from MCU
    garbage = fscanf(s,'%d %d');
    in = fscanf(s,'%d %d %d %d %d %d');
    xcoord = in(1);
    ycoord = in(2);
    on = in(3);
    leftclick = in(4);
    rightclick = in(5);
    scrolldir = in(6);
    
    % Switch is on
    if (on)
        mouse.mouseMove(xcoord,ycoord);
    end
    
    % FSM for buttons
    if (state == 0 && leftclick == 1)
        mouse.mousePress(InputEvent.BUTTON1_MASK);
        state = 1;
    elseif (state == 0 && rightclick == 1)
        mouse.mousePress(InputEvent.BUTTON3_MASK);
        state = 2;        
    elseif (state == 0 && scrolldir ~= 0)
        if(scrolldir > 0)
            mouse.mouseWheel(1);
        else
            mouse.mouseWheel(-1);
        end
        state = 3;
    end
    
    if (state == 1 && leftclick == 0)
        mouse.mouseRelease(InputEvent.BUTTON1_MASK);
        state = 0;
    elseif (state == 2 && rightclick == 0)
        mouse.mouseRelease(InputEvent.BUTTON3_MASK);
        state = 0;
    elseif (state == 3)
        if(scrolldir > 0)
            mouse.mouseWheel(1);
        elseif (scrolldir == 0)
            state = 0;
        elseif (scrolldir < 0)
            mouse.mouseWheel(-1);
        end
        
    end
end

hold off
