aboutsummaryrefslogtreecommitdiff
path: root/src/argaze/AreaOfInterest/AOI2DScene.py
blob: f648803753ac5a00a4e6f038eabc17bbf8b75a40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python

from typing import Tuple

from argaze import DataStructures
from argaze.AreaOfInterest import AOIFeatures
from argaze import GazeFeatures

import cv2 as cv
import numpy

class AOI2DScene(AOIFeatures.AOIScene):
	"""Define AOI 2D scene."""

	def __init__(self, aois_2d = None):

		super().__init__(2, aois_2d)

	def draw(self, frame, exclude=[], color=(0, 255, 255)):
		"""Draw AOI polygons on frame."""

		for name, aoi in self.items():

			if name in exclude:
				continue

			aoi.draw(frame, color)

	def raycast(self, gaze_position: GazeFeatures.GazePosition) -> Tuple[str, "AOIFeatures.AreaOfInterest", bool]:
		"""Iterate over aoi to know which aoi is looked considering only gaze position value.
		* **Returns:** 
			- aoi name
			- aoi object
			- looked status
		"""

		for name, aoi in self.items():

			looked = aoi.contains_point(gaze_position.value)

			yield name, aoi, looked

	def draw_raycast(self, frame, gaze_position: GazeFeatures.GazePosition, exclude=[], base_color=(0, 0, 255), looked_color=(0, 255, 0)):
		"""Draw AOIs with their looked status."""

		for name, aoi, looked in self.raycast(gaze_position):

			if name in exclude:
				continue
			
			color = looked_color if looked else base_color

			if looked:

				top_left_corner_pixel = numpy.rint(aoi.clockwise()[0]).astype(int)
				cv.putText(frame, name, top_left_corner_pixel, cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv.LINE_AA)

			# Draw form
			aoi.draw(frame, color)

	def circlecast(self, gaze_position: GazeFeatures.GazePosition) -> Tuple[str, "AOIFeatures.AreaOfInterest", numpy.array, float, float]:
		"""Iterate over areas to know which aoi is looked considering gaze position value and its accuracy.
		* **Returns:**
			- aoi name
			- aoi object
			- looked region points
			- ratio of looked region area relatively to aoi area
			- ratio of looked region area relatively to gaze position circle accuracy
		"""

		for name, aoi in self.items():

			looked_region, aoi_ratio, gaze_ratio = aoi.circle_intersection(gaze_position.value, gaze_position.accuracy)

			yield name, aoi, looked_region, aoi_ratio, gaze_ratio

	def draw_circlecast(self, frame, gaze_position: GazeFeatures.GazePosition, exclude=[], base_color=(0, 0, 255), looked_color=(0, 255, 0)):
		"""Draw AOIs with their looked status and looked region."""

		for name, aoi, looked_region, aoi_ratio, gaze_ratio in self.circlecast(gaze_position):

			if name in exclude:
				continue
			
			# Draw looked region
			if aoi_ratio > 0:
				looked_region.draw(frame, base_color, 4)

			# TODO : Externalise this criteria
			looked = aoi_ratio > 0.25 or gaze_ratio > 0.5

			color = looked_color if looked else base_color

			if looked:

				top_left_corner_pixel = numpy.rint(aoi.clockwise()[0]).astype(int)
				cv.putText(frame, name, top_left_corner_pixel, cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 1, cv.LINE_AA)

				# Draw looked region
				looked_region.draw(frame, looked_color, 4)

			# Draw form
			aoi.draw(frame, color)