pythonopencvcascade-classifier

Object detection with openCV cascade classifiers taking too much time


I am trying to do object detection from raspberry pi by getting frames from three webcam camera's attached to raspberry. currently I have three types of objects which I want to detect so I trained three cascade classifiers as following .

 opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 1200 -numNeg 1000 -numStages 11 -minHitRate 0.999 -maxFalseAlarmRate 0.2 -w 24 -h 24 

I am getting the frames from three cameras in a loop and passing each frame to Detection class .

        obj_detection= ObjectDetection()
        for name in camera_names:

            if name not in self.cv2_window_name:
                self.cv2_window_name.append(name)

            frame = datavector[name]
            width, height, channel = frame.shape
            frame=cv2.resize(frame,(int(width/1),int(height/2)),interpolation=cv2.INTER_AREA)  #resizing image helped a little but didnt helped much 
            frame = obj_detection.detect(frame)

            print(time.time())    #to check frame rate currently showing 4 frames per second

            cv2.imshow(name, frame)
            cv2.waitKey(1)  # CV2 Devil

in ObjectDetection class

    self.objs['Traffic light']= cv2.CascadeClassifier("../1.xml")
    self.objs['Stop']= cv2.CascadeClassifier("../2.xml")
    self.objs['No Left'] = cv2.CascadeClassifier("../3.xml")

 def detect(self,image):
        self.image=image

        objects = [key for key in self.objs]
        t={}
        for type in objects:
            t[type]=Thread(target = self.detect_obj,args=(self.objs[type],self.image,type))
            t[type].start()
        [t[type].join() for type in objects] 
        return self.image




 def detect_obj(self,classifier,image,type=""):
        self.image=image
        gray_image = cv2.cvtColor(self.image , cv2.COLOR_BGR2GRAY)   
        obj=classifier.detectMultiScale(
            gray_image,
            scaleFactor=1.02,
            minNeighbors=2,
            minSize=(50,50),
            flags=cv2.CASCADE_SCALE_IMAGE
            )



        for (x,y,w,h) in obj:
            cv2.rectangle(self.image,(x,y),(x+w,y+h),(255,219,0),2)

The problem is that i am getting 4-5 frames per second after detection but I need at least 10 frames per second. Is there anything I can try to speed up the detection ?? Any help would be highly appreciated .

NOTE I have also tried Using LBP features while training but that didnt helped .


Solution

  • You are trying to do alot on very little

    A few points to answer the question of "How can I try and speed up detection", these are all opinion but based on experience

    1. The RPi largely struggles to process large amounts of camera data very fast, especially with three cameras. It does not have a huge amount of processing power, I would suggest looking at what your processing usage is without any detection
    2. Object detection is quite CPU intensive, even when used sparingly, trying to run this on three threads is likely just way too much for your processor
    3. You can reduce the amount of processing you are doing by increasing/decreasing your scale factor and min/max size, this will end up in much more detections (i.e. noise) but will run faster
    4. Resizing frames also takes time, try and setup the cameras so that they are providing you the correct size images, rather than resizing them on the fly

    A couple of other notes:

    1. Try running your code on a much gruniter processor (i.e. a desktop PC or a laptop) and see how this increases the speed
    2. As "@Long Luong" states your lack of GPU will be very limiting
    3. This is inherently a difficult question to answer reliably because of all the different factors that need to be taken into consideration, hence my fairly wishy washy answer.