Ejemplo n.º 1
0
def detectFacesInImage(cvImage, detectionDebug=False): 
  logger = logging.getLogger('ELIME.OpenCVFunctions.detectFacesInImage')
  width, height = cv.GetSize(cvImage)
  
  minDimension = min(width, height)
  
#   scale_factor = 1.1
#   min_neighbors = 3
#   flags = 0
#   min_size = (20,20)
  
  arguments = [(1.1, 3, 0, (20, 20)),
              (1.1, 3, 0, (int(1.0 * minDimension), int(1.0 * minDimension))),
              (1.1, 3, 0, (int(0.7 * minDimension), int(0.7 * minDimension))),
              (1.1, 3, 0, (int(0.4 * minDimension), int(0.4 * minDimension))),
              (1.1, 3, 0, (int(0.1 * minDimension), int(0.1 * minDimension))),
              (1.1, 3, 0, (int(0.01 * minDimension), int(0.01 * minDimension)))]
              
  path = os.path.join(PATHTOCASCADES, 'haarcascade_frontalface_default.xml')
  path = HelperFunctions.checkFile(path)
 
  if path is None:
    logger.critical("Path to opencv haarcascades is wrong: %s", PATHTOCASCADES)
    sys.exit(1)

  print path    
  faceCascade = cv.Load(path)
  
  storage = cv.CreateMemStorage()
  
  returnFaces = set()
  
  for (scale_factor, min_neighbors, flags, min_size) in arguments:
    
    detectedFaces = cv.HaarDetectObjects(cvImage, faceCascade, storage, scale_factor, min_neighbors, flags, min_size)
    debugString = '{0:d} faces found, args: {1} {2} {3} {4}'.format(len(detectedFaces), str(scale_factor), str(min_neighbors), str(flags), str(min_size))
    logger.debug(debugString)
    for face,n in detectedFaces:
      returnFaces.add(face)
    
    if detectionDebug:
      debugFaces = []
      for face,n in detectedFaces:
        debugFaces.append((face, cv.RGB(0, 0, 255)))
      UiFunctions.displayColoredRects(cvImage, debugString, debugFaces)
      
  logger.debug("returning Faces: %s", returnFaces)     
  return returnFaces
Ejemplo n.º 2
0
def main():

  configTemplate = """  [ELIME]
  # dbFile - The file path to where your eye position database will be 
  #  stored
  dbFile = ~/Documents/ELIME Project/Database/eyepositions.db

  # sourceFolder - The folder where ELIME's pre(process) command will find
  #  your unrenamed digital cameras photos
  sourceFolder = ~/Documents/ELIME Project/Drop Regular Files/

  # prefix - The prefix ELIME's pre(process) command will prepend to your
  #  photo's creation date to create the new filename
  prefix = christoph

  # delete - If ELIME should move (and not copy) your photos while renaming
  #  from sourceFolder to photoFolder
  delete = true

  # photoFolder - The folder where all your (preprocessed) daily photos
  #  savely and permanently are stored. The names of the photos in that 
  #  folder get stored in the eye position database.
  photoFolder = ~/Documents/ELIME Project/Photo Storage/

  # targetFolder - The folder where the rendered (scaled and roated) images
  #  that make up the frames of your project's video get saved. Must be 
  #  different from photoFolder for "security reasons" (tm)
  targetFolder = ~/Documents/ELIME Project/temp/

  # maxSize - The maximum x or y of the image's dimensions on which ELIME 
  #  will automatically detect eye positions and show in window. Do not go
  #  over 1024! The final size of the rendered images is completey 
  #  independent from this!
  maxSize = 1024
  
  # posDebug - Draws a colored pixel at the the eyes' positions in the rendered
  #  output images.
  posDebug = false
  
  # detectionDebug - Shows all detected eyes and faces before manual fine 
  #  control.
  detectionDebug = false
  
  # openCVHaarcascadesFolder - Path to where your opencv installation's 
  #  haarcascades reside.
  openCVHaarcascadesFolder = /usr/local/opt/opencv/share/OpenCV/haarcascades/
  """

  defaultConfigPath = os.path.expanduser('~/.ELIME.cfg')

  defaultValues = {'delete': 'false', 'maxSize': '1024', 'prefix': 'elime', 
                   'posDebug': 'false', 'detectionDebug': 'false', 
                   'openCVHaarcascadesFolder': '/usr/local/opt/opencv/share/OpenCV/haarcascades/'}

  conf_parser = argparse.ArgumentParser(add_help=False)
  conf_parser.add_argument("-c", "--conf", help="Use config file not located in '~/.ELIME.cfg' (which is the default path for ELIME's config file)", metavar="FILE")
  conf_parser.add_argument("-cc", "--createConf", action='store_true', help="Create new config file from config file template")
  args, remainingArgv = conf_parser.parse_known_args()

  if args.conf:
    defaultConfigPath = args.confFile

  if args.createConf:
    if os.path.exists(defaultConfigPath):
      print "File exists:", defaultConfigPath, "will not overwrite! Exit."
      sys.exit(1)
    with open(defaultConfigPath, 'wb') as configfile:
      configfile.write(textwrap.dedent(configTemplate))
      
    print "Created config file template at", defaultConfigPath, "Go now and customize it! ELIME's waiting here."
    sys.exit(0)

  if os.path.exists(defaultConfigPath):
    config = ConfigParser.SafeConfigParser(defaults=defaultValues, allow_no_value=True)
    config.read([defaultConfigPath])
  
    if not config.has_section('ELIME'):
      print "The config file at", defaultConfigPath, "is not a valid ELIME config file. No 'ELIME' section found. Exit."
      sys.exit(1)
    
    # print config.items('ELIME')
  
    if config.has_option('ELIME', 'dbFile'):
      defaultValues['dbFile'] = config.get('ELIME', 'dbFile')
  
    if config.has_option('ELIME', 'sourceFolder'):
      defaultValues['sourceFolder'] = config.get('ELIME', 'sourceFolder')
    
    if config.has_option('ELIME', 'prefix'):
      defaultValues['prefix'] = config.get('ELIME', 'prefix')
    
    if config.has_option('ELIME', 'delete'):
      defaultValues['delete'] = config.getboolean('ELIME', 'delete')

    if config.has_option('ELIME', 'photoFolder'):
      defaultValues['photoFolder'] = config.get('ELIME', 'photoFolder')
        
    if config.has_option('ELIME', 'targetFolder'):
      defaultValues['targetFolder'] = config.get('ELIME', 'targetFolder')
    
    if config.has_option('ELIME', 'maxSize'):
      defaultValues['maxSize'] = config.getint('ELIME', 'maxSize') 
      
    if config.has_option('ELIME', 'posDebug'):
      defaultValues['posDebug'] = config.getboolean('ELIME', 'posDebug')
      
    if config.has_option('ELIME', 'detectionDebug'):
      defaultValues['detectionDebug'] = config.getboolean('ELIME', 'detectionDebug')
    
    if config.has_option('ELIME', 'openCVHaarcascadesFolder'):
      defaultValues['openCVHaarcascadesFolder'] = config.get('ELIME', 'openCVHaarcascadesFolder')
    
    
  #print defaultValues  

  if not isinstance(defaultValues['delete'], bool):
    defaultValues['delete'] = defaultValues['delete'] in ['true', 'True']
    
  if not isinstance(defaultValues['posDebug'], bool):
    defaultValues['posDebug'] = defaultValues['posDebug'] in ['true', 'True']
    
  if not isinstance(defaultValues['detectionDebug'], bool):
    defaultValues['detectionDebug'] = defaultValues['detectionDebug'] in ['true', 'True']

  if not isinstance(defaultValues['maxSize'], int):
    defaultValues['maxSize'] = int(defaultValues['maxSize'])
  
  # print defaultValues

  parser = argparse.ArgumentParser(parents=[conf_parser], description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, epilog = "Everyday, look into my eyes!")
  parser.set_defaults(**defaultValues)

  # main parser
  parser.add_argument('--logFile', help='To enable log to file specify path of logfile')

  subparsers = parser.add_subparsers(dest='subparser_name')

  # create the parser for the "pre" command
  parser_pre = subparsers.add_parser('pre', help='Tries to determines your photos creation date and renames and moves your photos to the permanent photo folder.')
  parser_pre.add_argument('-sF', '--sourceFolder', help="The folder where ELIME's pre(process) command will find your unrenamed digital cameras photos")
  parser_pre.add_argument('-pF', '--photoFolder', help='The folder where all your (preprocessed) daily photos savely and permanently are stored. The names of the photos in that folder get stored in the eye position database.')
  parser_pre.add_argument('-p', '--prefix', help="The prefix ELIME's pre(process) command will prepend to your photo's creation date to create the new filename")
  parser_pre.add_argument('-d', '--delete', action='store_true', help='If ELIME should move (and not copy) your photos while renaming from sourceFolder to photoFolder')
  parser_pre.add_argument('-mS', '--maxSize', type=int, help="The maximum x or y of the image's dimensions on which ELIME will automatically detect eye positions and show in window. Do not go over 1024! The final size of the rendered images is completey independent from this!")
  parser_pre.set_defaults(func=preProcessImageFiles)
  # the lines in the subparsers like the next line was not needed before. Just a quick hack. Might be not the optimal solution for why it suddenly does not work anymore without.
  parser_pre.set_defaults(**defaultValues)

  # create the parser for the "add" command
  parser_add = subparsers.add_parser('add', help='"Automagically" detects your eyes in your photos from the photoFolder, lets you do fine adjustments and saves eye locations to database file.')
  parser_add.add_argument('-pF', '--photoFolder', help='The folder where all your (preprocessed) daily photos savely and permanently are stored. The names of the photos in that folder get stored in the eye position database.')
  parser_add.add_argument('-dF', '--dbFile', help='The file path to where your eye position database will be stored')
  parser_add.add_argument('-mS', '--maxSize', type=int, help="The maximum x or y of the image's dimensions on which ELIME will automatically detect eye positions and show in window. Do not go over 1024! The final size of the rendered images is completey independent from this!")
  parser_add.add_argument('--detectionDebug', action='store_true', help="Shows all detected eyes and faces before manual fine control.")
  parser_add.add_argument('-oF', '--openCVHaarcascadesFolder', help="Path to where your opencv installation's haarcascades reside.")
  parser_add.set_defaults(func=addMissingEyeData)
  parser_add.set_defaults(**defaultValues)

  # create the parser for the "check" command  
  parser_check = subparsers.add_parser('check', help='If you want to correct saved eye positions in database, here you can.')
  parser_check.add_argument('-pF', '--photoFolder', help='The folder where all your (preprocessed) daily photos savely and permanently are stored. The names of the photos in that folder get stored in the eye position database.')
  parser_check.add_argument('-dF', '--dbFile', help='The file path to where your eye position database are be stored')
  parser_check.add_argument('-mS', '--maxSize', type=int, help="The maximum x or y of the image's dimensions on which ELIME will automatically detect eye positions and show in window. Do not go over 1024! The final size of the rendered images is completey independent from this!")
  parser_check.add_argument('beginWith', nargs='*', help='Filename to begin with checking.')
  parser_check.set_defaults(func=checkEyeData)  
  parser_check.set_defaults(**defaultValues)
    
  # create the parser for the "tidy" command
  parser_tidy = subparsers.add_parser('tidy', help='Did you delete photos from your photoFolder? Run tidy to tidy the eyeposition database from deleted pictures.')
  parser_tidy.add_argument('-pF', '--photoFolder', help='The folder where all your (preprocessed) daily photos savely and permanently are stored. The names of the photos in that folder get stored in the eye position database.')
  parser_tidy.add_argument('-dF', '--dbFile', help='The file path to where your eye position database are be stored')
  parser_tidy.set_defaults(func=tidyDB)
  parser_tidy.set_defaults(**defaultValues)  
  
  # create the parser for the "render" command
  parser_render = subparsers.add_parser('render', help='Render your photos - scaled, moved and roated based on your eye positions stored in database into JPGs for further processing.')
  parser_render.add_argument('-pF', '--photoFolder', help='The folder where all your (preprocessed) daily photos savely and permanently are stored. The names of the photos in that folder get stored in the eye position database.')
  parser_render.add_argument('-dF', '--dbFile', help='The file path to where your eye position database are be stored')
  parser_render.add_argument('-tF', '--targetFolder', help="The folder where the rendered (scaled and roated) images that make up the frames of your project's video get saved. Must be different from photoFolder for 'security reasons' (tm)")
  parser_render.add_argument('--posDebug', action='store_true', help="Draws a colored pixel at the the eyes' positions in the rendered output images")
  parser_render.set_defaults(func=renderPhotos)
  parser_render.set_defaults(**defaultValues)
  
  #print parser_pre.get_default("sourceFolder")
  
  #print remainingArgv
  args = parser.parse_args(remainingArgv)
	
  #print args
	
  args.logFile = HelperFunctions.checkFile(args.logFile)
  
  setupLogging(logFile=args.logFile)
  
  if args.func == preProcessImageFiles:
    args.sourceFolder = HelperFunctions.checkFolder(args.sourceFolder)
    args.photoFolder = HelperFunctions.checkFolder(args.photoFolder)
    args.func(args.sourceFolder, args.photoFolder, args.prefix, args.delete)
  
  if args.func == addMissingEyeData:
    args.openCVHaarcascadesFolder = HelperFunctions.checkFolder(args.openCVHaarcascadesFolder)
    OpenCvFunctions.PATHTOCASCADES = args.openCVHaarcascadesFolder
    
    args.photoFolder = HelperFunctions.checkFolder(args.photoFolder)
    args.dbFile = HelperFunctions.checkFile(args.dbFile)

    args.func(args.photoFolder, args.dbFile, args.maxSize, 
              detectionDebug=args.detectionDebug)
    
  if args.func == checkEyeData:
    args.photoFolder = HelperFunctions.checkFolder(args.photoFolder)
    args.dbFile = HelperFunctions.checkFile(args.dbFile)

    args.func(args.photoFolder, args.dbFile, args.beginWith, args.maxSize)
    
  if args.func == tidyDB:
    args.photoFolder = HelperFunctions.checkFolder(args.photoFolder)
    args.dbFile = HelperFunctions.checkFile(args.dbFile)

    args.func(args.photoFolder, args.dbFile)
  
  if args.func == renderPhotos:
    args.photoFolder = HelperFunctions.checkFolder(args.photoFolder)
    args.dbFile = HelperFunctions.checkFile(args.dbFile)
    args.targetFolder = HelperFunctions.checkFolder(args.targetFolder)

    args.func(args.photoFolder, args.targetFolder, args.dbFile, 
              posDebug=args.posDebug)
      
  sys.exit(0)
Ejemplo n.º 3
0
def detectEyesInRectInImage(cvImage, rect, detectionDebug=False):

  logger = logging.getLogger('ELIME.OpenCVFunctions.detectEyesInRectInImage')
  
  EYESWANTED = 2
  
#   (scale_factor, min_neighbors, flags, min_size)
  arguments = [(1.1, 3, 0, (20,20)),
               (1.01, 3, 0, (10,10)),
               (1.05, 3, 0, (15,15)),
               (1.025, 3, 0, (10,10)),
               (1.075, 3, 0, (10,10)),
               (1.125, 3, 0, (10,10)),
               (1.15, 3, 0, (15,15)),
               (1.1, 2, 0, (30, 30))]
  
  if rect:
    (x, y, w, h) = rect
    cv.SetImageROI(cvImage, (x, y, w, int(h * 0.6)))
  
  haarcascades = ['haarcascade_eye_tree_eyeglasses.xml', 'haarcascade_eye.xml']

  storage = cv.CreateMemStorage()

  returnedEyes = []

  for cascade in haarcascades:
    
    path = os.path.join(PATHTOCASCADES, cascade)
    path = HelperFunctions.checkFile(path)
 
    if len(returnedEyes) == 2:
      break
    
    if path is None:
      logger.critical("Path to haarcascade is wrong: %s", os.path.join(PATHTOCASCADES, cascade))
      sys.exit(1)
      
    eyeCascade = cv.Load(path)
    
    for (scale_factor, min_neighbors, flags, min_size) in arguments:
      
      detectedEyes = cv.HaarDetectObjects(cvImage, eyeCascade, storage, scale_factor, min_neighbors, flags, min_size)
      
      debugString = '{0:d} eyes found, args: {1} {2} {3} {4} {5}'.format(len(detectedEyes), cascade, str(scale_factor), str(min_neighbors), str(flags), str(min_size))
      
      if detectionDebug:
        debugEyes = []
        for eye,n in detectedEyes:
          debugEyes.append((eye, cv.RGB(255, 255, 0)))
        UiFunctions.displayColoredRects(cvImage, debugString, debugEyes)
      
      logger.debug(debugString)

      if len(detectedEyes) == 0:
        logger.debug("0 eyes found. Continue.")
        continue
      
      if len(detectedEyes) == 2:
        logger.debug("2 eyes found. Break")
        returnedEyes = detectedEyes
        break
    
      if len(returnedEyes) == 0 or math.fabs(len(detectedEyes) - EYESWANTED) < math.fabs(len(returnedEyes) - EYESWANTED):
        logger.debug("%d eyes found. Better than: %d", len(detectedEyes), len(returnedEyes))
        returnedEyes = detectedEyes
    
  cv.ResetImageROI(cvImage)

  logger.debug("Returning Eyes: %s", returnedEyes)     
  return returnedEyes