facetracker.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. from picamera.array import PiRGBArray
  2. from picamera import PiCamera
  3. from datetime import datetime
  4. import time
  5. import cv2
  6. import sys
  7. import imutils
  8. import math # for sqrt distance formula
  9. # Create the haar cascade
  10. frontalfaceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
  11. profilefaceCascade = cv2.CascadeClassifier("haarcascade_profileface.xml")
  12. face = [0,0,0,0] # This will hold the array that OpenCV returns when it finds a face: (makes a rectangle)
  13. center = [0,0] # Center of the face: a point calculated from the above variable
  14. lastface = 0 # int 1-3 used to speed up detection. The script is looking for a right profile face,-
  15. # a left profile face, or a frontal face; rather than searching for all three every time,-
  16. # it uses this variable to remember which is last saw: and looks for that again. If it-
  17. # doesn't find it, it's set back to zero and on the next loop it will search for all three.-
  18. # This basically tripples the detect time so long as the face hasn't moved much.
  19. # initialize the camera and grab a reference to the raw camera capture
  20. camera = PiCamera()
  21. #camera.resolution = (160, 120)
  22. camera.resolution = (320,240)
  23. cameracenter = (320/2, 240/2)
  24. camera.framerate = 32
  25. rawCapture = PiRGBArray(camera, size=(320, 240))
  26. def distance(p0, p1):
  27. return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
  28. def search_rightprofile(i):
  29. return profilefaceCascade.detectMultiScale(i,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(30,30))
  30. def search_leftprofile(i):
  31. revimage = cv2.flip(i, 1) # Flip the image
  32. return profilefaceCascade.detectMultiScale(i,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(30,30))
  33. def search_frontface(i):
  34. return frontalfaceCascade.detectMultiScale(i,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(30,30))
  35. # allow the camera to warmup
  36. time.sleep(0.1)
  37. lastTime = time.time()*1000.0
  38. # capture frames from the camera
  39. for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
  40. # grab the raw NumPy array representing the image, then initialize the timestamp
  41. # and occupied/unoccupied text
  42. image = frame.array
  43. faceFound = False # This variable is set to true if, on THIS loop a face has already been found
  44. # We search for a face three diffrent ways, and if we have found one already-
  45. # there is no reason to keep looking.
  46. faces = ()
  47. # First Scan
  48. if lastface == 1:
  49. faces = search_rightprofile(image)
  50. if faces != ():
  51. faceFound=True
  52. lastface = 1
  53. elif lastface == 2:
  54. faces = search_leftprofile(image)
  55. if faces != ():
  56. faceFound=True
  57. lastface = 2
  58. else:
  59. faces = search_frontface(image)
  60. if faces != ():
  61. lastface = 3
  62. faceFound=True
  63. # Second scan
  64. if not faceFound:
  65. faces = search_frontface(image)
  66. if faces != ():
  67. lastface = 3
  68. faceFound=True
  69. elif lastface == 2:
  70. faces = search_rightprofile(image)
  71. if faces != ():
  72. faceFound=True
  73. lastface = 1
  74. else:
  75. faces = search_leftprofile(image)
  76. if faces != ():
  77. faceFound=True
  78. lastface = 2
  79. # Third scan
  80. if not faceFound:
  81. faces = search_leftprofile(image)
  82. if faces != ():
  83. faceFound=True
  84. lastface = 2
  85. elif lastface == 2:
  86. faces = search_frontface(image)
  87. if faces != ():
  88. lastface = 3
  89. faceFound=True
  90. else:
  91. faces = search_rightprofile(image)
  92. if faces != ():
  93. faceFound=True
  94. lastface = 1
  95. if not faceFound:
  96. print time.time()*1000.0-lastTime," no faces found."
  97. lastTime = time.time()*1000.0
  98. # clear the stream in preparation for the next frame
  99. rawCapture.truncate(0)
  100. continue;
  101. print time.time()*1000.0-lastTime," {} faces found.".format(len(faces))
  102. lastTime = time.time()*1000.0
  103. # Draw a rectangle around the faces
  104. for (x, y, w, h) in faces:
  105. cv2.circle(image, (x+w/2, y+h/2), int((w+h)/3), (255, 255, 255), 1)
  106. # Temporary, save the image
  107. cv2.imwrite("tmp/img.{}.png".format(datetime.now().strftime("%Y%m%%d.%H%M%S.%f")), image)
  108. # clear the stream in preparation for the next frame
  109. rawCapture.truncate(0)
  110. # Find teh centermost face
  111. curdistance = 1000000 # Outside the dimensions of the picture
  112. for f in faces:
  113. x,y,w,h = f
  114. tmpcenter = [(w/2+x),(h/2+y)] # we are given an x,y corner point and a width and height, we need the center
  115. tmpdistance = distance(tmpcenter, cameracenter)
  116. if(tmpdistance < curdistance):
  117. print "Face closer to center detected. New target location: ({}, {}) - distance: {}".format(tmpcenter[0],tmpcenter[1],tmpdistance)
  118. center = tmpcenter;