I'm trying to track face with Pan and tilt motion, using servoblaster and opencv, i followed this tutorial if anyone is intrested..
it runs perfectly but after few seconds camera freezes and it stops responding and freezes completely. can any one help ? here is the code:
from multiprocessing import Process, Queue
import time
import cv2
# Upper limit
_Servo1UL = 250
_Servo0UL = 230
# Lower Limit
_Servo1LL = 75
_Servo0LL = 70
ServoBlaster = open('/dev/servoblaster', 'w')
webcam = cv2.VideoCapture(0)
webcam.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320)
webcam.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
frontalface = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
profileface = cv2.CascadeClassifier("haarcascade_profileface.xml")
face = [0,0,0,0]
Cface = [0,0]
lastface = 0
Servo0CP = Queue()
Servo1CP = Queue()
Servo0DP = Queue()
Servo1DP = Queue()
Servo0S = Queue()
Servo1S = Queue()
def P0():
speed = .1
_Servo0CP = 99
_Servo0DP = 100
while True:
time.sleep(speed)
if Servo0CP.empty():
Servo0CP.put(_Servo0CP)
if not Servo0DP.empty():
_Servo0DP = Servo0DP.get()
if not Servo0S.empty():
_Servo0S = Servo0S.get()
speed = .1 / _Servo0S
if _Servo0CP < _Servo0DP:
_Servo0CP += 1
Servo0CP.put(_Servo0CP)
ServoBlaster.write('0=' + str(_Servo0CP) + '\n') #
ServoBlaster.flush() #
if not Servo0CP.empty():
trash = Servo0CP.get()
if _Servo0CP > _Servo0DP:
_Servo0CP -= 1
Servo0CP.put(_Servo0CP)
ServoBlaster.write('0=' + str(_Servo0CP) + '\n') #
ServoBlaster.flush() #
if not Servo0CP.empty():
trash = Servo0CP.get()
if _Servo0CP == _Servo0DP:
_Servo0S = 1
def P1():
speed = .1
_Servo1CP = 99
_Servo1DP = 100
while True:
time.sleep(speed)
if Servo1CP.empty():
Servo1CP.put(_Servo1CP)
if not Servo1DP.empty():
_Servo1DP = Servo1DP.get()
if not Servo1S.empty():
_Servo1S = Servo1S.get()
speed = .1 / _Servo1S
if _Servo1CP < _Servo1DP:
_Servo1CP += 1
Servo1CP.put(_Servo1CP)
ServoBlaster.write('1=' + str(_Servo1CP) + '\n')
ServoBlaster.flush()
if not Servo1CP.empty():
trash = Servo1CP.get()
if _Servo1CP > _Servo1DP:
_Servo1CP -= 1
Servo1CP.put(_Servo1CP)
ServoBlaster.write('1=' + str(_Servo1CP) + '\n')
ServoBlaster.flush()
if not Servo1CP.empty():
trash = Servo1CP.get()
if _Servo1CP == _Servo1DP:
_Servo1S = 1
Process(target=P0, args=()).start() #
Process(target=P1, args=()).start() #
time.sleep(1)
#====================================================================================================
def CamRight( distance, speed ): .
global _Servo0CP
if not Servo0CP.empty():
_Servo0CP = Servo0CP.get()
_Servo0DP = _Servo0CP + distance
if _Servo0DP > _Servo0UL:
_Servo0DP = _Servo0UL
Servo0DP.put(_Servo0DP)
Servo0S.put(speed)
return;
def CamLeft(distance, speed):
global _Servo0CP
if not Servo0CP.empty():
_Servo0CP = Servo0CP.get()
_Servo0DP = _Servo0CP - distance
if _Servo0DP < _Servo0LL:
_Servo0DP = _Servo0LL
Servo0DP.put(_Servo0DP)
Servo0S.put(speed)
return;
def CamDown(distance, speed):
global _Servo1CP
if not Servo1CP.empty():
_Servo1CP = Servo1CP.get()
_Servo1DP = _Servo1CP + distance
if _Servo1DP > _Servo1UL:
_Servo1DP = _Servo1UL
Servo1DP.put(_Servo1DP)
Servo1S.put(speed)
return;
def CamUp(distance, speed):
global _Servo1CP
if not Servo1CP.empty():
_Servo1CP = Servo1CP.get()
_Servo1DP = _Servo1CP - distance
if _Servo1DP < _Servo1LL:
_Servo1DP = _Servo1LL
Servo1DP.put(_Servo1DP)
Servo1S.put(speed)
return;
#============================================================================================================
while True:
faceFound = False #
if not faceFound:
if lastface == 0 or lastface == 1:
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
fface = frontalface.detectMultiScale(aframe,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(60,60))
if fface != ():
lastface = 1
for f in fface:
faceFound = True
face = f
if not faceFound:
if lastface == 0 or lastface == 2:
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
pfacer = profileface.detectMultiScale(aframe,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(80,80))
if pfacer != ():
lastface = 2
for f in pfacer:
faceFound = True
face = f
if not faceFound:
if lastface == 0 or lastface == 3:
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
aframe = webcam.read()[1]
cv2.flip(aframe,1,aframe)
pfacel = profileface.detectMultiScale(aframe,1.3,4,(cv2.cv.CV_HAAR_DO_CANNY_PRUNING + cv2.cv.CV_HAAR_FIND_BIGGEST_OBJECT + cv2.cv.CV_HAAR_DO_ROUGH_SEARCH),(80,80))
if pfacel != ():
lastface = 3
for f in pfacel:
faceFound = True
face = f
if not faceFound:
lastface = 0
face = [0,0,0,0]
x,y,w,h = face
Cface = [(w/2+x),(h/2+y)]
print str(Cface[0]) + "," + str(Cface[1])
if Cface[0] != 0:
if Cface[0] > 180:
CamLeft(5,1)
if Cface[0] > 190: #
CamLeft(7,2) #
if Cface[0] > 200: #
CamLeft(9,3) #
if Cface[0] < 140:
CamRight(5,1)
if Cface[0] < 130:
CamRight(7,2)
if Cface[0] < 120:
CamRight(9,3)
if Cface[1] > 140:
CamDown(5,1)
if Cface[1] > 150:
CamDown(7,2)
if Cface[1] > 160:
CamDown(9,3)
if Cface[1] < 100:
CamUp(5,1)
if Cface[1] < 90:
CamUp(7,2)
if Cface[1] < 80:
CamUp(9,3)
-
When you say "freezes completely", do you mean just your python application or the entire Raspberry Pi?HeatfanJohn– HeatfanJohn2014年04月08日 13:55:27 +00:00Commented Apr 8, 2014 at 13:55
2 Answers 2
Face tracking with OpenCV requires a ton of calculations, so plain and simple the Pi cannot keep up with it, assuming you are running at 700MHz. I had this problem and fixed this by overclocking the Pi a bit. I now get around 25fps using the RasPi Cam module, but I am only using tracking/color filtering, not face tracking. I would recommend trying it, but be careful because the GPU and CPU will get pretty warm, so a heatsink on each would be prudent here. Hope this helps..
If load on system is high (use "top" command to check) and each detectMultiScale() call is taking too much time (10-100 millisecs is ideal.>500 ms is bad. Use clock_gettime to profile the call), try the following:
1) Introduce a small delay in the while loop
2) Tune the face detection parameters. Increase reduction factor from 1.3 to 3 or higher.
Since face detection doesn't need high resolutions, increasing it will scale down the image by that factor and then perform the classification.
I've got good results even with factor of 5 when face is close (< 3-4 feet) in front of camera.
3) Why acquire 5 frames in every iteration only to discard the first 4? It's unnecessary load on the USB driver.