Exemple #1
0
    to_do = gui.get_key_pressed()
    if to_do == 'quit':
        break
    #shame on me for the next lines FIXME!!!:
    elif to_do == 'debug':
        if debug == 'on':
            debug = 'off'
        elif debug == 'off':
            debug = 'on'

    if debug == 'on':
        #Timecv:
        cv2.putText(a_frame, "fps=%s avg=%s" % (timer.fps, timer.avg_fps), (10, 75),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
        #Frame counter:
        cv2.putText(a_frame, "frame=%s" % (timer.frame_num), (10, 95),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))

    #On-screen controls:
    cv2.putText(a_frame, "Behave!!! :)", (10, 130),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
    cv2.putText(a_frame, "Click with the mouse to begin", (10, 170),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
    cv2.putText(a_frame, "Press 'd' to debug, 'q' to quit", (10, 190),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
    #Display the resulting frame
    cv2.imshow('behave', a_frame)

capturer.release()
cv2.destroyAllWindows()
Exemple #2
0
class Behave(object):
    def __init__(self):
        self.timer = CvTimer()
        self.work_timer = CountdownTimer()
        #TODO:this should be configurable from gui
        self.frame_counter = FPSCounter(every=5)

        self.capturer = Capturer()
        self.frame_size = frame_width, frame_heigth = self.capturer.get_camera_width_heigth()
        #TODO: check the way to reduce the capture.
        print('capturing %sx%s' % (frame_width, frame_heigth)) 

        self.face_enforcer = enforcers.EnforceFaceLimits(say_warning)
        self.face_classifier = classifiers.CascadeClassifier(find_data_file('cascades/haarcascade_frontalface_alt.xml'))

        #Initialize GUI:
        self.gui = CX_Gui(window_name='behave', frame_size=self.frame_size, callback_obj=self)
        self.gui.initialize_gui()

        #Event hooks, they control the flow of the main loop:
        self._event_debug = False
        self._event_enforcing = True
        self._event_quit = False
        self._event_auto_limit = False
        self._event_image_show = True
        #_msg is used to get output from events
        self._event_msg = None

        #Auto-adjust protocol needs:
        self._auto_faces = []
        self._auto_num_faces = 5 #TODO: gui configurable
        self._auto_tilt = 10

    def dispatch_keyb_events(self):
        keyb_event = self.gui.keyb_event_generator()
        if keyb_event == 'quit':
            self._event_quit = True

        elif keyb_event == 'debug':
            self._event_debug = not self._event_debug

        elif keyb_event == 'toggle_work_timer':
            if self.work_timer.is_started:
                self.work_timer.stop()
            else: 
                self.work_timer.start()

        elif keyb_event == 'toggle_show_image':
            self._event_image_show = not self._event_image_show

        elif keyb_event == 'set_limit_auto':
            self._event_auto_limit = True

    def handle_left_click_in_img(self, y_coord):
        self.face_enforcer.set_y_limit_low(y_limit_low=y_coord)

    def handle_auto_limit(self, face):
        """Fancy protocol, saves N faces, takes average and sets the y limit with a tilt"""
        #We disable enforcing
        self._event_enforcing = False

        self._auto_faces.append(face)

        len_faces = len(self._auto_faces)
        msg = ("AUTO-adjusting in process... sit correctly! %s of %s" % (len_faces, self._auto_num_faces))
        
        if len_faces == self._auto_num_faces:
            y_s = [y + h / 2. for x, y, w, h in self._auto_faces]
            h_s = [h for x, y, w, h in self._auto_faces]
            #Very ugly, but needed, float to get the real avg, then truncate to get pixels
            avg_y_s = int(sum(y_s) / len_faces)
            avg_size = int(float(sum(h_s)) / len_faces)

            surplus = int(float(avg_size) / self._auto_tilt)
            y_limit_low = avg_y_s + surplus
            self.face_enforcer.set_y_limit_low(y_limit_low)

            #leaving the auto adjustment, cleaning up:
            self.face_enforcer.reset_wrongs()
            self.face_enforcer.reset_oks()
            self._auto_faces = list() 
            self._event_auto_limit = False
            self._event_enforcing = True

        return msg

    def detect_face_in_frame(self, a_frame): 
        a_frame = convert_to_gray(a_frame)
        a_frame = equalize(a_frame)
        faces_list = self.face_classifier.detect_multiscale(a_frame)

        return faces_list[0] if len(faces_list) == 1 else None

    def handle_enforce(self, face): 
        action_needed, msg = self.face_enforcer.check_face(face)
        if action_needed:
            action_needed()
            #slight relax in the limit, trying to adjust.TODO:only reduces.
            self.face_enforcer.adjust_y_limit_low_after_scold()
        if msg:
            return msg
    
    @property
    def should_process_this_frame(self):
        return self.frame_counter.check_if_capture

    def main(self):
                
        while(not self._event_quit):
            self.timer.mark_new_frame()

            #Capture frame-by-frame
            a_frame = self.capturer.get_frame()
            a_frame = flip_frame(a_frame)
            self.gui.feed_frame(a_frame)

            #detect face part:
            if self.should_process_this_frame:
                #face>>(x,y,w,h)
                face = self.detect_face_in_frame(a_frame)

                if face is not None:
                    self.gui.show_face_position(face)
                    if self._event_debug:
                        self.gui.show_face(face)
                    if self._event_auto_limit:
                        self._event_msg = self.handle_auto_limit(face)
                    elif self._event_enforcing:
                        self._event_msg = self.handle_enforce(face)

            #this if is out of the process one to leave the msg in between frames
            if self._event_msg:
                self.gui.show_msg(self._event_msg)

            #Check user input, this part needs to be after the frame has been created and fed to gui:
            self.dispatch_keyb_events()
            if self._event_debug:
                self.gui.show_debug(self.timer)
            #TODO: if face detected, work counter counts:
            if self.work_timer.is_started:
                self.gui.show_contdown(self.work_timer.get_time_left())
                
            #Add on-screen controls and limits visual guide:
            self.gui.show_controls()
            self.gui.show_limits(self.face_enforcer)

            #Display the resulting frame
            if self._event_image_show:
                self.gui.show_image()

        #if we are out of the while:
        self.clean_up()

    def clean_up(self):
        self.capturer.release()
        self.gui.close_window()