0

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 Apr 8 '14 at 13:55
1

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..

0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.