antoinelame / GazeTracking

👀 Eye Tracking library easily implementable to your projects
MIT License
1.85k stars 505 forks source link

Contours sorting and mouse movement #6

Open codeYazar opened 5 years ago

codeYazar commented 5 years ago

First of all, your work is working very well. And I'm new on this. I'm trying to understand codes.

what does it mean , especially [-2] in moments = cv2.moments(contours[-2])

I also want to ask you how to match the coordinates on the webcam, on the PC screen. Thanks

antoinelame commented 5 years ago

Hi @codeYazar

what does it mean , especially [-2] in moments = cv2.moments(contours[-2])

The algorithm detects faces, eyes and then processes the frame to get that:

Iris

The black block is the iris. We use it to calculate the centroid (I consider that is the pupil position). First, it's necessary to detect this contour:

_, contours, _ = cv2.findContours(self.iris_frame, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

It returns a list of several contours:

Of course, we want to get only the iris contour. So to do that, the algorithm sorts the contours list by size:

contours = sorted(contours, key=cv2.contourArea)

The contours are now sorted from the smallest to the largest. So the last one is the contour of the entire frame and the second to last is the contour of iris.

So we can access iris contour like so: contours[-2]

I also want to ask you how to match the coordinates on the webcam, on the PC screen.

I don't understand well your question. Do you want to use it to move your mouse?

codeYazar commented 5 years ago

Yeah. I want to move the mouse with my eyes. But the head will not be fixed. He should let the head move.

antoinelame commented 5 years ago

To have the relative coordinates of the pupils, without the position of the head having any impact, you can change:

def pupil_left_coords(self):
        """Returns the coordinates of the left pupil"""
        if self.pupils_located:
            x = self.eye_left.origin[0] + self.eye_left.pupil.x
            y = self.eye_left.origin[1] + self.eye_left.pupil.y
            return (x, y)

to

def pupil_left_coords(self):
        """Returns the coordinates of the left pupil"""
        if self.pupils_located:
            x = self.eye_left.pupil.x
            y = self.eye_left.pupil.y
            return (x, y)
wittynerd commented 5 years ago

I tried using horizontal_ratio and vertical_ratio to move the mouse cursor (using pyautogui library) as in,

`` X,Y = gaze.horizontal_ratio(),gaze.vertical_ratio() w , h = pyautogui.size() #Returns the size of the screen

try:
    x = int(w*X)
    y = int(h*Y)

except TypeError:
    x , y = None,None

print(x,y)
pyautogui.moveTo(x,y)    #Moves the mouse cursor to (x,y)``

The performance isn't good. Is there any better way or a calibration technique I'm missing?

antoinelame commented 5 years ago

Hi @wittynerd, gaze.horizontal_ratio() and gaze.vertical_ratio() return ratios to know the gaze direction. It doesn't return any coordinates, and you shouldn't try to get coordinates from it. Instead, you should use gaze.pupil_left_coords() and gaze.pupil_right_coords(). Good luck!