Example #1
0
    def _map_binocular(self, p0, p1):

        if '3d'not in p0['method'] or '3d' not in p1['method']:
            return None

        #find the nearest intersection point of the two gaze lines
        # a line is defined by two point
        s0_center = self.eye0_to_World( np.array( p0['sphere']['center'] ) )
        s1_center = self.eye1_to_World( np.array( p1['sphere']['center'] ) )

        s0_normal = np.dot( self.rotation_matricies[0], np.array( p0['circle_3d']['normal'] ) )
        s1_normal = np.dot( self.rotation_matricies[1], np.array( p1['circle_3d']['normal'] ) )

        gaze_line0 = [ s0_center, s0_center + s0_normal ]
        gaze_line1 = [ s1_center, s1_center + s1_normal ]

        nearest_intersection_point , intersection_distance = math_helper.nearest_intersection( gaze_line0, gaze_line1 )

        if nearest_intersection_point is not None :
            self.last_gaze_distance = np.sqrt( nearest_intersection_point.dot( nearest_intersection_point ) )
            image_point, _  =  cv2.projectPoints( np.array([nearest_intersection_point]) ,  np.array([0.0,0.0,0.0]) ,  np.array([0.0,0.0,0.0]) , self.camera_matrix , self.dist_coefs )
            image_point = image_point.reshape(-1,2)
            image_point = normalize( image_point[0], self.world_frame_size , flip_y = True)


        if self.visualizer.window:
            gaze0_3d =  s0_normal * self.last_gaze_distance  + s0_center
            gaze1_3d =  s1_normal * self.last_gaze_distance  + s1_center
            self.gaze_pts_debug0.append(  gaze0_3d)
            self.gaze_pts_debug1.append(  gaze1_3d)
            if nearest_intersection_point is not None:
                self.intersection_points_debug.append( nearest_intersection_point )

            self.sphere0['center'] = s0_center #eye camera coordinates
            self.sphere0['radius'] = p0['sphere']['radius']
            self.sphere1['center'] = s1_center #eye camera coordinates
            self.sphere1['radius'] = p1['sphere']['radius']

        if nearest_intersection_point is None :
            return None


        confidence = (p0['confidence'] + p1['confidence'])/2.
        ts = (p0['timestamp'] + p1['timestamp'])/2.
        g = {   'norm_pos':image_point,
                'eye_centers_3d':{0:s0_center.tolist(),1:s1_center.tolist()},
                'gaze_normals_3d':{0:s0_normal.tolist(),1:s1_normal.tolist()},
                'gaze_point_3d':nearest_intersection_point.tolist(),
                'confidence':confidence,
                'timestamp':ts,
                'base':[p0,p1]}
        return g
Example #2
0
    def _map_binocular(self, p0, p1):

        if '3d' not in p0['method'] or '3d' not in p1['method']:
            return None

        #find the nearest intersection point of the two gaze lines
        #eye ball centers in world coords
        s0_center = self.eye0_to_World( np.array( p0['sphere']['center'] ) )
        s1_center = self.eye1_to_World( np.array( p1['sphere']['center'] ) )
        #eye line of sight in world coords
        s0_normal = np.dot( self.rotation_matricies[0], np.array( p0['circle_3d']['normal'] ) )
        s1_normal = np.dot( self.rotation_matricies[1], np.array( p1['circle_3d']['normal'] ) )

        # See Lech Swirski: "Gaze estimation on glasses-based stereoscopic displays"
        # Chapter: 7.4.2 Cyclopean gaze estimate

        #the cyclop is the avg of both lines of sight
        cyclop_normal = (s0_normal+s1_normal)/2.
        cyclop_center = (s0_center+s1_center)/2.

        # We use it to define a viewing plane.
        gaze_plane = np.cross(cyclop_normal , s1_center-s0_center)
        gaze_plane = gaze_plane/np.linalg.norm(gaze_plane)

        #project lines of sight onto the gaze plane
        s0_norm_on_plane =  s0_normal - np.dot(gaze_plane,s0_normal)*gaze_plane
        s1_norm_on_plane =  s1_normal - np.dot(gaze_plane,s1_normal)*gaze_plane

        #create gaze lines on this plane
        gaze_line0 = [ s0_center, s0_center + s0_norm_on_plane ]
        gaze_line1 = [ s1_center, s1_center + s1_norm_on_plane ]

        #find the intersection of left and right line of sight.
        nearest_intersection_point , intersection_distance = math_helper.nearest_intersection( gaze_line0, gaze_line1 )
        if nearest_intersection_point is not None :
            cyclop_gaze =  nearest_intersection_point-cyclop_center
            self.last_gaze_distance = np.sqrt( cyclop_gaze.dot( cyclop_gaze ) )
            image_point, _  =  cv2.projectPoints( np.array([nearest_intersection_point]) ,  np.array([0.0,0.0,0.0]) ,  np.array([0.0,0.0,0.0]) , self.camera_matrix , self.dist_coefs )
            image_point = image_point.reshape(-1,2)
            image_point = normalize( image_point[0], self.world_frame_size , flip_y = True)


        if self.visualizer.window:
            gaze0_3d =  s0_normal * self.last_gaze_distance  + s0_center
            gaze1_3d =  s1_normal * self.last_gaze_distance  + s1_center
            self.gaze_pts_debug0.append(  gaze0_3d)
            self.gaze_pts_debug1.append(  gaze1_3d)
            if nearest_intersection_point is not None:
                self.intersection_points_debug.append( nearest_intersection_point )

            self.sphere0['center'] = s0_center #eye camera coordinates
            self.sphere0['radius'] = p0['sphere']['radius']
            self.sphere1['center'] = s1_center #eye camera coordinates
            self.sphere1['radius'] = p1['sphere']['radius']

        if nearest_intersection_point is None :
            return None


        confidence = min(p0['confidence'],p1['confidence'])
        ts = (p0['timestamp'] + p1['timestamp'])/2.
        g = {   'norm_pos':image_point,
                'eye_centers_3d':{0:s0_center.tolist(),1:s1_center.tolist()},
                'gaze_normals_3d':{0:s0_normal.tolist(),1:s1_normal.tolist()},
                'gaze_point_3d':nearest_intersection_point.tolist(),
                'confidence':confidence,
                'timestamp':ts,
                'base_data':[p0,p1]}
        return g
Example #3
0
    def _map_binocular(self, p0, p1):

        if '3d' not in p0['method'] or '3d' not in p1['method']:
            return None

        #find the nearest intersection point of the two gaze lines
        #eye ball centers in world coords
        s0_center = self.eye0_to_World( np.array( p0['sphere']['center'] ) )
        s1_center = self.eye1_to_World( np.array( p1['sphere']['center'] ) )
        #eye line of sight in world coords
        s0_normal = np.dot( self.rotation_matricies[0], np.array( p0['circle_3d']['normal'] ) )
        s1_normal = np.dot( self.rotation_matricies[1], np.array( p1['circle_3d']['normal'] ) )

        # See Lech Swirski: "Gaze estimation on glasses-based stereoscopic displays"
        # Chapter: 7.4.2 Cyclopean gaze estimate

        #the cyclop is the avg of both lines of sight
        cyclop_normal = (s0_normal+s1_normal)/2.
        cyclop_center = (s0_center+s1_center)/2.

        # We use it to define a viewing plane.
        gaze_plane = np.cross(cyclop_normal , s1_center-s0_center)
        gaze_plane = gaze_plane/np.linalg.norm(gaze_plane)

        #project lines of sight onto the gaze plane
        s0_norm_on_plane =  s0_normal - np.dot(gaze_plane,s0_normal)*gaze_plane
        s1_norm_on_plane =  s1_normal - np.dot(gaze_plane,s1_normal)*gaze_plane

        #create gaze lines on this plane
        gaze_line0 = [ s0_center, s0_center + s0_norm_on_plane ]
        gaze_line1 = [ s1_center, s1_center + s1_norm_on_plane ]

        #find the intersection of left and right line of sight.
        nearest_intersection_point , intersection_distance = math_helper.nearest_intersection( gaze_line0, gaze_line1 )
        if nearest_intersection_point is not None :
            cyclop_gaze =  nearest_intersection_point-cyclop_center
            self.last_gaze_distance = np.sqrt( cyclop_gaze.dot( cyclop_gaze ) )
            image_point, _  =  cv2.projectPoints( np.array([nearest_intersection_point]) ,  np.array([0.0,0.0,0.0]) ,  np.array([0.0,0.0,0.0]) , self.camera_matrix , self.dist_coefs )
            image_point = image_point.reshape(-1,2)
            image_point = normalize( image_point[0], self.world_frame_size , flip_y = True)


        if self.visualizer.window:
            gaze0_3d =  s0_normal * self.last_gaze_distance  + s0_center
            gaze1_3d =  s1_normal * self.last_gaze_distance  + s1_center
            self.gaze_pts_debug0.append(  gaze0_3d)
            self.gaze_pts_debug1.append(  gaze1_3d)
            if nearest_intersection_point is not None:
                self.intersection_points_debug.append( nearest_intersection_point )

            self.sphere0['center'] = s0_center #eye camera coordinates
            self.sphere0['radius'] = p0['sphere']['radius']
            self.sphere1['center'] = s1_center #eye camera coordinates
            self.sphere1['radius'] = p1['sphere']['radius']

        if nearest_intersection_point is None :
            return None


        confidence = min(p0['confidence'],p1['confidence'])
        ts = (p0['timestamp'] + p1['timestamp'])/2.
        g = {   'norm_pos':image_point,
                'eye_centers_3d':{0:s0_center.tolist(),1:s1_center.tolist()},
                'gaze_normals_3d':{0:s0_normal.tolist(),1:s1_normal.tolist()},
                'gaze_point_3d':nearest_intersection_point.tolist(),
                'confidence':confidence,
                'timestamp':ts,
                'base_data':[p0,p1]}
        return g
Example #4
0
    def _map_binocular(self, p0, p1):

        if "3d" not in p0["method"] or "3d" not in p1["method"]:
            return None

        # find the nearest intersection point of the two gaze lines
        # eye ball centers in world coords
        s0_center = self.eye0_to_World(np.array(p0["sphere"]["center"]))
        s1_center = self.eye1_to_World(np.array(p1["sphere"]["center"]))
        # eye line of sight in world coords
        s0_normal = np.dot(
            self.rotation_matricies[0], np.array(p0["circle_3d"]["normal"])
        )
        s1_normal = np.dot(
            self.rotation_matricies[1], np.array(p1["circle_3d"]["normal"])
        )

        # See Lech Swirski: "Gaze estimation on glasses-based stereoscopic displays"
        # Chapter: 7.4.2 Cyclopean gaze estimate

        # the cyclop is the avg of both lines of sight
        cyclop_normal = (s0_normal + s1_normal) / 2.0
        cyclop_center = (s0_center + s1_center) / 2.0

        # We use it to define a viewing plane.
        gaze_plane = np.cross(cyclop_normal, s1_center - s0_center)
        gaze_plane = gaze_plane / np.linalg.norm(gaze_plane)

        # project lines of sight onto the gaze plane
        s0_norm_on_plane = s0_normal - np.dot(gaze_plane, s0_normal) * gaze_plane
        s1_norm_on_plane = s1_normal - np.dot(gaze_plane, s1_normal) * gaze_plane

        # create gaze lines on this plane
        gaze_line0 = [s0_center, s0_center + s0_norm_on_plane]
        gaze_line1 = [s1_center, s1_center + s1_norm_on_plane]

        # find the intersection of left and right line of sight.
        (
            nearest_intersection_point,
            intersection_distance,
        ) = math_helper.nearest_intersection(gaze_line0, gaze_line1)
        if nearest_intersection_point is not None and self.backproject:
            cyclop_gaze = nearest_intersection_point - cyclop_center
            self.last_gaze_distance = np.sqrt(cyclop_gaze.dot(cyclop_gaze))
            image_point = self.g_pool.capture.intrinsics.projectPoints(
                np.array([nearest_intersection_point])
            )
            image_point = image_point.reshape(-1, 2)
            image_point = normalize(
                image_point[0], self.g_pool.capture.intrinsics.resolution, flip_y=True
            )
            image_point = _clamp_norm_point(image_point)

        if hasattr(self, "visualizer") and self.visualizer.window:
            gaze0_3d = s0_normal * self.last_gaze_distance + s0_center
            gaze1_3d = s1_normal * self.last_gaze_distance + s1_center
            self.gaze_pts_debug0.append(gaze0_3d)
            self.gaze_pts_debug1.append(gaze1_3d)
            if nearest_intersection_point is not None:
                self.intersection_points_debug.append(nearest_intersection_point)

            self.sphere0["center"] = s0_center  # eye camera coordinates
            self.sphere0["radius"] = p0["sphere"]["radius"]
            self.sphere1["center"] = s1_center  # eye camera coordinates
            self.sphere1["radius"] = p1["sphere"]["radius"]

        if nearest_intersection_point is None:
            return None

        confidence = min(p0["confidence"], p1["confidence"])
        ts = (p0["timestamp"] + p1["timestamp"]) / 2.0
        g = {
            "topic": "gaze.3d.01.",
            "eye_centers_3d": {0: s0_center.tolist(), 1: s1_center.tolist()},
            "gaze_normals_3d": {0: s0_normal.tolist(), 1: s1_normal.tolist()},
            "gaze_point_3d": nearest_intersection_point.tolist(),
            "confidence": confidence,
            "timestamp": ts,
            "base_data": [p0, p1],
        }

        if self.backproject:
            g["norm_pos"] = image_point

        return g
Example #5
0
    def _predict_single(self, x):
        assert x.ndim == 1, x
        assert x.shape[0] == _BINOCULAR_FEATURE_COUNT, x
        # find the nearest intersection point of the two gaze lines
        # eye ball centers in world coords
        s1_center = self._eye1_to_World(x[_MONOCULAR_SPHERE_CENTER])
        s0_center = self._eye0_to_World(x[_BINOCULAR_SPHERE_CENTER])
        # eye line of sight in world coords
        s1_normal = np.dot(self.rotation_matricies[1], x[_MONOCULAR_PUPIL_NORMAL])
        s0_normal = np.dot(self.rotation_matricies[0], x[_BINOCULAR_PUPIL_NORMAL])

        # See Lech Swirski: "Gaze estimation on glasses-based stereoscopic displays"
        # Chapter: 7.4.2 Cyclopean gaze estimate

        # the cyclop is the avg of both lines of sight
        cyclop_normal = (s0_normal + s1_normal) / 2.0
        cyclop_center = (s0_center + s1_center) / 2.0

        # We use it to define a viewing plane.
        gaze_plane = np.cross(cyclop_normal, s1_center - s0_center)
        gaze_plane = gaze_plane / np.linalg.norm(gaze_plane)

        # project lines of sight onto the gaze plane
        s0_norm_on_plane = s0_normal - np.dot(gaze_plane, s0_normal) * gaze_plane
        s1_norm_on_plane = s1_normal - np.dot(gaze_plane, s1_normal) * gaze_plane

        # create gaze lines on this plane
        gaze_line0 = [s0_center, s0_center + s0_norm_on_plane]
        gaze_line1 = [s1_center, s1_center + s1_norm_on_plane]

        # find the intersection of left and right line of sight.
        (
            nearest_intersection_point,
            intersection_distance,
        ) = math_helper.nearest_intersection(gaze_line0, gaze_line1)

        if nearest_intersection_point is None:
            return None

        # Check if gaze is in front of camera. If it is not, flip direction.
        if nearest_intersection_point[-1] < 0:
            nearest_intersection_point *= -1.0

        g = {
            "eye_centers_3d": {"0": s0_center.tolist(), "1": s1_center.tolist()},
            "gaze_normals_3d": {"0": s0_normal.tolist(), "1": s1_normal.tolist()},
            "gaze_point_3d": nearest_intersection_point.tolist(),
        }

        if self.intrinsics is not None:
            cyclop_gaze = nearest_intersection_point - cyclop_center
            self.last_gaze_distance = np.sqrt(cyclop_gaze.dot(cyclop_gaze))
            image_point = self.intrinsics.projectPoints(
                np.array([nearest_intersection_point])
            )
            image_point = image_point.reshape(-1, 2)
            image_point = normalize(
                image_point[0], self.intrinsics.resolution, flip_y=True
            )
            image_point = _clamp_norm_point(image_point)
            g["norm_pos"] = image_point

        return g
Example #6
0
    def map_binocular_intersect(self, pupil_pts_0, pupil_pts_1 ,frame ):
        # maps gaze with binocular mapping
        # requires each list to contain at least one item!
        # returns 1 gaze point at minimum
        gaze_pts = []
        p0 = pupil_pts_0.pop(0)
        p1 = pupil_pts_1.pop(0)
        while True:

            #find the nearest intersection point of the two gaze lines
            # a line is defined by two point
            s0_center = self.eye0_to_World( np.array( p0['sphere']['center'] ) )
            s1_center = self.eye1_to_World( np.array( p1['sphere']['center'] ) )

            s0_normal = np.dot( self.rotation_matrix0, np.array( p0['circle_3d']['normal'] ) )
            s1_normal = np.dot( self.rotation_matrix1, np.array( p1['circle_3d']['normal'] ) )

            gaze_line0 = [ s0_center, s0_center + s0_normal ]
            gaze_line1 = [ s1_center, s1_center + s1_normal ]

            nearest_intersection_point , intersection_distance = math_helper.nearest_intersection( gaze_line0, gaze_line1 )

            if nearest_intersection_point is not None :

                self.last_gaze_distance = np.sqrt( nearest_intersection_point.dot( nearest_intersection_point ) )

                image_point, _  =  cv2.projectPoints( np.array([nearest_intersection_point]) ,  np.array([0.0,0.0,0.0]) ,  np.array([0.0,0.0,0.0]) , self.camera_matrix , self.dist_coefs )
                image_point = image_point.reshape(-1,2)
                image_point = normalize( image_point[0], (frame.width, frame.height) , flip_y = True)

                confidence = (p0['confidence'] + p1['confidence'])/2.
                ts = (p0['timestamp'] + p1['timestamp'])/2.
                gaze_pts.append({   'norm_pos':image_point,
                                    'eye_centers_3d':{0:s0_center.tolist(),1:s1_center.tolist()},
                                    'gaze_normals_3d':{0:s0_normal.tolist(),1:s1_normal.tolist()},
                                    'gaze_point_3d':nearest_intersection_point.tolist(),
                                    'confidence':confidence,
                                    'timestamp':ts,
                                    'base':[p0,p1]})
            else:
                logger.debug('No gaze line intersection point found')


            if self.visualizer.window:

                gaze0_3d =  s0_normal * self.last_gaze_distance  + s0_center
                gaze1_3d =  s1_normal * self.last_gaze_distance  + s1_center
                self.gaze_pts_debug0.append(  gaze0_3d)
                self.gaze_pts_debug1.append(  gaze1_3d)
                if nearest_intersection_point is not None:
                    self.intersection_points_debug.append( nearest_intersection_point )

                self.sphere0['center'] = s0_center #eye camera coordinates
                self.sphere0['radius'] = p0['sphere']['radius']

                self.sphere1['center'] = s1_center #eye camera coordinates
                self.sphere1['radius'] = p1['sphere']['radius']



            # keep sample with higher timestamp and increase the one with lower timestamp
            if p0['timestamp'] <= p1['timestamp'] and pupil_pts_0:
                p0 = pupil_pts_0.pop(0)
                continue
            elif p1['timestamp'] <= p0['timestamp'] and pupil_pts_1:
                p1 = pupil_pts_1.pop(0)
                continue
            elif pupil_pts_0 and not pupil_pts_1:
                p0 = pupil_pts_0.pop(0)
            elif pupil_pts_1 and not pupil_pts_0:
                p1 = pupil_pts_1.pop(0)
            else:
                break

        return gaze_pts
Example #7
0
    def _map_binocular(self, p0, p1):

        if '3d' not in p0['method'] or '3d' not in p1['method']:
            return None

        #find the nearest intersection point of the two gaze lines
        # a line is defined by two point
        s0_center = self.eye0_to_World(np.array(p0['sphere']['center']))
        s1_center = self.eye1_to_World(np.array(p1['sphere']['center']))

        s0_normal = np.dot(self.rotation_matricies[0],
                           np.array(p0['circle_3d']['normal']))
        s1_normal = np.dot(self.rotation_matricies[1],
                           np.array(p1['circle_3d']['normal']))

        gaze_line0 = [s0_center, s0_center + s0_normal]
        gaze_line1 = [s1_center, s1_center + s1_normal]

        nearest_intersection_point, intersection_distance = math_helper.nearest_intersection(
            gaze_line0, gaze_line1)

        if nearest_intersection_point is not None:
            self.last_gaze_distance = np.sqrt(
                nearest_intersection_point.dot(nearest_intersection_point))
            image_point, _ = cv2.projectPoints(
                np.array([nearest_intersection_point]),
                np.array([0.0, 0.0, 0.0]), np.array([0.0, 0.0, 0.0]),
                self.camera_matrix, self.dist_coefs)
            image_point = image_point.reshape(-1, 2)
            image_point = normalize(image_point[0],
                                    self.world_frame_size,
                                    flip_y=True)

        if self.visualizer.window:
            gaze0_3d = s0_normal * self.last_gaze_distance + s0_center
            gaze1_3d = s1_normal * self.last_gaze_distance + s1_center
            self.gaze_pts_debug0.append(gaze0_3d)
            self.gaze_pts_debug1.append(gaze1_3d)
            if nearest_intersection_point is not None:
                self.intersection_points_debug.append(
                    nearest_intersection_point)

            self.sphere0['center'] = s0_center  #eye camera coordinates
            self.sphere0['radius'] = p0['sphere']['radius']
            self.sphere1['center'] = s1_center  #eye camera coordinates
            self.sphere1['radius'] = p1['sphere']['radius']

        if nearest_intersection_point is None:
            return None

        confidence = (p0['confidence'] + p1['confidence']) / 2.
        ts = (p0['timestamp'] + p1['timestamp']) / 2.
        g = {
            'norm_pos': image_point,
            'eye_centers_3d': {
                0: s0_center.tolist(),
                1: s1_center.tolist()
            },
            'gaze_normals_3d': {
                0: s0_normal.tolist(),
                1: s1_normal.tolist()
            },
            'gaze_point_3d': nearest_intersection_point.tolist(),
            'confidence': confidence,
            'timestamp': ts,
            'base': [p0, p1]
        }
        return g