Raspberry Pi cv2.VideoCapture stuck at the second time init with same id

Viewed 254

I'm facing problem when build my source code to Raspberry Pi.

OpenCV can't init new instance and stuck at step call cv2.VideoCapture.

Here is my source code:

import threading
import time
import cv2

CAPTURE_HZ = 30.0

class Person(object):
    def __init__(self, name, id):
        self._camera = cv2.VideoCapture(id)
        print("Debug")
        self.name = name
        self._capture_frame = None
        # Use a lock to prevent access concurrent access to the camera.
        self._capture_lock = threading.Lock()
        self._capture_thread = threading.Thread(target=self._grab_frames)
        self._capture_thread.daemon = True
        self._capture_thread.start()

    def _grab_frames(self):
        while True:
            with self._capture_lock:
                self._capture_frame = self.name
            time.sleep(1.0 / CAPTURE_HZ)

    def speak(self):
        print("Hi! My name is {self.name}.".format(self=self))

Here is result I'm testing:

$ python3
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import camera
>>> camera1 = camera.Camera("Cam1", 0)
Debug
>>> camera2 = camera.Camera("Cam2", 0) <<<<< It's stuck at here

And this process take 100% CPU of Raspberry. I must using sudo kill

Thank you because read my issue!

1 Answers

I found solution for solving this problem is using: Multiprocessing

We will create a server for manage camera for make sure in once time have only one camera running and can share camera between processes.

For example:

manager.py

import threading
import time
import cv2
from multiprocessing import Process
from multiprocessing.managers import BaseManager

CAPTURE_HZ = 30.0

class Camera(object):
    def __init__(self, name, id):
        self._camera = cv2.VideoCapture(id)
        print("Debug")
        self.name = name
        self._capture_frame = None
        # Use a lock to prevent access concurrent access to the camera.
        self._capture_lock = threading.Lock()
        self._capture_thread = threading.Thread(target=self._grab_frames)
        self._capture_thread.daemon = True
        self._capture_thread.start()

    def _grab_frames(self):
        while True:
            with self._capture_lock:
                self._capture_frame = self.name
            time.sleep(1.0 / CAPTURE_HZ)

    def speak(self):
        return self.name

class CameraManager(BaseManager):
   def __init__(self, address=None, authkey=''):
      BaseManager.__init__(self, address, authkey)
      self.camera = {}

   def addCamera(self, name, texture):
      self.camera[name] = texture

   def hasCamera(self, name):
      return name in self.camera


server.py

from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Camera, CameraManager

manager = CameraManager(address=('127.0.0.1', 50000), authkey=b'hello')

def getCamera(name): # Client always call to one function is getCamera
    if manager.hasCamera(name): # If camera already running -> return that camera
        print("Exist Camera")
        return manager.camera[name]
    else: # If camera not exist -> create the new one
        print("Create New Camera")
        camera = Camera(name, 0)
        manager.addCamera(name, camera)
        manager.register(name, lambda: camera)
        return manager.camera[name]

CameraManager.register("getCamera", getCamera)

if __name__ == "__main__":
    server = manager.get_server()
    server.serve_forever()

client.py

from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Camera, CameraManager

if __name__ == "__main__":
    manager = CameraManager(address=('127.0.0.1', 50000), authkey=b'hello')
    manager.connect()
    CameraManager.register("getCamera")
    camera = manager.getCamera("camera01")
    print("data = %s" % (camera.speak()))

And here is result I was tested:

$ python3 server.py

And run two process for client.py

$ python3 client.py

At that time my server.py will be

python3 server.py
Create New Camera
Debug
Exist Camera
Exist Camera

I was learned this tutorial from This Stackoverflow Thread. Thank you so much!

Related