Esempio n. 1
0
    def recent_events(self, events):
        frame = events.get('frame')
        if not frame:
            return
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        for pt in events.get('gaze_positions', []):
            self.pupil_display_list.append(
                (pt['norm_pos'], pt['confidence'] * 0.8))
        self.pupil_display_list[:-3] = []

        # pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[]) if pt['confidence']>=self.min_confidence]
        for pt, a in self.pupil_display_list:
            #print('vis_circle', pt, a)
            transparent_circle(frame.img,
                               pt,
                               radius=self.radius,
                               color=(self.b, self.g, self.r, self.a),
                               thickness=thickness)
            draw_points_norm([pt],
                             size=self.radius,
                             color=RGBA(self.r, self.g, self.b, self.a))
Esempio n. 2
0
    def recent_events(self, events):
        if self.bg_task:
            recent = [d for d in self.bg_task.fetch()]
            if recent:
                progress, data = zip(*recent)
                self.fixations.extend(chain(*data))
                self.status = progress[-1]
                if self.fixations:
                    current = self.fixations[-1]['timestamp']
                    progress = (current - self.g_pool.timestamps[0]) /\
                               (self.g_pool.timestamps[1] - self.g_pool.timestamps[0])
                    self.menu_icon.indicator_stop = progress
            if self.bg_task.completed:
                self.correlate_and_publish()
                self.bg_task = None
                self.menu_icon.indicator_stop = 0.

        frame = events.get('frame')
        if not frame:
            return

        self.last_frame_ts = frame.timestamp
        events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
        if self.show_fixations:
            for f in self.g_pool.fixations_by_frame[frame.index]:
                x = int(f['norm_pos'][0] * frame.width)
                y = int((1. - f['norm_pos'][1]) * frame.height)
                transparent_circle(frame.img, (x, y), radius=25., color=(0., 1., 1., 1.), thickness=-1)
                cv2.putText(frame.img, '{}'.format(f['id']), (x + 30, y),
                            cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))

        if self.prev_index != frame.index:
            info = ''
            for f in self.g_pool.fixations_by_frame[frame.index]:
                info += 'Current fixation, {} of {}\n'.format(f['id'], len(self.g_pool.fixations))
                info += '    Confidence: {:.2f}\n'.format(f['confidence'])
                info += '    Duration: {:.2f} milliseconds\n'.format(f['duration'])
                info += '    Dispersion: {:.3f} degrees\n'.format(f['dispersion'])
                info += '    Frame range: {}-{}\n'.format(f['start_frame_index'] + 1, f['end_frame_index'] + 1)
                info += '    2d gaze pos: x={:.3f}, y={:.3f}\n'.format(*f['norm_pos'])
                if 'gaze_point_3d' in f:
                    info += '    3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n'.format(*f['gaze_point_3d'])
                else:
                    info += '    3d gaze pos: N/A\n'
                if f['id'] > 1:
                    prev_f = self.g_pool.fixations[f['id'] - 2]
                    time_lapsed = f['timestamp'] - prev_f['timestamp'] + prev_f['duration'] / 1000
                    info += '    Time since prev. fixation: {:.2f} seconds\n'.format(time_lapsed)
                else:
                    info += '    Time since prev. fixation: N/A\n'

                if f['id'] < len(self.g_pool.fixations):
                    next_f = self.g_pool.fixations[f['id']]
                    time_lapsed = next_f['timestamp'] - f['timestamp'] + f['duration'] / 1000
                    info += '    Time to next fixation: {:.2f} seconds\n'.format(time_lapsed)
                else:
                    info += '    Time to next fixation: N/A\n'

            self.current_fixation_details.text = info
            self.prev_index = frame.index
Esempio n. 3
0
    def update(self, frame, events):
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        fixation_pts = [
            denormalize(pt['norm_pos'],
                        frame.img.shape[:-1][::-1],
                        flip_y=True) for pt in events.get('fixations', [])
        ]
        not_fixation_pts = [
            denormalize(pt['norm_pos'],
                        frame.img.shape[:-1][::-1],
                        flip_y=True)
            for pt in events.get('gaze_positions', [])
        ]

        if fixation_pts:
            for pt in fixation_pts:
                transparent_circle(frame.img,
                                   pt,
                                   radius=self.radius,
                                   color=(self.b, self.g, self.r, self.a),
                                   thickness=thickness)
        else:
            for pt in not_fixation_pts:
                transparent_circle(frame.img,
                                   pt,
                                   radius=7.0,
                                   color=(0.2, 0.0, 0.7, 0.5),
                                   thickness=thickness)
Esempio n. 4
0
 def update(self,frame,events):
     events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             x = int(f['norm_pos'][0]*self.img_size[0])
             y = int((1-f['norm_pos'][1])*self.img_size[1])
             transparent_circle(frame.img, (x,y), radius=f['pix_dispersion'], color=(.5, .2, .6, .7), thickness=-1)
             cv2.putText(frame.img,'%i'%f['id'],(x+20,y), cv2.FONT_HERSHEY_DUPLEX,0.8,(255,150,100))
Esempio n. 5
0
 def update(self,frame,events):
     events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             x = int(f['norm_pos'][0]*self.img_size[0])
             y = int((1-f['norm_pos'][1])*self.img_size[1])
             transparent_circle(frame.img, (x,y), radius=f['pix_dispersion'], color=(.5, .2, .6, .7), thickness=-1)
             cv2.putText(frame.img,'%i'%f['id'],(x+20,y), cv2.FONT_HERSHEY_DUPLEX,0.8,(255,150,100))
Esempio n. 6
0
    def draw_circle(self, segment: model.Classified_Segment):
        segment_point = segment.mean_2d_point_within_world(self.canvas_size)
        segment_color = color_from_segment(segment).to_bgra().channels

        pm.transparent_circle(
            self._image, segment_point, radius=25.0, color=segment_color, thickness=3
        )

        self.draw_id(segment=segment, ref_point=segment_point)
Esempio n. 7
0
    def update(self,frame,events):
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events['pupil_positions'] if pt['norm_gaze'] is not None]
        for pt in pts:
            transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
Esempio n. 8
0
    def draw_circle(self, segment: model.Classified_Segment):
        segment_point = segment.mean_2d_point_within_world(self.canvas_size)
        segment_color = color_from_segment(segment).to_bgra().channels

        pm.transparent_circle(
            self._image, segment_point, radius=25.0, color=segment_color, thickness=3
        )

        self.draw_id(segment=segment, ref_point=segment_point)
Esempio n. 9
0
    def update(self,frame,events):
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[])]
        for pt in pts:
            transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
Esempio n. 10
0
    def update(self,frame,events):
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[]) if pt['confidence']>=self.g_pool.min_data_confidence]
        for pt in pts:
            transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
Esempio n. 11
0
 def update(self, frame, events):
     events["fixations"] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             x = int(f["norm_pos"][0] * self.img_size[0])
             y = int((1 - f["norm_pos"][1]) * self.img_size[1])
             transparent_circle(
                 frame.img, (x, y), radius=f["pix_dispersion"], color=(0.5, 0.2, 0.6, 0.7), thickness=-1
             )
             cv2.putText(frame.img, "%i" % f["id"], (x + 20, y), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
Esempio n. 12
0
    def update(self,frame,recent_pupil_positions,events):
        color = map(lambda x:int(x*255),self.color)
        color = color[:3][::-1]+color[-1:]
        if self.fill.value:
            thickness= -1
        else:
            thickness = self.thickness.value

        radius = self.radius.value
        pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in recent_pupil_positions if pt['norm_gaze'] is not None]
        for pt in pts:
            transparent_circle(frame.img, pt, radius=radius, color=color, thickness=thickness)
Esempio n. 13
0
 def update(self, frame, events):
     self.last_frame_ts = frame.timestamp
     from player_methods import transparent_circle
     events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             x = int(f['norm_pos'][0] * self.img_size[0])
             y = int((1 - f['norm_pos'][1]) * self.img_size[1])
             transparent_circle(frame.img, (x, y),
                                radius=f['pix_dispersion'] / 2,
                                color=(.5, .2, .6, .7),
                                thickness=-1)
             cv2.putText(frame.img, '{:d}'.format(f['id']), (x + 20, y),
                         cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
Esempio n. 14
0
 def update(self,frame,events):
     self.last_frame_ts = frame.timestamp
     from player_methods import transparent_circle
     events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             eye_id = f['eye_id']
             x = int(f['norm_pos'][0]*self.img_size[0])
             y = int((1-f['norm_pos'][1])*self.img_size[1])
             transparent_circle(frame.img, (x,y), radius=f['pix_dispersion']/2, color=(.5, .2, .6, .7), thickness=-1)
             cv2.putText(
                 frame.img,
                 '%i - eye %i'%(f['id'],eye_id),
                 (x+20,y-5+30*eye_id),
                 cv2.FONT_HERSHEY_DUPLEX,
                 0.8,(255,150,100))
Esempio n. 15
0
    def update(self,frame,events):
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        fixation_pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('fixations',[])]
        not_fixation_pts = [denormalize(pt['norm_pos'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events.get('gaze_positions',[])]


        if fixation_pts:
            for pt in fixation_pts:
                transparent_circle(frame.img, pt, radius=self.radius, color=(self.b, self.g, self.r, self.a), thickness=thickness)
        else:
            for pt in not_fixation_pts:
                transparent_circle(frame.img, pt, radius=7.0, color=(0.2, 0.0, 0.7, 0.5), thickness=thickness)
Esempio n. 16
0
 def recent_events(self, events):
     frame = events.get('frame')
     if not frame:
         return
     self.last_frame_ts = frame.timestamp
     from player_methods import transparent_circle
     events['fixations'] = self.g_pool.fixations_by_frame[frame.index]
     if self.show_fixations:
         for f in self.g_pool.fixations_by_frame[frame.index]:
             eye_id = f['eye_id']
             x = int(f['norm_pos'][0] * self.img_size[0])
             y = int((1 - f['norm_pos'][1]) * self.img_size[1])
             transparent_circle(frame.img, (x, y),
                                radius=f['pix_dispersion'] / 2,
                                color=(.5, .2, .6, .7),
                                thickness=-1)
             cv2.putText(frame.img,
                         '{:d} - eye {:d}'.format(f['id'], eye_id),
                         (x + 20, y - 5 + 30 * eye_id),
                         cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))
Esempio n. 17
0
    def recent_events(self, events):
        frame = events.get('frame')
        if not frame:
            return
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        pts = [
            denormalize(pt['norm_pos'],
                        frame.img.shape[:-1][::-1],
                        flip_y=True)
            for pt in events.get('gaze_positions', [])
            if pt['confidence'] >= self.g_pool.min_data_confidence
        ]
        for pt in pts:
            transparent_circle(frame.img,
                               pt,
                               radius=self.radius,
                               color=(self.b, self.g, self.r, self.a),
                               thickness=thickness)
Esempio n. 18
0
    def _draw_scan_path_debug(self, frame, events):
        from methods import denormalize
        from player_methods import transparent_circle

        gaze_data = self.scan_path_controller.scan_path_gaze_for_frame(frame)

        if gaze_data is None:
            return

        points_to_draw_count = len(gaze_data)
        image_size = frame.img.shape[:-1][::-1]

        for idx, datum in enumerate(gaze_data):
            point = (datum["norm_x"], datum["norm_y"])
            point = denormalize(point, image_size, flip_y=True)

            gray = float(idx) / points_to_draw_count
            transparent_circle(frame.img,
                               point,
                               radius=20,
                               color=(gray, gray, gray, 0.9),
                               thickness=2)
Esempio n. 19
0
    def recent_events(self, events):
        frame = events.get("frame")
        if not frame:
            return
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        fixation_pts = [
            denormalize(pt["norm_pos"],
                        frame.img.shape[:-1][::-1],
                        flip_y=True) for pt in events.get("fixations", [])
        ]
        not_fixation_pts = [
            denormalize(pt["norm_pos"],
                        frame.img.shape[:-1][::-1],
                        flip_y=True) for pt in events.get("gaze", [])
        ]

        if fixation_pts:
            for pt in fixation_pts:
                transparent_circle(
                    frame.img,
                    pt,
                    radius=self.radius,
                    color=(self.b, self.g, self.r, self.a),
                    thickness=thickness,
                )
        else:
            for pt in not_fixation_pts:
                transparent_circle(
                    frame.img,
                    pt,
                    radius=7.0,
                    color=(0.2, 0.0, 0.7, 0.5),
                    thickness=thickness,
                )
Esempio n. 20
0
    def recent_events(self, events):
        frame = events.get("frame")
        if not frame:
            return
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        frame_width_height = frame.img.shape[:-1][::-1]
        pts = [
            denormalize(pt["norm_pos"], frame_width_height, flip_y=True)
            for pt in events.get("gaze", [])
            if pt["confidence"] >= self.g_pool.min_data_confidence
        ]

        for pt in pts:
            transparent_circle(
                frame.img,
                pt,
                radius=self.radius,
                color=(self.b, self.g, self.r, self.a),
                thickness=thickness,
            )
Esempio n. 21
0
    def recent_events(self, events):
        frame = events.get("frame")
        if not frame:
            return
        if self.fill:
            thickness = -1
        else:
            thickness = self.thickness

        fixation_pts = [
            denormalize(pt["norm_pos"], frame.img.shape[:-1][::-1], flip_y=True)
            for pt in events.get("fixations", [])
        ]
        not_fixation_pts = [
            denormalize(pt["norm_pos"], frame.img.shape[:-1][::-1], flip_y=True)
            for pt in events.get("gaze", [])
        ]

        if fixation_pts:
            for pt in fixation_pts:
                transparent_circle(
                    frame.img,
                    pt,
                    radius=self.radius,
                    color=(self.b, self.g, self.r, self.a),
                    thickness=thickness,
                )
        else:
            for pt in not_fixation_pts:
                transparent_circle(
                    frame.img,
                    pt,
                    radius=7.0,
                    color=(0.2, 0.0, 0.7, 0.5),
                    thickness=thickness,
                )
Esempio n. 22
0
    def recent_events(self, events):
        if self.bg_task:
            for progress, fixation_result in self.bg_task.fetch():
                self.status = progress
                if fixation_result:
                    serialized, start_ts, stop_ts = fixation_result
                    self.fixation_data.append(
                        fm.Serialized_Dict(msgpack_bytes=serialized)
                    )
                    self.fixation_start_ts.append(start_ts)
                    self.fixation_stop_ts.append(stop_ts)

                if self.fixation_data:
                    current_ts = self.fixation_stop_ts[-1]
                    progress = (current_ts - self.g_pool.timestamps[0]) / (
                        self.g_pool.timestamps[-1] - self.g_pool.timestamps[0]
                    )
                    self.menu_icon.indicator_stop = progress
            if self.bg_task.completed:
                self.status = "{} fixations detected".format(len(self.fixation_data))
                self.correlate_and_publish()
                self.bg_task = None
                self.menu_icon.indicator_stop = 0.0

        frame = events.get("frame")
        if not frame:
            return

        self.last_frame_idx = frame.index
        frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index)
        fixations = self.g_pool.fixations.by_ts_window(frame_window)
        events["fixations"] = fixations
        if self.show_fixations:
            for f in fixations:
                x = int(f["norm_pos"][0] * frame.width)
                y = int((1.0 - f["norm_pos"][1]) * frame.height)
                pm.transparent_circle(
                    frame.img,
                    (x, y),
                    radius=25.0,
                    color=(0.0, 1.0, 1.0, 1.0),
                    thickness=3,
                )
                cv2.putText(
                    frame.img,
                    "{}".format(f["id"]),
                    (x + 30, y),
                    cv2.FONT_HERSHEY_DUPLEX,
                    0.8,
                    (255, 150, 100),
                )

        if self.current_fixation_details and self.prev_index != frame.index:
            info = ""
            for f in fixations:
                info += "Current fixation, {} of {}\n".format(
                    f["id"], len(self.g_pool.fixations)
                )
                info += "    Confidence: {:.2f}\n".format(f["confidence"])
                info += "    Duration: {:.2f} milliseconds\n".format(f["duration"])
                info += "    Dispersion: {:.3f} degrees\n".format(f["dispersion"])
                info += "    Frame range: {}-{}\n".format(
                    f["start_frame_index"] + 1, f["end_frame_index"] + 1
                )
                info += "    2d gaze pos: x={:.3f}, y={:.3f}\n".format(*f["norm_pos"])
                if "gaze_point_3d" in f:
                    info += "    3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n".format(
                        *f["gaze_point_3d"]
                    )
                else:
                    info += "    3d gaze pos: N/A\n"
                if f["id"] > 1:
                    prev_f = self.g_pool.fixations[f["id"] - 2]
                    time_lapsed = (
                        f["timestamp"] - prev_f["timestamp"] + prev_f["duration"] / 1000
                    )
                    info += "    Time since prev. fixation: {:.2f} seconds\n".format(
                        time_lapsed
                    )
                else:
                    info += "    Time since prev. fixation: N/A\n"

                if f["id"] < len(self.g_pool.fixations):
                    next_f = self.g_pool.fixations[f["id"]]
                    time_lapsed = (
                        next_f["timestamp"] - f["timestamp"] + f["duration"] / 1000
                    )
                    info += "    Time to next fixation: {:.2f} seconds\n".format(
                        time_lapsed
                    )
                else:
                    info += "    Time to next fixation: N/A\n"

            self.current_fixation_details.text = info
            self.prev_index = frame.index
Esempio n. 23
0
    def recent_events(self, events):
        if self.bg_task:
            for progress, fixation_result in self.bg_task.fetch():
                self.status = progress
                if fixation_result:
                    serialized, start_ts, stop_ts = fixation_result
                    self.fixation_data.append(
                        fm.Serialized_Dict(msgpack_bytes=serialized))
                    self.fixation_start_ts.append(start_ts)
                    self.fixation_stop_ts.append(stop_ts)

                if self.fixation_data:
                    current_ts = self.fixation_stop_ts[-1]
                    progress = (current_ts - self.g_pool.timestamps[0]) / (
                        self.g_pool.timestamps[-1] - self.g_pool.timestamps[0])
                    self.menu_icon.indicator_stop = progress
            if self.bg_task.completed:
                self.status = "{} fixations detected".format(
                    len(self.fixation_data))
                self.correlate_and_publish()
                self.bg_task = None
                self.menu_icon.indicator_stop = 0.0

        frame = events.get("frame")
        if not frame:
            return

        self.last_frame_idx = frame.index
        frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index)
        fixations = self.g_pool.fixations.by_ts_window(frame_window)
        events["fixations"] = fixations
        if self.show_fixations:
            for f in fixations:
                x = int(f["norm_pos"][0] * frame.width)
                y = int((1.0 - f["norm_pos"][1]) * frame.height)
                pm.transparent_circle(
                    frame.img,
                    (x, y),
                    radius=25.0,
                    color=(0.0, 1.0, 1.0, 1.0),
                    thickness=3,
                )
                cv2.putText(
                    frame.img,
                    "{}".format(f["id"]),
                    (x + 30, y),
                    cv2.FONT_HERSHEY_DUPLEX,
                    0.8,
                    (255, 150, 100),
                )

        if self.current_fixation_details and self.prev_index != frame.index:
            info = ""
            for f in fixations:
                info += "Current fixation, {} of {}\n".format(
                    f["id"], len(self.g_pool.fixations))
                info += "    Confidence: {:.2f}\n".format(f["confidence"])
                info += "    Duration: {:.2f} milliseconds\n".format(
                    f["duration"])
                info += "    Dispersion: {:.3f} degrees\n".format(
                    f["dispersion"])
                info += "    Frame range: {}-{}\n".format(
                    f["start_frame_index"] + 1, f["end_frame_index"] + 1)
                info += "    2d gaze pos: x={:.3f}, y={:.3f}\n".format(
                    *f["norm_pos"])
                if "gaze_point_3d" in f:
                    info += "    3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n".format(
                        *f["gaze_point_3d"])
                else:
                    info += "    3d gaze pos: N/A\n"
                if f["id"] > 1:
                    prev_f = self.g_pool.fixations[f["id"] - 2]
                    time_lapsed = (f["timestamp"] - prev_f["timestamp"] +
                                   prev_f["duration"] / 1000)
                    info += "    Time since prev. fixation: {:.2f} seconds\n".format(
                        time_lapsed)
                else:
                    info += "    Time since prev. fixation: N/A\n"

                if f["id"] < len(self.g_pool.fixations):
                    next_f = self.g_pool.fixations[f["id"]]
                    time_lapsed = (next_f["timestamp"] - f["timestamp"] +
                                   f["duration"] / 1000)
                    info += "    Time to next fixation: {:.2f} seconds\n".format(
                        time_lapsed)
                else:
                    info += "    Time to next fixation: N/A\n"

            self.current_fixation_details.text = info
            self.prev_index = frame.index
Esempio n. 24
0
    def recent_events(self, events):
        frame = events.get('frame')
        events['fixations'] = self.g_pool.fixations_by_frame[frame.index]

        img = frame.img
        img_shape = img.shape[:-1][::-1] # width,height

        succeeding_frame = frame.index-self.prev_frame_idx == 1
        same_frame = frame.index == self.prev_frame_idx
        gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        #vars for calcOpticalFlowPyrLK
        lk_params = dict( winSize  = (90, 90),
                  maxLevel = 3,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 20, 0.03))

        updated_past_gaze = []
        updated_past_fixations = []

        if self.past_fixation_positions and succeeding_frame:
            past_screen_fixation = np.array(
                [denormalize(ng['norm_pos'], img_shape, flip_y=True) for ng in self.past_fixation_positions],
                dtype=np.float32)
            new_pts, status, err = cv2.calcOpticalFlowPyrLK(self.prev_gray, gray_img, past_screen_fixation, None, minEigThreshold=0.005, **lk_params)

            for fixation, new_gaze_pt, s, e in zip(self.past_fixation_positions, new_pts, status, err):
                if s:
                    # print "norm,updated",gaze['norm_gaze'], normalize(new_gaze_pt,img_shape[:-1],flip_y=True)
                    fixation['norm_pos'] = normalize(new_gaze_pt, img_shape, flip_y=True)
                    updated_past_fixations.append(fixation)
                    # logger.debug("updated gaze")
                else:
                    # logger.debug("dropping gaze")
                    # Since we will replace self.past_gaze_positions later,
                    # not appedning tu updated_past_gaze is like deliting this data point.
                    pass
        else:
            # we must be seeking, do not try to do optical flow, or pausing: see below.
            pass

        if same_frame:
            # re-use last result
            events['fixations'][:] = self.past_fixation_positions[:]
        else:
            if events.get('fixations', []):
                now = events.get('fixations', [])[0]['timestamp']

                cutoff = now - self.timeframe
                updated_past_fixations = [g for g in updated_past_fixations if g['timestamp'] > cutoff]


                # inject the scan path gaze points into recent_gaze_positions
            events.get('fixations', [])[:] = updated_past_fixations + events.get('fixations',[])
            events.get('fixations', []).sort(key=lambda x: x['timestamp'])


        fixation_pts = []

        for pt in events.get('fixations', []):
            denorm_pos = denormalize(pt['norm_pos'], frame.img.shape[:-1][::-1], flip_y=True)
            fixation_pts.append(denorm_pos)
            transparent_circle(frame.img, denorm_pos, 20, color=(0.2, 0.0, 0.7, 0.5), thickness=2)

            try:
                aoi_label = pt['aoi_label'] #self.aoi_encoder.hex_hash(pt['aoi']) #self.aoi_encoder.encode_aoi(pt['aoi'])
                cv2.putText(img, aoi_label, tuple(map(int, denorm_pos)), cv2.FONT_HERSHEY_SIMPLEX, .7, (185, 224, 236),
                            1, lineType=cv2.LINE_AA)
            except:
                #logger.info(str(pt['timestamp']))
                pass
                #pt['aoi'] = None


            # aoi = self.aoi_encoder.encode_aoi(pt['aoi'])
            # if aoi is not None:
            #     cv2.putText(img, aoi, tuple(map(int, denorm_pos)), cv2.FONT_HERSHEY_SIMPLEX, .7, (185, 224, 236), 1, lineType=cv2.LINE_AA)

        if fixation_pts:
            pts = np.array([fixation_pts], dtype=np.int32)
            cv2.polylines(frame.img, pts, isClosed=False, color= (0.25*255,0.7*255,0,0.2*255), thickness=2, lineType=cv2.LINE_AA)
        else:
            pass
            #Visualize the gaze-points

        #update info for next frame.
        self.prev_gray = gray_img
        self.prev_frame_idx = frame.index
        self.past_gaze_positions = events['gaze_positions']
        self.past_fixation_positions = events.get('fixations', [])
Esempio n. 25
0
                except KeyError, e:
                    #print e
                    color = map(lambda x: int(x * 255),(0, 0, 0, self.a))

                transparent_circle(
                            img,
                            pt_codes[x][_POINT],
                            radius = int(radius/2),
                            color = color,
                            thickness = thickness    )
        # do not find any contour        
        else:
            for pt in pts:
                transparent_circle(
                    frame.img,
                    pt,
                    radius = radius,
                    color = map(lambda x: int(x * 255),self.colors[-1]),
                    thickness = thickness    )
                cv2.putText(img, '?', (int(pt[0] -10),int(pt[1]) +10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,0), 1, lineType = cv2.CV_AA )
    
    def init_gui(self):
        # initialize the menu
        self.menu = ui.Scrolling_Menu('Gaze Circles on Contours')
        # load the configuration of last session
        self.menu.configuration = self.menu_conf
        # add menu to the window
        self.g_pool.gui.append(self.menu)
        self.menu.append(ui.Info_Text('Circle Properties'))
        self.menu.append(ui.Slider('radius',self,min=1,step=1,max=100,label='Radius'))
        self.menu.append(ui.Slider('thickness',self,min=1,step=1,max=15,label='Stroke width'))
        self.menu.append(ui.Switch('fill',self,label='Fill'))
Esempio n. 26
0
    def update(self,frame,events):
        # get image from frame       
        img = frame.img

        # set color1    
        color1 = map(lambda x: int(x * 255),(self.b, self.g, self.r, self.a))

        # cv2.THRESH_BINARY
        # cv2.THRESH_BINARY_INV
        # cv2.THRESH_TRUNC

        # find raw ellipses from cv2.findContours

        # the less the difference between ellipse area and source contour area are,
        # the better a fit between ellipse and source contour will be
        # delta_area_threshold gives the maximum allowed difference
        ellipses = []
        merge = []
        contained_contours = []

        ellipses, merge, contained_contours = ellipses_from_findContours(img,cv2_thresh_mode=cv2.THRESH_BINARY,delta_area_threshold=self.delta_area_threshold,threshold=self.threshold)
        
        alfa = self.ellipse_size

        if self.show_edges:
            #frame.img = cv2.merge(merge)
            #cv2.drawContours(frame.img, contained_contours,-1, (0,0,255))
            if ellipses:
                for ellipse in ellipses:
                            center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] ))) 
                            axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa )))
                            angle = int( round(ellipse[2] ))
                            cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0)


        # we need denormalized points for point polygon tests    
        pts = [denormalize(pt['norm_gaze'],frame.img.shape[:-1][::-1],flip_y=True) for pt in events['pupil_positions'] if pt['norm_gaze'] is not None]
           
        if ellipses:
            # get area of all ellipses
            ellipses_temp = [e[1][0]/2. * e[1][1]/2. * np.pi for e in ellipses]
            ellipses_temp.sort()

            # take the highest area as reference
            area_threshold = ellipses_temp[-1]
        
            # filtering by proportional area
            ellipses_temp = []
            for e in ellipses:
                a,b = e[1][0] / 2., e[1][1] / 2.
                ellipse_area = np.pi * a * b
                if (ellipse_area/area_threshold) < .10:
                    pass  
                else:
                    ellipses_temp.append(e)

            # cluster_hierarchy is ordenated by appearence order, from top left screen
            # it is a list of clustered ellipses
            cluster_hierarchy = []
            cluster_hierarchy = get_cluster_hierarchy(
                                    ellipses=ellipses_temp,
                                    dist_threshold=self.dist_threshold)
            # total_stm is expected to be the number of stimuli on screen
            # total_stm = len(cluster_hierarchy)

            # we need contours for point polygon tests, not ellipses
            stm_contours = []

            # cluster_set is the ellipse set associated with each stimulus on screen
            

            temp = list(cluster_hierarchy)
            for cluster_set in temp:
                #print len(cluster_set)
                if len(cluster_set) > 2:
                    cluster_hierarchy.append(cluster_hierarchy.pop(cluster_hierarchy.index(cluster_set)))

            for cluster_set in cluster_hierarchy:
                if len(cluster_set) > 0:
                    if True:
                        for ellipse in cluster_set:
                            center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] ))) 
                            axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa )))
                            angle = int( round(ellipse[2] ))
                            cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0)

                    # use only the biggest (last) ellipse for reference
                    stm_contours.append(ellipse_to_contour(cluster_set[-1], alfa))

            #print stm_contours
            # pt_codes is a list tuples:
            # tuple((denormalized point as a float x, y coordenate), 'string code given by the PointPolygonTextEx function')
            # ex.: tuple([x, y], '+1-2')
            contour_count = 0
            pt_codes = []
            for pt in pts:
                contour_count = 0
                counter_code = ''
                for contour in stm_contours:
                    contour_count, counter_code = PolygonTestRC(contour, pt, contour_count, counter_code)
                # a single code for a single point
                pt_codes.append((pt, counter_code))
            #print pt_codes
        else:
            #print 'else'
            contour_count = 0
           
        # transparent circle parameters
        radius = self.radius
        if self.fill:
            thickness= -1
        else:
            thickness = self.thickness

        # each code specifies the color of each point
        # in accordance with the self.ColorDictionary
        if contour_count > 0:
            for x in xrange(len(pt_codes)):
                try:
                    #print pt_codes[x]
                    color = self.ColorDictionary[pt_codes[x][_CODE]]
                except KeyError, e:
                    #print e
                    color = map(lambda x: int(x * 255),(0, 0, 0, self.a))

                transparent_circle(
                            img,
                            pt_codes[x][_POINT],
                            radius = int(radius/2),
                            color = color,
                            thickness = thickness    )
Esempio n. 27
0
    def recent_events(self, events):
        if self.bg_task:
            for progress, fixation_result in self.bg_task.fetch():
                self.status = progress
                if fixation_result:
                    serialized, start_ts, stop_ts = fixation_result
                    self.fixation_data.append(fm.Serialized_Dict(msgpack_bytes=serialized))
                    self.fixation_start_ts.append(start_ts)
                    self.fixation_stop_ts.append(stop_ts)

                if self.fixation_data:
                    current_ts = self.fixation_stop_ts[-1]
                    progress = ((current_ts - self.g_pool.timestamps[0]) /
                                (self.g_pool.timestamps[-1] - self.g_pool.timestamps[0]))
                    self.menu_icon.indicator_stop = progress
            if self.bg_task.completed:
                self.status = "{} fixations detected".format(len(self.fixation_data))
                self.correlate_and_publish()
                self.bg_task = None
                self.menu_icon.indicator_stop = 0.

        frame = events.get('frame')
        if not frame:
            return

        self.last_frame_idx = frame.index
        frame_window = pm.enclosing_window(self.g_pool.timestamps, frame.index)
        fixations = self.g_pool.fixations.by_ts_window(frame_window)
        events['fixations'] = fixations
        if self.show_fixations:
            for f in fixations:
                x = int(f['norm_pos'][0] * frame.width)
                y = int((1. - f['norm_pos'][1]) * frame.height)
                pm.transparent_circle(frame.img, (x, y), radius=25., color=(0., 1., 1., 1.), thickness=3)
                cv2.putText(frame.img, '{}'.format(f['id']), (x + 30, y),
                            cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 150, 100))

        if self.current_fixation_details and self.prev_index != frame.index:
            info = ''
            for f in fixations:
                info += 'Current fixation, {} of {}\n'.format(f['id'], len(self.g_pool.fixations))
                info += '    Confidence: {:.2f}\n'.format(f['confidence'])
                info += '    Duration: {:.2f} milliseconds\n'.format(f['duration'])
                info += '    Dispersion: {:.3f} degrees\n'.format(f['dispersion'])
                info += '    Frame range: {}-{}\n'.format(f['start_frame_index'] + 1, f['end_frame_index'] + 1)
                info += '    2d gaze pos: x={:.3f}, y={:.3f}\n'.format(*f['norm_pos'])
                if 'gaze_point_3d' in f:
                    info += '    3d gaze pos: x={:.3f}, y={:.3f}, z={:.3f}\n'.format(*f['gaze_point_3d'])
                else:
                    info += '    3d gaze pos: N/A\n'
                if f['id'] > 1:
                    prev_f = self.g_pool.fixations[f['id'] - 2]
                    time_lapsed = f['timestamp'] - prev_f['timestamp'] + prev_f['duration'] / 1000
                    info += '    Time since prev. fixation: {:.2f} seconds\n'.format(time_lapsed)
                else:
                    info += '    Time since prev. fixation: N/A\n'

                if f['id'] < len(self.g_pool.fixations):
                    next_f = self.g_pool.fixations[f['id']]
                    time_lapsed = next_f['timestamp'] - f['timestamp'] + f['duration'] / 1000
                    info += '    Time to next fixation: {:.2f} seconds\n'.format(time_lapsed)
                else:
                    info += '    Time to next fixation: N/A\n'

            self.current_fixation_details.text = info
            self.prev_index = frame.index
    def recent_events(self, events):
        frame = events['frame']
        if frame is not None:
            # get image from frame
            img = frame.img

            # set color1
            color1 = map(lambda x: int(x * 255),
                         (self.b, self.g, self.r, self.a))

            # cv2.THRESH_BINARY
            # cv2.THRESH_BINARY_INV
            # cv2.THRESH_TRUNC

            # find raw ellipses from cv2.findContours

            # the less the difference between ellipse area and source contour area are,
            # the better a fit between ellipse and source contour will be
            # delta_area_threshold gives the maximum allowed difference
            ellipses = []
            merge = []

            ellipses, merge, ellipses_contours = ellipses_from_findContours(
                img,
                cv2_thresh_mode=cv2.THRESH_BINARY,
                delta_area_threshold=self.delta_area_threshold,
                threshold=self.threshold)

            # for contour in ellipses_contours:
            #     print(contour.shape)
            #     break

            alfa = self.ellipse_size

            # if self.show_edges:
            #     #frame.img = cv2.merge(merge)
            #     #cv2.drawContours(frame.img, contained_contours,-1, (0,0,255))
            #     if ellipses:
            #         for ellipse in ellipses:
            #             center = ( int(round( ellipse[0][0] )), int( round( ellipse[0][1] )))
            #             axes = ( int( round( ellipse[1][0]/alfa )), int( round( ellipse[1][1]/alfa )))
            #             angle = int( round(ellipse[2] ))
            #             cv2.ellipse(img, center, axes, angle, startAngle=0, endAngle=359, color=color1, thickness=1, lineType=8, shift= 0)

            # we need denormalized points for point polygon tests
            pts = [
                denormalize(pt['norm_pos'],
                            frame.img.shape[:-1][::-1],
                            flip_y=True)
                for pt in events.get('gaze_positions', [])
            ]
            contour_count = 0
            if ellipses:
                # get area of all ellipses
                ellipses_temp = [
                    e[1][0] / 2. * e[1][1] / 2. * np.pi for e in ellipses
                ]
                ellipses_temp.sort()

                # take the highest area as reference
                area_threshold = ellipses_temp[-1]

                # filtering by proportional area
                ellipses_temp = []
                for e in ellipses:
                    a, b = e[1][0] / 2., e[1][1] / 2.
                    ellipse_area = np.pi * a * b
                    if (ellipse_area / area_threshold) < .10:
                        pass
                    else:
                        ellipses_temp.append(e)

                # cluster_hierarchy is ordenated by appearence order, from top left screen
                # it is a list of clustered ellipses
                cluster_hierarchy = []
                cluster_hierarchy = get_cluster_hierarchy(
                    ellipses=ellipses_temp, dist_threshold=self.dist_threshold)
                # total_stm is expected to be the number of stimuli on screen
                # total_stm = len(cluster_hierarchy)

                # we need contours for point polygon tests, not ellipses
                stm_contours = []

                # cluster_set is the ellipse set associated with each stimulus on screen

                temp = list(cluster_hierarchy)
                for cluster_set in temp:
                    #print(len(cluster_set))
                    if len(cluster_set) > 2:
                        cluster_hierarchy.append(
                            cluster_hierarchy.pop(
                                cluster_hierarchy.index(cluster_set)))

                for cluster_set in cluster_hierarchy:
                    if len(cluster_set) > 0:
                        # use only the smallest (first) ellipse for reference
                        ellipse = cluster_set[0]
                        stm_contours.append(ellipse_to_contour(ellipse, alfa))

                        if self.show_edges:
                            # for ellipse in cluster_set:
                            center = (int(round(ellipse[0][0])),
                                      int(round(ellipse[0][1])))
                            axes = (int(round(ellipse[1][0] / alfa)),
                                    int(round(ellipse[1][1] / alfa)))
                            angle = int(round(ellipse[2]))
                            cv2.ellipse(frame.img,
                                        center,
                                        axes,
                                        angle,
                                        startAngle=0,
                                        endAngle=359,
                                        color=color1,
                                        thickness=1,
                                        lineType=8,
                                        shift=0)

                #print(stm_contours)
                # pt_codes is a list tuples:
                # tuple((denormalized point as a float x, y coordenate), 'string code given by the PointPolygonTextEx function')
                # ex.: tuple([x, y], '+1-2')
                # if self.show_edges:
                #     for contour in stm_contours: # populated by ellipse2Poly
                # print(np.array([[c] for c in contour]).shape)
                # sys.exit("contour")
                # (x, y, w, h) = cv2.boundingRect(np.array([[c] for c in contour]))
                # cv2.rectangle(frame.img, (x, y), (x+w, y+h), (255,0,0), 2)

                # box = np.int0(cv2.cv.BoxPoints(cv2.minAreaRect(np.array([[c] for c in contour]))))
                # cv2.drawContours(frame.img,[box],0,color1,1)

                pt_codes = []
                for pt in pts:
                    contour_count = 0
                    counter_code = ''
                    for contour in stm_contours:
                        contour_count, counter_code = PolygonTestRC(
                            contour, pt, contour_count, counter_code)
                    # a single code for a single point
                    pt_codes.append((pt, counter_code))
                #print(pt_codes)

            # transparent circle parameters
            radius = self.radius
            if self.fill:
                thickness = -1
            else:
                thickness = self.thickness

            # each code specifies the color of each point
            # in accordance with the self.ColorDictionary
            if contour_count > 0:
                for pt in pt_codes:
                    try:
                        #print(pt)
                        color = self.ColorDictionary[pt[_CODE]]
                    except KeyError:
                        #print(e)
                        color = map(lambda x: int(x * 255), (0, 0, 0, self.a))

                    transparent_circle(frame.img,
                                       pt[_XY],
                                       radius=int(radius / 2),
                                       color=color,
                                       thickness=thickness)
            # do not find any contour
            else:
                for pt in pts:
                    transparent_circle(frame.img,
                                       pt,
                                       radius=radius,
                                       color=map(lambda x: int(x * 255),
                                                 self.colors[-1]),
                                       thickness=thickness)
                    cv2.putText(frame.img,
                                '?', (int(pt[0] - 10), int(pt[1]) + 10),
                                cv2.FONT_HERSHEY_SIMPLEX,
                                1, (0, 0, 0),
                                1,
                                lineType=cv2.CV_AA)