% Skin Pixels Motion Detection
% ICBV 2008 Course Final Project, May 2008
% Aviad Pinkovezky 021396767 aviadpin@cs.bgu.ac.il
% Arik krol 042835850 arikkrol@gmail.com
function res = motion(filename)

gaussianFilter =( 1/273) .*   [1, 4, 7, 4, 1;
    4,16,26,16,4;
    7,26,41,26,7;
    4,16,26,16,4;
    1, 4, 7, 4, 1];

direction = 0;  % -1 : right to left , 1: left to right, 0:no current movement
newDirection = 0;
skinPixThresh = 1400; % amount of skin pixels that is determined as palm movement
consecFrames = 0; % number of consecutive frames in which skin motion was detected (numOfPixels > skinPixThresh
currXavg = -1;  %not calculated yet
prevXavg = -1;  %not calculated yet

fileinfo = aviinfo(filename);
firstFrame = aviread(filename,1);

firstFrameGray = rgb2gray(firstFrame.cdata);
firstFrameGray = double(firstFrameGray);

[firstFrameRGB,Map]= frame2im(firstFrame) ;
dims = size(firstFrameRGB);
rows = dims(1);
colms = dims(2);
numFrames = fileinfo.NumFrames;
for i = [2:+1:numFrames];
    secondFrame = aviread(filename,i);

    secondFrameGray = rgb2gray(secondFrame.cdata);

    [secondFrameRGB,Map]= frame2im(secondFrame) ;

    hsv2 = rgb2hsv(secondFrameRGB);

    % motion detection part:
    firstFrameGray = rgb2gray(firstFrame.cdata);
    firstFrameGray = double(firstFrameGray);
    secondFrameGray = rgb2gray(secondFrame.cdata);
    secondFrameGray = double(secondFrameGray);
    if (~isequal(firstFrameGray ,secondFrameGray))
        diff = abs(secondFrameGray - firstFrameGray);
        diff= diff ./ 255;  % normailizing the image so we can smooth it

        diff = conv2(gaussianFilter,diff); % remove noise by gaussian smoothing

        skinNumAvgVec =   skinMotion (firstFrameRGB ,secondFrameRGB ,diff);

        if skinNumAvgVec(1)< skinPixThresh % for each frame that doesn't contain movement, we have to reset those values
            direction = 0;
            consecFrames = 0;
            currXavg = -1;
            prevXavg = -1;

        else
            currXavg = skinNumAvgVec(2);
            if consecFrames == 0
                consecFrames = consecFrames +1;
            else
                %now in prevXavg we have a value
                if currXavg > prevXavg
                    newDirection = 1;
                else
                    newDirection = -1;
                end
                if direction == 0
                    direction = newDirection;
                    consecFrames = consecFrames +1;
                else
                    if direction == newDirection
                        consecFrames = consecFrames +1;
                        if consecFrames == 3
                            %here we want to print a message, in the real
                            %utility, this part connects to the outer
                            %progrma in order to make the browsing
                            % all directions refer to the user (right is
                            % the right side of the user, not the screen
                            if direction == 1
                                'Right to Left Movement detected'
                            else
                                'Left to Right Movement detected'
                            end
                        end
                    else
                        direction = 0;
                        consecFrames = 0;
                    end
                end
            end %if
        end
        firstFrame = secondFrame;
        prevXavg = currXavg;
    end %if
end %main loop

% first entry of result vector - number of skin pixels detected in 
% the lowest 1/3 of the image
% second enrty  - average X value of those skin pixels
function skinNumAvgVec = skinMotion (rgb1,rgb2,Motion)
dims = size(rgb1);
rows = dims(1);
colms = dims(2);
movementMat = zeros(rows,colms);

hsv1 = rgb2hsv(rgb1);
hsv2 = rgb2hsv(rgb2);

skinNumAvgVec =  [0 0];
for i = rows*2/3:rows
    for j = 1:colms
        if Motion(i,j) >= 40/255;
            if (skinPixel(hsv2,i,j) == 1)
                movementMat(i,j)=255;
                skinNumAvgVec(1)=skinNumAvgVec(1)+1;
                skinNumAvgVec(2)=skinNumAvgVec(2)+j;
            end
        end
    end
end


skinNumAvgVec(2)=skinNumAvgVec(2)/ max(skinNumAvgVec(1),1);

function isSkin = skinPixel(hsvMat ,i ,j)
h = 360 * hsvMat(i,j,1);
v =  255 *  hsvMat(i,j,1);
s =  hsvMat(i,j,2);
if (((0<h) && (h<25)) || ((335<h) && (h<360)) && v>=40)
    isSkin =1;
else
    isSkin =0;
end




