0

I am currently working on a project that aims to capture photos with 4 cameras at the same time. For that, I have an Arduino that sends a trigger every second. I am using uEye cameras and I have developed a python code using the uEye API to initialize and configure the cameras as well as to collect/process/save the images.

Right now my best version has a Camera class that looks like the example below:

class Camera:

    def __init__(self, camID):
        self.id = ueye.HIDS(camID)
        

    def initCamera(self):
        # ...

    def closeCamera(self):
        # ...

    def setParameters(self):
        # ...

    def alloc_memory(self):
        # ...


    def capture(self):
        # this method searches for new images in the memory queue and saves it to a repository

I first create an instance of the Camera class for each device that is connected (= 4 cameras). I configure the cameras and, when they are ready for capture, I create a thread for each camera that will execute the "capture()" method of each Camera instance. My thread class looks like this:

class FrameThread(Thread):
    def __init__(self, camera):
        super(FrameThread, self).__init__()
        self.camera = camera

    def run(self):
        
        repos = 'C:/Users/XXXX/acquisition/'
        try:
            self.camera.capture()
        finally:
            self.stop()

    def stop(self):
        self.camera.closeCamera()

I have satisfying results when I use 1 or 2 cameras, however it is getting shaky when I add a 3rd camera and it's very bad when I have 4 cameras. By shaky I mean that, at trigger, I may only receive the images of 2 cameras instead of 3, or a camera might be disconnected during the processing. When I have 4 cameras, I may receive an image for 1, 2 or 3 cameras at the first trigger but then nothing, until maybe 30seconds later. Reading the error codes, I see that cameras get randomly disconnected during the execution. I have this error code: Error: 3 IS_CANT_OPEN_DEVICE and the API documentation details: IS_CANT_OPEN_DEVICE : An attempt to initialize or select the camera failed (no camera connected or initialization error). And this happens during the capture because all cameras need to be successfully connected before starting capturing.

I got the whole setup (arduino, cameras, usb hub and cables) from another university and I am not supposed to challenge the hardware since it used to be working for them a few years ago (hence why we chose it). This is however very old hardware and the cameras and the API are not maintained any more by the manufacturer.

That's why I am still trying to find a programming solution. A colleague mentioned the multiprocessing module instead of the threading one.

My first question is: do you think that could be relevant to my problem ?

My second question is about my implementation. I have followed basic tutorials and it worked but I haven't succeeded yet with my own code. I have extended the Process class, like below:

class FrameProcess(Process):
    
    def __init__(self, cam):
        super().__init__()
        self.camera = camera

    def run(self):
        
        repos = 'C:/Users/xxxxx/acquisition/'
        try:
            self.camera.capture()
        finally:
            self.stop()

    def stop(self):
        self.camera.closeCamera()

I have the following error

Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Python\python_3.10.8\lib\multiprocessing\spawn.py", line 116, in spawn_main
exitcode = _main(fd, parent_sentinel)
File "C:\Python\python_3.10.8\lib\multiprocessing\spawn.py", line 126, in _main
self = reduction.pickle.load(from_parent)
TypeError: function.__new__(X): X is not a type object (function)

I have also tried to create my processes without extending the Process class, using:

process = multiprocessing.Process(target=camera.capture)

I have also tried to create the instances of the Camera class in the process, basically create and initialise a process for each camera and then everything is done in each process.

But I always end up with this error, there is clearly something here that I am missing.

Thanks for reading, I know it is a lot. I'll happily add any details

lagoon
  • 1
  • Do you know for sure that the driver for the camera is thread-safe? If it's not, that could lead to the type of (somewhat random) errors you are seeing. Python shares memory between threads, but there is probably and underlying hardware driver here and it may not supporting multithreading. Perhaps it would be simple to move the creation of the Camera objects into each thread; in other words, call Camera() at the beginning of the FrameThread.run() method. That way each camera's code is isolated in a single thread. Switching to multiprocessing will almost certainly create worse problems. – Paul Cornelius Aug 22 '23 at 01:11
  • Thank you for your answer. I tried your suggestion but I didn't see any changes of behaviour. I have however found the solution of my problem which is a hardware limitation regarding the bandwidth (it's all USB 2.0). – lagoon Aug 23 '23 at 08:39

0 Answers0