def __init__(self): rospy.init_node("fasel") self.enrollService = rospy.Service("enroll", Enroll, self.handleEnrollFace) self.trainService = rospy.Service("train", Train, self.handleTrain) self.resetService = rospy.Service("reset", Reset, self.handleReset) self.namesPub = rospy.Publisher("names", String) self.personEventPub = rospy.Publisher("person_event", PersonEvent) self.imagePub = rospy.Publisher("images", Image) self.imageSub = rospy.Subscriber("image", Image, self.handleImage) self.bridge = CvBridge() self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME, image_scale=0.5) self.fel = loadFilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 64 self.enroll_list = [] self.enrollCondition = Condition() self.isTrained = False self.nameList = [] self.faceNames = [] self.faceCount = 0 self.faceTrack = dict() self.face_processing = True self.eye_processing = True self.image_flip = True self.reqQueueLock = Lock() self.faceTrackLock = Lock() self.is_running = True self.eventUpdateDelay = 2.0 # seconds self.eventUpdateTimer = Thread(target=self.eventUpdate) self.eventUpdateTimer.start()
class Facel: def __init__(self): rospy.init_node("fasel") self.enrollService = rospy.Service("enroll", Enroll, self.handleEnrollFace) self.trainService = rospy.Service("train", Train, self.handleTrain) self.resetService = rospy.Service("reset", Reset, self.handleReset) self.namesPub = rospy.Publisher("names", String) self.personEventPub = rospy.Publisher("person_event", PersonEvent) self.imagePub = rospy.Publisher("images", Image) self.imageSub = rospy.Subscriber("image", Image, self.handleImage) self.bridge = CvBridge() self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME, image_scale=0.5) self.fel = loadFilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 64 self.enroll_list = [] self.enrollCondition = Condition() self.isTrained = False self.nameList = [] self.faceNames = [] self.faceCount = 0 self.faceTrack = dict() self.face_processing = True self.eye_processing = True self.image_flip = True self.reqQueueLock = Lock() self.faceTrackLock = Lock() self.is_running = True self.eventUpdateDelay = 2.0 # seconds self.eventUpdateTimer = Thread(target=self.eventUpdate) self.eventUpdateTimer.start() # Convert opencv2 image to pyvision image def opencv_to_pyvision(self, cv_image): pil_img = PIL.Image.fromstring("RGB", (cv_image.width, cv_image.height), cv_image.tostring()) pyimg = pv.Image(pil_img) return pyimg # Convert pyvision image to opencv2 image def pyvision_to_opencv(self, pyimg): pil_img = pyimg.asPIL() cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3) # RGB image cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0] * 3) return cv_img def PIL_to_opencv(self, pil_img): cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3) # RGB image cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0] * 3) return cv_img def onFrame(self, img): """ Process a video frame. """ self.eye_time = 0.0 names = [] nFaces = 0 if self.face_processing: faces = self.findFaces(img) nFaces = len(faces) if self.enrolling != None: success = None for rect, leye, reye in faces: img.annotateRect(self.enrolling, color="yellow") if (success == None) and is_success(self.enrolling, rect): success = rect img.annotateRect(rect, color="blue") if self.eye_processing: img.annotatePoint(leye, color="blue") img.annotatePoint(reye, color="blue") self.enroll_list.append([img, rect, leye, reye]) else: img.annotateRect(rect, color="red") if self.eye_processing: img.annotatePoint(leye, color="red") img.annotatePoint(reye, color="red") img.annotateLine( pv.Point(rect.x, rect.y), pv.Point(rect.x + rect.w, rect.y + rect.h), color="red" ) img.annotateLine( pv.Point(rect.x + rect.w, rect.y), pv.Point(rect.x, rect.y + rect.h), color="red" ) if success == None: rect = self.enrolling img.annotateLine( pv.Point(rect.x, rect.y), pv.Point(rect.x + rect.w, rect.y + rect.h), color="yellow" ) img.annotateLine( pv.Point(rect.x + rect.w, rect.y), pv.Point(rect.x, rect.y + rect.h), color="yellow" ) else: # enroll in the identification algorithm pass else: for rect, leye, reye in faces: img.annotateRect(rect, color="blue") if self.eye_processing: img.annotatePoint(leye, color="blue") img.annotatePoint(reye, color="blue") for rect, leye, reye in faces: img.annotateRect(rect, color="blue") img.annotatePoint(leye, color="blue") img.annotatePoint(reye, color="blue") if self.isTrained: self.label_time = time.time() for rect, leye, reye in faces: if self.face_rec.isTrained(): label = self.face_rec.predict(img, leye, reye) names.append([0.5 * (leye + reye), label]) self.label_time = time.time() - self.label_time im = img.asAnnotated() # Flip to mirror image if self.image_flip: im = im.transpose(FLIP_LEFT_RIGHT) if self.enrolling != None: self.enrollCondition.acquire() self.enroll_count += 1 self.enrollCondition.notify() self.enrollCondition.release() # Draw on the image draw = PIL.ImageDraw.Draw(im) x, y = self.enrolling.x, self.enrolling.y if self.image_flip: xsize, ysize = im.size x = xsize - (x + self.enrolling.w) draw.text( (x + 10, y + 10), "Enrolling: %2d of %2d" % (self.enroll_count, self.enroll_max), fill="yellow", font=self.arialblack24, ) del draw facesEntered = [] if len(names) > 0: draw = PIL.ImageDraw.Draw(im) for pt, name in names: x, y = pt.X(), pt.Y() # Draw on the image x, y = pt.X(), pt.Y() w, h = draw.textsize(name, font=self.arialblack24) if self.image_flip: xsize, ysize = im.size x = xsize - x - 0.5 * w else: x = x - 0.5 * w draw.text((x, y - 20 - h), name, fill="green", font=self.arialblack24) facesEntered.append(name) # Publish only new names if name not in self.faceNames: str = "seeing %s" % name rospy.loginfo(str) self.namesPub.publish(String(name)) self.publishPersonEvent(name, "entered") del draw # Find all of the faces that are no longer detected for name in self.faceNames: if name not in facesEntered: self.publishPersonEvent(name, "exited") # print "{0} {1} {2}".format(nFaces, self.faceCount, len(facesEntered)) nFaces = nFaces - len(facesEntered) # For unidentified faces # figure out how many entered/exited if (nFaces - self.faceCount) > 0: self.publishPersonEvent("unknown", "entered") if (nFaces - self.faceCount) < 0: self.publishPersonEvent("unknown", "exited") # Update all for the next round self.faceNames = facesEntered self.faceCount = nFaces # Publish the image cv_img = self.PIL_to_opencv(im) # cv_img = self.pyvision_to_opencv(img) msg = self.bridge.cv_to_imgmsg(cv_img, encoding="rgb8") self.imagePub.publish(msg) def publishPersonEvent(self, name, event): """ Updates the dictionary """ now = time.time() # In case of non-existing records, force the update if name in self.faceTrack: self.faceTrackLock.acquire() pastEvent, lastEvent, recTime = self.faceTrack[name] self.faceTrackLock.release() else: recTime = now - self.eventUpdateDelay lastEvent = "undefined" pastEvent = lastEvent self.faceTrackLock.acquire() self.faceTrack[name] = (pastEvent, event, now) self.faceTrackLock.release() # print "publishPersonEvent for {0} {1} {2} {3} ".format(name,pastEvent,event,now) def eventUpdate(self): """ Publishes events and updates the dictionary """ while self.is_running: now = time.time() # Publish evey n seconds to avoid hysterisis, # where n = self.eventUpdateDelay self.faceTrackLock.acquire() for name in self.faceTrack: lastEvent, event, eventTime = self.faceTrack[name] if ((now - eventTime) >= self.eventUpdateDelay) and (event <> lastEvent): # print "eventUpdate for {0} {1} {2} {3} ".format(name,lastEvent,event,now) self.personEventPub.publish(event, name) self.faceTrack[name] = (event, event, now) # print "eventUpdate to {0} ".format(event) self.faceTrackLock.release() time.sleep(self.eventUpdateDelay) def enrollFace(self, name): with self.reqQueueLock: """ Starts the enrollment process. """ faces = self.current_faces if len(faces) > 1: return "too many faces to enroll" for rect, leye, reye in faces: print "Start Enrolling %s" % (name) self.enrolling = rect self.enroll_count = 0 self.nameList.append(name) self.enrollCondition.acquire() while self.enroll_count < self.enroll_max: self.enrollCondition.wait() self.enrollCondition.release() self.enrolling = None for data, rect, leye, reye in self.enroll_list: self.face_rec.addTraining(data, leye, reye, name) self.enroll_count = 0 self.enroll_list = [] return "ok" def trainFaces(self): with self.reqQueueLock: """ Start the SVM training process. """ result = "ok" # Prevent face prediction while training self.isTrained = False if self.svm_mode == SVM_AUTOMATIC: # Train with automatic tuning. print "Training mode: auto tuning" self.face_rec.train() # callback=progress.Update) self.svm_C = self.face_rec.svm.C self.svm_Gamma = self.face_rec.svm.gamma else: # Train with manual tuning. print "Training mode: manual tuning" self.face_rec.train(C=[self.svm_C], Gamma=[self.svm_Gamma]) # ,callback=progress.Update) if self.face_rec.isTrained(): result = "ok" self.isTrained = True else: result = "Error" return result def resetFaces(self): with self.reqQueueLock: """ Clear the enrollment data. """ result = "ok" self.isTrained = False nameList = [] # Clear the enrollment data for the SVM self.face_rec.reset() return result def findFaces(self, img): faces = [] self.detect_time = time.time() rects = self.face_detector.detect(img) self.detect_time = time.time() - self.detect_time cvtile = opencv.cvCreateMat(128, 128, opencv.CV_8UC3) bwtile = opencv.cvCreateMat(128, 128, opencv.CV_8U) cvimg = img.asOpenCV() self.eye_time = time.time() for rect in rects: faceim = opencv.cvGetSubRect(cvimg, rect.asOpenCV()) opencv.cvResize(faceim, cvtile) affine = pv.AffineFromRect(rect, (128, 128)) opencv.cvCvtColor(cvtile, bwtile, cv.CV_BGR2GRAY) leye, reye, lcp, rcp = self.fel.locateEyes(bwtile) leye = pv.Point(leye) reye = pv.Point(reye) leye = affine.invertPoint(leye) reye = affine.invertPoint(reye) faces.append([rect, leye, reye]) self.eye_time = time.time() - self.eye_time self.current_faces = faces return faces def handleImage(self, image_message): cv_image = self.bridge.imgmsg_to_cv(image_message, desired_encoding="rgb8") pyimg = self.opencv_to_pyvision(cv_image) self.onFrame(pyimg) # msg = self.bridge.cv_to_imgmsg(cv_image, encoding='rgb8') # self.imagePub.publish(msg) def handleEnrollFace(self, msg): result = "ok" print "Enrolling new name:" + msg.name result = self.enrollFace(msg.name) return EnrollResponse(result) def handleTrain(self, msg): result = "ok" print "Training..." if len(self.nameList) >= 2: result = self.trainFaces() else: result = "Error: need at least 2 faces to train" return TrainResponse(result) def handleReset(self, msg): result = "ok" print "Resetting..." result = self.resetFaces() return ResetResponse(result)
def __init__(self,parent,id,name,size=(640,672)): ''' Create all the windows and controls used for the window and ''' wx.Frame.__init__(self,parent,id,name,size=size) self.CenterOnScreen(wx.HORIZONTAL) self.timing_window = None # Initialize timing window # ------------- Face Processing ----------------- self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME,image_scale=0.5) self.fel = FilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e+00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 32 self.enroll_list = [] self.previous_time = time.time() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) # ---------------- Basic Data ------------------- try: self.webcam = Webcam() except SystemExit: raise except: trace = traceback.format_exc() message = TraceBackDialog(None, "Camera Error", CAMERA_ERROR, trace) message.ShowModal() sys.stderr.write("FaceL Error: an error occurred while trying to connect to the camera. Details follow.\n\n") sys.stderr.write(trace) sys.exit(CAMERA_ERROR_CODE) # ------------- Other Components ---------------- self.CreateStatusBar() # ------------------- Menu ---------------------- # Creating the menubar. # Menu IDs license_id = wx.NewId() mirror_id = wx.NewId() face_id = wx.NewId() svm_tune_id = wx.NewId() performance_id = wx.NewId() # Menu Items self.file_menu = wx.Menu(); self.file_menu.Append( wx.ID_ABOUT, "&About..." ) self.file_menu.Append( license_id, "FaceL License..." ) self.file_menu.AppendSeparator(); self.file_menu.Append( wx.ID_EXIT, "E&xit" ) self.options_menu = wx.Menu(); self.face_menuitem = self.options_menu.AppendCheckItem( face_id, "Face Processing" ) self.eye_menuitem = self.options_menu.AppendCheckItem( face_id, "Eye Detection" ) self.mirror_menuitem = self.options_menu.AppendCheckItem( mirror_id, "Mirror Video" ) self.options_menu.AppendSeparator() self.options_menu.Append( svm_tune_id, "SVM Tuning..." ) self.options_menu.Append( performance_id, "Performance..." ) # Create Menu Bar self.menu_bar = wx.MenuBar(); self.menu_bar.Append( self.file_menu, "&File" ) self.menu_bar.Append( self.options_menu, "&Options" ) self.SetMenuBar( self.menu_bar ) # Menu Events wx.EVT_MENU(self, wx.ID_ABOUT, self.onAbout ) wx.EVT_MENU(self, license_id, self.onLicense ) wx.EVT_MENU(self, mirror_id, self.onNull ) wx.EVT_MENU(self, face_id, self.onNull ) wx.EVT_MENU(self, svm_tune_id, self.onSVMTune ) wx.EVT_MENU(self, performance_id, self.onTiming ) # Set up menu checks self.face_menuitem.Check(True) self.eye_menuitem.Check(True) self.mirror_menuitem.Check(True) # ----------------- Image List ------------------ # --------------- Image Display ----------------- self.static_bitmap = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.EmptyBitmap(640, 480)) self.controls_box = wx.StaticBox(self, wx.NewId(), "Controls") self.facel_logo = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.Bitmap(FACEL_LOGO)) self.csu_logo = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.Bitmap(CSU_LOGO)) # self.performance_box = wx.StaticBox(self, wx.NewId(), "Performance") self.enroll_chioce_label = wx.StaticText(self, wx.NewId(), "Enrollment Count:", style=wx.ALIGN_LEFT) self.enroll_choice = wx.Choice(self,wx.NewId(),wx.Point(0,0),wx.Size(-1,-1),['16','32','48','64','128','256']) self.enroll_choice.Select(3) self.train_button = wx.Button(self,wx.NewId(),'Train Labeler') self.reset_button = wx.Button(self,wx.NewId(),'Clear Labels') # --------------- Instrumentation --------------- self.enroll_label = wx.StaticText(self, wx.NewId(), "Click a face in the video to enroll.", style=wx.ALIGN_LEFT) self.ids_label = wx.StaticText(self, wx.NewId(), "Labels:", size=wx.Size(-1,16), style=wx.ALIGN_LEFT) self.ids_text = wx.StaticText(self, wx.NewId(), size = wx.Size(30,16), style= wx.ALIGN_RIGHT ) self.faces_label = wx.StaticText(self, wx.NewId(), "Faces:", size=wx.Size(-1,16), style=wx.ALIGN_LEFT) self.faces_text = wx.StaticText(self, wx.NewId(), size = wx.Size(30,16), style= wx.ALIGN_RIGHT ) # --------------- Window Layout ----------------- enroll_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_sizer.Add(self.ids_label, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.ids_text, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.AddSpacer(20) enroll_sizer.Add(self.faces_label, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.faces_text, flag = wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer = wx.BoxSizer(wx.HORIZONTAL) training_sizer.Add(self.train_button, flag = wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer.Add(self.reset_button, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_choice_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_choice_sizer.Add(self.enroll_chioce_label, flag = wx.ALIGN_CENTER | wx.ALL, border=0) enroll_choice_sizer.Add(self.enroll_choice, flag = wx.ALIGN_CENTER | wx.ALL, border=0) controls_sizer = wx.StaticBoxSizer(self.controls_box,wx.VERTICAL) #wx.BoxSizer(wx.VERTICAL) controls_sizer.Add(self.enroll_label, flag = wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_choice_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=4) controls_sizer.Add(training_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=0) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) bottom_sizer.Add(self.facel_logo, flag = wx.ALIGN_CENTER | wx.ALL, border=0) bottom_sizer.Add(controls_sizer, flag = wx.ALIGN_TOP | wx.ALL, border=4) bottom_sizer.Add(self.csu_logo, flag = wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(self.static_bitmap, flag = wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer.Add(bottom_sizer, flag = wx.ALIGN_CENTER | wx.ALL, border=4) self.SetAutoLayout(True) self.SetSizer(main_sizer) self.Layout() # ----------------------------------------------- self.timer = FrameTimer(self) self.timer.Start(200) # -------------- Event Handleing ---------------- wx.EVT_SIZE(self.static_bitmap, self.onBitmapResize) wx.EVT_LEFT_DOWN(self.static_bitmap, self.onClick) self.Bind(wx.EVT_BUTTON, self.onTrain, id=self.train_button.GetId()) self.Bind(wx.EVT_BUTTON, self.onReset, id=self.reset_button.GetId()) # --------------- Setup State ------------------- self.setupState()
class VideoWindow(wx.Frame): ''' This is the main FaceL window which includes the webcam video and enrollment and training controls. ''' def __init__(self,parent,id,name,size=(640,672)): ''' Create all the windows and controls used for the window and ''' wx.Frame.__init__(self,parent,id,name,size=size) self.CenterOnScreen(wx.HORIZONTAL) self.timing_window = None # Initialize timing window # ------------- Face Processing ----------------- self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME,image_scale=0.5) self.fel = FilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e+00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 32 self.enroll_list = [] self.previous_time = time.time() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) # ---------------- Basic Data ------------------- try: self.webcam = Webcam() except SystemExit: raise except: trace = traceback.format_exc() message = TraceBackDialog(None, "Camera Error", CAMERA_ERROR, trace) message.ShowModal() sys.stderr.write("FaceL Error: an error occurred while trying to connect to the camera. Details follow.\n\n") sys.stderr.write(trace) sys.exit(CAMERA_ERROR_CODE) # ------------- Other Components ---------------- self.CreateStatusBar() # ------------------- Menu ---------------------- # Creating the menubar. # Menu IDs license_id = wx.NewId() mirror_id = wx.NewId() face_id = wx.NewId() svm_tune_id = wx.NewId() performance_id = wx.NewId() # Menu Items self.file_menu = wx.Menu(); self.file_menu.Append( wx.ID_ABOUT, "&About..." ) self.file_menu.Append( license_id, "FaceL License..." ) self.file_menu.AppendSeparator(); self.file_menu.Append( wx.ID_EXIT, "E&xit" ) self.options_menu = wx.Menu(); self.face_menuitem = self.options_menu.AppendCheckItem( face_id, "Face Processing" ) self.eye_menuitem = self.options_menu.AppendCheckItem( face_id, "Eye Detection" ) self.mirror_menuitem = self.options_menu.AppendCheckItem( mirror_id, "Mirror Video" ) self.options_menu.AppendSeparator() self.options_menu.Append( svm_tune_id, "SVM Tuning..." ) self.options_menu.Append( performance_id, "Performance..." ) # Create Menu Bar self.menu_bar = wx.MenuBar(); self.menu_bar.Append( self.file_menu, "&File" ) self.menu_bar.Append( self.options_menu, "&Options" ) self.SetMenuBar( self.menu_bar ) # Menu Events wx.EVT_MENU(self, wx.ID_ABOUT, self.onAbout ) wx.EVT_MENU(self, license_id, self.onLicense ) wx.EVT_MENU(self, mirror_id, self.onNull ) wx.EVT_MENU(self, face_id, self.onNull ) wx.EVT_MENU(self, svm_tune_id, self.onSVMTune ) wx.EVT_MENU(self, performance_id, self.onTiming ) # Set up menu checks self.face_menuitem.Check(True) self.eye_menuitem.Check(True) self.mirror_menuitem.Check(True) # ----------------- Image List ------------------ # --------------- Image Display ----------------- self.static_bitmap = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.EmptyBitmap(640, 480)) self.controls_box = wx.StaticBox(self, wx.NewId(), "Controls") self.facel_logo = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.Bitmap(FACEL_LOGO)) self.csu_logo = wx.StaticBitmap(self,wx.NewId(), bitmap=wx.Bitmap(CSU_LOGO)) # self.performance_box = wx.StaticBox(self, wx.NewId(), "Performance") self.enroll_chioce_label = wx.StaticText(self, wx.NewId(), "Enrollment Count:", style=wx.ALIGN_LEFT) self.enroll_choice = wx.Choice(self,wx.NewId(),wx.Point(0,0),wx.Size(-1,-1),['16','32','48','64','128','256']) self.enroll_choice.Select(3) self.train_button = wx.Button(self,wx.NewId(),'Train Labeler') self.reset_button = wx.Button(self,wx.NewId(),'Clear Labels') # --------------- Instrumentation --------------- self.enroll_label = wx.StaticText(self, wx.NewId(), "Click a face in the video to enroll.", style=wx.ALIGN_LEFT) self.ids_label = wx.StaticText(self, wx.NewId(), "Labels:", size=wx.Size(-1,16), style=wx.ALIGN_LEFT) self.ids_text = wx.StaticText(self, wx.NewId(), size = wx.Size(30,16), style= wx.ALIGN_RIGHT ) self.faces_label = wx.StaticText(self, wx.NewId(), "Faces:", size=wx.Size(-1,16), style=wx.ALIGN_LEFT) self.faces_text = wx.StaticText(self, wx.NewId(), size = wx.Size(30,16), style= wx.ALIGN_RIGHT ) # --------------- Window Layout ----------------- enroll_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_sizer.Add(self.ids_label, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.ids_text, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.AddSpacer(20) enroll_sizer.Add(self.faces_label, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.faces_text, flag = wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer = wx.BoxSizer(wx.HORIZONTAL) training_sizer.Add(self.train_button, flag = wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer.Add(self.reset_button, flag = wx.ALIGN_CENTER | wx.ALL, border=4) enroll_choice_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_choice_sizer.Add(self.enroll_chioce_label, flag = wx.ALIGN_CENTER | wx.ALL, border=0) enroll_choice_sizer.Add(self.enroll_choice, flag = wx.ALIGN_CENTER | wx.ALL, border=0) controls_sizer = wx.StaticBoxSizer(self.controls_box,wx.VERTICAL) #wx.BoxSizer(wx.VERTICAL) controls_sizer.Add(self.enroll_label, flag = wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_choice_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=4) controls_sizer.Add(training_sizer, flag = wx.ALIGN_LEFT | wx.ALL, border=0) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) bottom_sizer.Add(self.facel_logo, flag = wx.ALIGN_CENTER | wx.ALL, border=0) bottom_sizer.Add(controls_sizer, flag = wx.ALIGN_TOP | wx.ALL, border=4) bottom_sizer.Add(self.csu_logo, flag = wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(self.static_bitmap, flag = wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer.Add(bottom_sizer, flag = wx.ALIGN_CENTER | wx.ALL, border=4) self.SetAutoLayout(True) self.SetSizer(main_sizer) self.Layout() # ----------------------------------------------- self.timer = FrameTimer(self) self.timer.Start(200) # -------------- Event Handleing ---------------- wx.EVT_SIZE(self.static_bitmap, self.onBitmapResize) wx.EVT_LEFT_DOWN(self.static_bitmap, self.onClick) self.Bind(wx.EVT_BUTTON, self.onTrain, id=self.train_button.GetId()) self.Bind(wx.EVT_BUTTON, self.onReset, id=self.reset_button.GetId()) # --------------- Setup State ------------------- self.setupState() def onTrain(self,event=None): ''' Start the SVM training process. ''' print "Train" #progress = wx.ProgressDialog(title="SVM Training", message="Training the Face Recognition Algorithm. Please Wait...") if self.svm_mode == SVM_AUTOMATIC: # Train with automatic tuning. self.face_rec.train() #callback=progress.Update) self.svm_C = self.face_rec.svm.C self.svm_Gamma = self.face_rec.svm.gamma else: # Train with manual tuning. self.face_rec.train( C=[self.svm_C] , Gamma=[self.svm_Gamma])# ,callback=progress.Update) #progress.Destroy() def onReset(self,event=None): ''' Clear the enrollment data for the SVM. ''' self.face_rec.reset() self.setupState() def onFrame(self,event=None): ''' Retrieve and process a video frame. ''' self.timer.Stop() starttime = time.time() self.detect_time = 0.0 self.eye_time = 0.0 self.label_time = 0.0 img = self.webcam.query() face_processing = self.face_menuitem.IsChecked() eye_processing = self.eye_menuitem.IsChecked() names = [] if face_processing: faces = self.findFaces(img) if self.enrolling != None: success = None for rect,leye,reye in faces: img.annotateRect(self.enrolling,color='yellow') if (success == None) and is_success(self.enrolling,rect): success = rect img.annotateRect(rect,color='blue') if eye_processing: img.annotatePoint(leye,color='blue') img.annotatePoint(reye,color='blue') self.enroll_list.append([img,rect,leye,reye]) else: img.annotateRect(rect,color='red') if eye_processing: img.annotatePoint(leye,color='red') img.annotatePoint(reye,color='red') img.annotateLine(pv.Point(rect.x,rect.y),pv.Point(rect.x+rect.w,rect.y+rect.h), color='red') img.annotateLine(pv.Point(rect.x+rect.w,rect.y),pv.Point(rect.x,rect.y+rect.h), color='red') if success == None: rect = self.enrolling img.annotateLine(pv.Point(rect.x,rect.y),pv.Point(rect.x+rect.w,rect.y+rect.h), color='yellow') img.annotateLine(pv.Point(rect.x+rect.w,rect.y),pv.Point(rect.x,rect.y+rect.h), color='yellow') else: #enroll in the identification algorithm pass else: for rect,leye,reye in faces: img.annotateRect(rect,color='blue') if eye_processing: img.annotatePoint(leye,color='blue') img.annotatePoint(reye,color='blue') if self.face_rec.isTrained(): self.label_time = time.time() for rect,leye,reye in faces: label = self.face_rec.predict(img,leye,reye) names.append([0.5*(leye+reye),label]) self.label_time = time.time() - self.label_time # Displaying Annotated Frame im = img.asAnnotated() if self.mirror_menuitem.IsChecked(): im = im.transpose(FLIP_LEFT_RIGHT) if self.enrolling != None: draw = PIL.ImageDraw.Draw(im) x,y = self.enrolling.x,self.enrolling.y if self.mirror_menuitem.IsChecked(): x = 640 - (x + self.enrolling.w) self.enroll_count += 1 draw.text((x+10,y+10), "Enrolling: %2d of %2d"%(self.enroll_count,self.enroll_max), fill='yellow', font=self.arialblack24) del draw if self.enroll_count >= self.enroll_max: print "Count:",self.enroll_count if len(self.enroll_list) == 0: warning_dialog = wx.MessageDialog(self, "No faces were detected during the enrollment process. Please face towards the camera and keep your face in the yellow rectangle during enrollment.", style=wx.ICON_EXCLAMATION | wx.OK, caption="Enrollment Error") warning_dialog.ShowModal() else: name_dialog = wx.TextEntryDialog(self, "Please enter a name to associate with the face. (%d faces captured)"%len(self.enroll_list), caption = "Enrollment ID") result = name_dialog.ShowModal() sub_id = name_dialog.GetValue() if result == wx.ID_OK: if sub_id == "": print "Warning: Empty Subject ID" warning_dialog = wx.MessageDialog(self, "A name was entered in the previous dialog so this face will not be enrolled in the database. Please repeat the enrollment process for this person.", style=wx.ICON_EXCLAMATION | wx.OK, caption="Enrollment Error") warning_dialog.ShowModal() else: for data,rect,leye,reye in self.enroll_list: self.face_rec.addTraining(data,leye,reye,sub_id) self.setupState() self.enroll_count = 0 self.enrolling = None self.enroll_list = [] if len(names) > 0: draw = PIL.ImageDraw.Draw(im) for pt,name in names: x,y = pt.X(),pt.Y() w,h = draw.textsize(name,font=self.arialblack24) if self.mirror_menuitem.IsChecked(): x = 640 - x - 0.5*w else: x = x - 0.5*w draw.text((x,y-20-h), name, fill='green', font=self.arialblack24) del draw wxImg = wx.EmptyImage(im.size[0], im.size[1]) wxImg.SetData(im.tostring()) bm = wxImg.ConvertToBitmap() self.static_bitmap.SetBitmap(bm) # Update timing gauges full_time = time.time() - starttime if self.timing_window != None: self.timing_window.update(self.detect_time,self.eye_time,self.label_time,full_time) self.ids_text.SetLabel("%d"%(self.face_rec.n_labels,)) self.faces_text.SetLabel("%d"%(self.face_rec.n_faces,)) sleep_time = 1 if sys.platform.startswith("linux"): sleep_time = 10 # TODO: For macosx milliseconds should be 1 # TODO: For linux milliseconds may need to be set to a higher value 10 self.timer.Start(milliseconds = sleep_time, oneShot = 1) def setupState(self): #print "state",self.face_rec.n_labels,self.IsEnabled() if self.face_rec.n_labels >= 2: self.train_button.Enable() else: self.train_button.Disable() def onBitmapResize(self,event): w = event.GetSize().GetWidth() h = event.GetSize().GetHeight() self.static_bitmap.SetSize(event.GetSize()) def onClick(self,event): ''' Process a click in the Video window which starts the enrollment process. ''' x = event.GetX() y = event.GetY() if self.mirror_menuitem.IsChecked(): x = 640-x for rect,leye,reye in self.current_faces: if rect.containsPoint(pv.Point(x,y)): self.enrolling = rect self.enroll_count = 0 self.enroll_max = int(self.enroll_choice.GetStringSelection()) def findFaces(self,im): eye_processing = self.eye_menuitem.IsChecked() self.detect_time = time.time() rects = self.face_detector.detect(im) self.detect_time = time.time() - self.detect_time self.eye_time = time.time() if eye_processing: faces = self.fel.locateEyes(im, rects) else: faces = [] for rect in rects: affine = pv.AffineFromRect(rect,(1,1)) leye = affine.invertPoint(AVE_LEFT_EYE) reye = affine.invertPoint(AVE_RIGHT_EYE) faces.append([rect,leye,reye]) self.eye_time = time.time() - self.eye_time self.current_faces = faces return faces def onAbout(self,event): wx.MessageBox( ABOUT_MESSAGE, "About FaceL", wx.OK | wx.ICON_INFORMATION ) def onLicense(self,event): wx.MessageBox( LICENSE_MESSAGE, "FaceL License", wx.OK | wx.ICON_INFORMATION ) def onNull(self,*args,**kwargs): pass def onSVMTune(self,event): dialog = SVMTuningDialog(self, self.svm_mode, self.svm_C, self.svm_Gamma) dialog.CenterOnParent() result = dialog.ShowModal() if result == wx.ID_OK: self.svm_mode = dialog.mode self.svm_C = dialog.C self.svm_Gamma = dialog.Gamma print "SVM Tuning Info <MODE:%s; C:%0.2e; Gamma:%0.2e>"%(self.svm_mode,self.svm_C,self.svm_Gamma) dialog.Destroy() def onTiming(self,event): if self.timing_window == None: self.timing_window = TimingWindow(self, wx.NewId(),"Performance") self.timing_window.CenterOnParent() self.timing_window.Show(True) self.timing_window.Bind(wx.EVT_CLOSE, self.onCloseTiming, id=self.timing_window.GetId()) else: self.timing_window.Show(True) self.timing_window.Raise() def onCloseTiming(self,event): self.timing_window.Destroy() self.timing_window = None
def __init__(self, parent, id, name, size=(640, 672)): ''' Create all the windows and controls used for the window and ''' wx.Frame.__init__(self, parent, id, name, size=size) self.CenterOnScreen(wx.HORIZONTAL) self.timing_window = None # Initialize timing window # ------------- Face Processing ----------------- self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME, image_scale=0.5) self.fel = FilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e+00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 32 self.enroll_list = [] self.previous_time = time.time() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) # ---------------- Basic Data ------------------- try: self.webcam = Webcam() except SystemExit: raise except: trace = traceback.format_exc() message = TraceBackDialog(None, "Camera Error", CAMERA_ERROR, trace) message.ShowModal() sys.stderr.write( "FaceL Error: an error occurred while trying to connect to the camera. Details follow.\n\n" ) sys.stderr.write(trace) sys.exit(CAMERA_ERROR_CODE) # ------------- Other Components ---------------- self.CreateStatusBar() # ------------------- Menu ---------------------- # Creating the menubar. # Menu IDs license_id = wx.NewId() mirror_id = wx.NewId() face_id = wx.NewId() svm_tune_id = wx.NewId() performance_id = wx.NewId() # Menu Items self.file_menu = wx.Menu() self.file_menu.Append(wx.ID_ABOUT, "&About...") self.file_menu.Append(license_id, "FaceL License...") self.file_menu.AppendSeparator() self.file_menu.Append(wx.ID_EXIT, "E&xit") self.options_menu = wx.Menu() self.face_menuitem = self.options_menu.AppendCheckItem( face_id, "Face Processing") self.eye_menuitem = self.options_menu.AppendCheckItem( face_id, "Eye Detection") self.mirror_menuitem = self.options_menu.AppendCheckItem( mirror_id, "Mirror Video") self.options_menu.AppendSeparator() self.options_menu.Append(svm_tune_id, "SVM Tuning...") self.options_menu.Append(performance_id, "Performance...") # Create Menu Bar self.menu_bar = wx.MenuBar() self.menu_bar.Append(self.file_menu, "&File") self.menu_bar.Append(self.options_menu, "&Options") self.SetMenuBar(self.menu_bar) # Menu Events wx.EVT_MENU(self, wx.ID_ABOUT, self.onAbout) wx.EVT_MENU(self, license_id, self.onLicense) wx.EVT_MENU(self, mirror_id, self.onNull) wx.EVT_MENU(self, face_id, self.onNull) wx.EVT_MENU(self, svm_tune_id, self.onSVMTune) wx.EVT_MENU(self, performance_id, self.onTiming) # Set up menu checks self.face_menuitem.Check(True) self.eye_menuitem.Check(True) self.mirror_menuitem.Check(True) # ----------------- Image List ------------------ # --------------- Image Display ----------------- self.static_bitmap = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.EmptyBitmap(640, 480)) self.controls_box = wx.StaticBox(self, wx.NewId(), "Controls") self.facel_logo = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.Bitmap(FACEL_LOGO)) self.csu_logo = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.Bitmap(CSU_LOGO)) # self.performance_box = wx.StaticBox(self, wx.NewId(), "Performance") self.enroll_chioce_label = wx.StaticText(self, wx.NewId(), "Enrollment Count:", style=wx.ALIGN_LEFT) self.enroll_choice = wx.Choice(self, wx.NewId(), wx.Point(0, 0), wx.Size(-1, -1), ['16', '32', '48', '64', '128', '256']) self.enroll_choice.Select(3) self.train_button = wx.Button(self, wx.NewId(), 'Train Labeler') self.reset_button = wx.Button(self, wx.NewId(), 'Clear Labels') # --------------- Instrumentation --------------- self.enroll_label = wx.StaticText( self, wx.NewId(), "Click a face in the video to enroll.", style=wx.ALIGN_LEFT) self.ids_label = wx.StaticText(self, wx.NewId(), "Labels:", size=wx.Size(-1, 16), style=wx.ALIGN_LEFT) self.ids_text = wx.StaticText(self, wx.NewId(), size=wx.Size(30, 16), style=wx.ALIGN_RIGHT) self.faces_label = wx.StaticText(self, wx.NewId(), "Faces:", size=wx.Size(-1, 16), style=wx.ALIGN_LEFT) self.faces_text = wx.StaticText(self, wx.NewId(), size=wx.Size(30, 16), style=wx.ALIGN_RIGHT) # --------------- Window Layout ----------------- enroll_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_sizer.Add(self.ids_label, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.ids_text, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.AddSpacer(20) enroll_sizer.Add(self.faces_label, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.faces_text, flag=wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer = wx.BoxSizer(wx.HORIZONTAL) training_sizer.Add(self.train_button, flag=wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer.Add(self.reset_button, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_choice_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_choice_sizer.Add(self.enroll_chioce_label, flag=wx.ALIGN_CENTER | wx.ALL, border=0) enroll_choice_sizer.Add(self.enroll_choice, flag=wx.ALIGN_CENTER | wx.ALL, border=0) controls_sizer = wx.StaticBoxSizer( self.controls_box, wx.VERTICAL) #wx.BoxSizer(wx.VERTICAL) controls_sizer.Add(self.enroll_label, flag=wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_choice_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=4) controls_sizer.Add(training_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=0) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) bottom_sizer.Add(self.facel_logo, flag=wx.ALIGN_CENTER | wx.ALL, border=0) bottom_sizer.Add(controls_sizer, flag=wx.ALIGN_TOP | wx.ALL, border=4) bottom_sizer.Add(self.csu_logo, flag=wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(self.static_bitmap, flag=wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer.Add(bottom_sizer, flag=wx.ALIGN_CENTER | wx.ALL, border=4) self.SetAutoLayout(True) self.SetSizer(main_sizer) self.Layout() # ----------------------------------------------- self.timer = FrameTimer(self) self.timer.Start(200) # -------------- Event Handleing ---------------- wx.EVT_SIZE(self.static_bitmap, self.onBitmapResize) wx.EVT_LEFT_DOWN(self.static_bitmap, self.onClick) self.Bind(wx.EVT_BUTTON, self.onTrain, id=self.train_button.GetId()) self.Bind(wx.EVT_BUTTON, self.onReset, id=self.reset_button.GetId()) # --------------- Setup State ------------------- self.setupState()
class VideoWindow(wx.Frame): ''' This is the main FaceL window which includes the webcam video and enrollment and training controls. ''' def __init__(self, parent, id, name, size=(640, 672)): ''' Create all the windows and controls used for the window and ''' wx.Frame.__init__(self, parent, id, name, size=size) self.CenterOnScreen(wx.HORIZONTAL) self.timing_window = None # Initialize timing window # ------------- Face Processing ----------------- self.face_detector = CascadeDetector(cascade_name=CASCADE_NAME, image_scale=0.5) self.fel = FilterEyeLocator(FEL_NAME) self.face_rec = SVMFaceRec() self.svm_mode = SVM_AUTOMATIC self.svm_C = 4.000e+00 self.svm_Gamma = 9.766e-04 self.current_faces = [] self.enrolling = None self.enroll_count = 0 self.enroll_max = 32 self.enroll_list = [] self.previous_time = time.time() self.arialblack24 = PIL.ImageFont.truetype(ARIAL_BLACK_NAME, 24) # ---------------- Basic Data ------------------- try: self.webcam = Webcam() except SystemExit: raise except: trace = traceback.format_exc() message = TraceBackDialog(None, "Camera Error", CAMERA_ERROR, trace) message.ShowModal() sys.stderr.write( "FaceL Error: an error occurred while trying to connect to the camera. Details follow.\n\n" ) sys.stderr.write(trace) sys.exit(CAMERA_ERROR_CODE) # ------------- Other Components ---------------- self.CreateStatusBar() # ------------------- Menu ---------------------- # Creating the menubar. # Menu IDs license_id = wx.NewId() mirror_id = wx.NewId() face_id = wx.NewId() svm_tune_id = wx.NewId() performance_id = wx.NewId() # Menu Items self.file_menu = wx.Menu() self.file_menu.Append(wx.ID_ABOUT, "&About...") self.file_menu.Append(license_id, "FaceL License...") self.file_menu.AppendSeparator() self.file_menu.Append(wx.ID_EXIT, "E&xit") self.options_menu = wx.Menu() self.face_menuitem = self.options_menu.AppendCheckItem( face_id, "Face Processing") self.eye_menuitem = self.options_menu.AppendCheckItem( face_id, "Eye Detection") self.mirror_menuitem = self.options_menu.AppendCheckItem( mirror_id, "Mirror Video") self.options_menu.AppendSeparator() self.options_menu.Append(svm_tune_id, "SVM Tuning...") self.options_menu.Append(performance_id, "Performance...") # Create Menu Bar self.menu_bar = wx.MenuBar() self.menu_bar.Append(self.file_menu, "&File") self.menu_bar.Append(self.options_menu, "&Options") self.SetMenuBar(self.menu_bar) # Menu Events wx.EVT_MENU(self, wx.ID_ABOUT, self.onAbout) wx.EVT_MENU(self, license_id, self.onLicense) wx.EVT_MENU(self, mirror_id, self.onNull) wx.EVT_MENU(self, face_id, self.onNull) wx.EVT_MENU(self, svm_tune_id, self.onSVMTune) wx.EVT_MENU(self, performance_id, self.onTiming) # Set up menu checks self.face_menuitem.Check(True) self.eye_menuitem.Check(True) self.mirror_menuitem.Check(True) # ----------------- Image List ------------------ # --------------- Image Display ----------------- self.static_bitmap = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.EmptyBitmap(640, 480)) self.controls_box = wx.StaticBox(self, wx.NewId(), "Controls") self.facel_logo = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.Bitmap(FACEL_LOGO)) self.csu_logo = wx.StaticBitmap(self, wx.NewId(), bitmap=wx.Bitmap(CSU_LOGO)) # self.performance_box = wx.StaticBox(self, wx.NewId(), "Performance") self.enroll_chioce_label = wx.StaticText(self, wx.NewId(), "Enrollment Count:", style=wx.ALIGN_LEFT) self.enroll_choice = wx.Choice(self, wx.NewId(), wx.Point(0, 0), wx.Size(-1, -1), ['16', '32', '48', '64', '128', '256']) self.enroll_choice.Select(3) self.train_button = wx.Button(self, wx.NewId(), 'Train Labeler') self.reset_button = wx.Button(self, wx.NewId(), 'Clear Labels') # --------------- Instrumentation --------------- self.enroll_label = wx.StaticText( self, wx.NewId(), "Click a face in the video to enroll.", style=wx.ALIGN_LEFT) self.ids_label = wx.StaticText(self, wx.NewId(), "Labels:", size=wx.Size(-1, 16), style=wx.ALIGN_LEFT) self.ids_text = wx.StaticText(self, wx.NewId(), size=wx.Size(30, 16), style=wx.ALIGN_RIGHT) self.faces_label = wx.StaticText(self, wx.NewId(), "Faces:", size=wx.Size(-1, 16), style=wx.ALIGN_LEFT) self.faces_text = wx.StaticText(self, wx.NewId(), size=wx.Size(30, 16), style=wx.ALIGN_RIGHT) # --------------- Window Layout ----------------- enroll_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_sizer.Add(self.ids_label, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.ids_text, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.AddSpacer(20) enroll_sizer.Add(self.faces_label, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_sizer.Add(self.faces_text, flag=wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer = wx.BoxSizer(wx.HORIZONTAL) training_sizer.Add(self.train_button, flag=wx.ALIGN_CENTER | wx.ALL, border=4) training_sizer.Add(self.reset_button, flag=wx.ALIGN_CENTER | wx.ALL, border=4) enroll_choice_sizer = wx.BoxSizer(wx.HORIZONTAL) enroll_choice_sizer.Add(self.enroll_chioce_label, flag=wx.ALIGN_CENTER | wx.ALL, border=0) enroll_choice_sizer.Add(self.enroll_choice, flag=wx.ALIGN_CENTER | wx.ALL, border=0) controls_sizer = wx.StaticBoxSizer( self.controls_box, wx.VERTICAL) #wx.BoxSizer(wx.VERTICAL) controls_sizer.Add(self.enroll_label, flag=wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=0) controls_sizer.Add(enroll_choice_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=4) controls_sizer.Add(training_sizer, flag=wx.ALIGN_LEFT | wx.ALL, border=0) bottom_sizer = wx.BoxSizer(wx.HORIZONTAL) bottom_sizer.Add(self.facel_logo, flag=wx.ALIGN_CENTER | wx.ALL, border=0) bottom_sizer.Add(controls_sizer, flag=wx.ALIGN_TOP | wx.ALL, border=4) bottom_sizer.Add(self.csu_logo, flag=wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(self.static_bitmap, flag=wx.ALIGN_CENTER | wx.ALL, border=0) main_sizer.Add(bottom_sizer, flag=wx.ALIGN_CENTER | wx.ALL, border=4) self.SetAutoLayout(True) self.SetSizer(main_sizer) self.Layout() # ----------------------------------------------- self.timer = FrameTimer(self) self.timer.Start(200) # -------------- Event Handleing ---------------- wx.EVT_SIZE(self.static_bitmap, self.onBitmapResize) wx.EVT_LEFT_DOWN(self.static_bitmap, self.onClick) self.Bind(wx.EVT_BUTTON, self.onTrain, id=self.train_button.GetId()) self.Bind(wx.EVT_BUTTON, self.onReset, id=self.reset_button.GetId()) # --------------- Setup State ------------------- self.setupState() def onTrain(self, event=None): ''' Start the SVM training process. ''' print "Train" #progress = wx.ProgressDialog(title="SVM Training", message="Training the Face Recognition Algorithm. Please Wait...") if self.svm_mode == SVM_AUTOMATIC: # Train with automatic tuning. self.face_rec.train() #callback=progress.Update) self.svm_C = self.face_rec.svm.C self.svm_Gamma = self.face_rec.svm.gamma else: # Train with manual tuning. self.face_rec.train(C=[self.svm_C], Gamma=[self.svm_Gamma ]) # ,callback=progress.Update) #progress.Destroy() def onReset(self, event=None): ''' Clear the enrollment data for the SVM. ''' self.face_rec.reset() self.setupState() def onFrame(self, event=None): ''' Retrieve and process a video frame. ''' self.timer.Stop() starttime = time.time() self.detect_time = 0.0 self.eye_time = 0.0 self.label_time = 0.0 img = self.webcam.query() face_processing = self.face_menuitem.IsChecked() eye_processing = self.eye_menuitem.IsChecked() names = [] if face_processing: faces = self.findFaces(img) if self.enrolling != None: success = None for rect, leye, reye in faces: img.annotateRect(self.enrolling, color='yellow') if (success == None) and is_success(self.enrolling, rect): success = rect img.annotateRect(rect, color='blue') if eye_processing: img.annotatePoint(leye, color='blue') img.annotatePoint(reye, color='blue') self.enroll_list.append([img, rect, leye, reye]) else: img.annotateRect(rect, color='red') if eye_processing: img.annotatePoint(leye, color='red') img.annotatePoint(reye, color='red') img.annotateLine(pv.Point(rect.x, rect.y), pv.Point(rect.x + rect.w, rect.y + rect.h), color='red') img.annotateLine(pv.Point(rect.x + rect.w, rect.y), pv.Point(rect.x, rect.y + rect.h), color='red') if success == None: rect = self.enrolling img.annotateLine(pv.Point(rect.x, rect.y), pv.Point(rect.x + rect.w, rect.y + rect.h), color='yellow') img.annotateLine(pv.Point(rect.x + rect.w, rect.y), pv.Point(rect.x, rect.y + rect.h), color='yellow') else: #enroll in the identification algorithm pass else: for rect, leye, reye in faces: img.annotateRect(rect, color='blue') if eye_processing: img.annotatePoint(leye, color='blue') img.annotatePoint(reye, color='blue') if self.face_rec.isTrained(): self.label_time = time.time() for rect, leye, reye in faces: label = self.face_rec.predict(img, leye, reye) names.append([0.5 * (leye + reye), label]) self.label_time = time.time() - self.label_time # Displaying Annotated Frame im = img.asAnnotated() if self.mirror_menuitem.IsChecked(): im = im.transpose(FLIP_LEFT_RIGHT) if self.enrolling != None: draw = PIL.ImageDraw.Draw(im) x, y = self.enrolling.x, self.enrolling.y if self.mirror_menuitem.IsChecked(): x = 640 - (x + self.enrolling.w) self.enroll_count += 1 draw.text( (x + 10, y + 10), "Enrolling: %2d of %2d" % (self.enroll_count, self.enroll_max), fill='yellow', font=self.arialblack24) del draw if self.enroll_count >= self.enroll_max: print "Count:", self.enroll_count if len(self.enroll_list) == 0: warning_dialog = wx.MessageDialog( self, "No faces were detected during the enrollment process. Please face towards the camera and keep your face in the yellow rectangle during enrollment.", style=wx.ICON_EXCLAMATION | wx.OK, caption="Enrollment Error") warning_dialog.ShowModal() else: name_dialog = wx.TextEntryDialog( self, "Please enter a name to associate with the face. (%d faces captured)" % len(self.enroll_list), caption="Enrollment ID") result = name_dialog.ShowModal() sub_id = name_dialog.GetValue() if result == wx.ID_OK: if sub_id == "": print "Warning: Empty Subject ID" warning_dialog = wx.MessageDialog( self, "A name was entered in the previous dialog so this face will not be enrolled in the database. Please repeat the enrollment process for this person.", style=wx.ICON_EXCLAMATION | wx.OK, caption="Enrollment Error") warning_dialog.ShowModal() else: for data, rect, leye, reye in self.enroll_list: self.face_rec.addTraining( data, leye, reye, sub_id) self.setupState() self.enroll_count = 0 self.enrolling = None self.enroll_list = [] if len(names) > 0: draw = PIL.ImageDraw.Draw(im) for pt, name in names: x, y = pt.X(), pt.Y() w, h = draw.textsize(name, font=self.arialblack24) if self.mirror_menuitem.IsChecked(): x = 640 - x - 0.5 * w else: x = x - 0.5 * w draw.text((x, y - 20 - h), name, fill='green', font=self.arialblack24) del draw wxImg = wx.EmptyImage(im.size[0], im.size[1]) wxImg.SetData(im.tostring()) bm = wxImg.ConvertToBitmap() self.static_bitmap.SetBitmap(bm) # Update timing gauges full_time = time.time() - starttime if self.timing_window != None: self.timing_window.update(self.detect_time, self.eye_time, self.label_time, full_time) self.ids_text.SetLabel("%d" % (self.face_rec.n_labels, )) self.faces_text.SetLabel("%d" % (self.face_rec.n_faces, )) sleep_time = 1 if sys.platform.startswith("linux"): sleep_time = 10 # TODO: For macosx milliseconds should be 1 # TODO: For linux milliseconds may need to be set to a higher value 10 self.timer.Start(milliseconds=sleep_time, oneShot=1) def setupState(self): #print "state",self.face_rec.n_labels,self.IsEnabled() if self.face_rec.n_labels >= 2: self.train_button.Enable() else: self.train_button.Disable() def onBitmapResize(self, event): w = event.GetSize().GetWidth() h = event.GetSize().GetHeight() self.static_bitmap.SetSize(event.GetSize()) def onClick(self, event): ''' Process a click in the Video window which starts the enrollment process. ''' x = event.GetX() y = event.GetY() if self.mirror_menuitem.IsChecked(): x = 640 - x for rect, leye, reye in self.current_faces: if rect.containsPoint(pv.Point(x, y)): self.enrolling = rect self.enroll_count = 0 self.enroll_max = int(self.enroll_choice.GetStringSelection()) def findFaces(self, im): eye_processing = self.eye_menuitem.IsChecked() self.detect_time = time.time() rects = self.face_detector.detect(im) self.detect_time = time.time() - self.detect_time self.eye_time = time.time() if eye_processing: faces = self.fel.locateEyes(im, rects) else: faces = [] for rect in rects: affine = pv.AffineFromRect(rect, (1, 1)) leye = affine.invertPoint(AVE_LEFT_EYE) reye = affine.invertPoint(AVE_RIGHT_EYE) faces.append([rect, leye, reye]) self.eye_time = time.time() - self.eye_time self.current_faces = faces return faces def onAbout(self, event): wx.MessageBox(ABOUT_MESSAGE, "About FaceL", wx.OK | wx.ICON_INFORMATION) def onLicense(self, event): wx.MessageBox(LICENSE_MESSAGE, "FaceL License", wx.OK | wx.ICON_INFORMATION) def onNull(self, *args, **kwargs): pass def onSVMTune(self, event): dialog = SVMTuningDialog(self, self.svm_mode, self.svm_C, self.svm_Gamma) dialog.CenterOnParent() result = dialog.ShowModal() if result == wx.ID_OK: self.svm_mode = dialog.mode self.svm_C = dialog.C self.svm_Gamma = dialog.Gamma print "SVM Tuning Info <MODE:%s; C:%0.2e; Gamma:%0.2e>" % ( self.svm_mode, self.svm_C, self.svm_Gamma) dialog.Destroy() def onTiming(self, event): if self.timing_window == None: self.timing_window = TimingWindow(self, wx.NewId(), "Performance") self.timing_window.CenterOnParent() self.timing_window.Show(True) self.timing_window.Bind(wx.EVT_CLOSE, self.onCloseTiming, id=self.timing_window.GetId()) else: self.timing_window.Show(True) self.timing_window.Raise() def onCloseTiming(self, event): self.timing_window.Destroy() self.timing_window = None