basler / pypylon

The official python wrapper for the pylon Camera Software Suite
http://www.baslerweb.com
BSD 3-Clause "New" or "Revised" License
574 stars 208 forks source link

Camera deadlocks when using multiprocessing and classes #794

Closed yGifoom closed 1 week ago

yGifoom commented 1 week ago

Describe what you want to implement and what the issue & the steps to reproduce it are:

Company is located in Italy. We were working on a computer vision pipeline, were each process is a separate class which inherits from multiprocess, all forked from a parent process. Only one said process uses the camera, the rest just process the data.

Whenever we tried to call self.cam.Close(), after having having initialized the device, that process would end up in a deadlock and freeze. We tried to replicate the behaviour and got the same results in this simplified script:

import os
import multiprocessing

class CameraEngine(multiprocessing.Process):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cam = py.InstantCamera(py.TlFactory.GetInstance().CreateFirstDevice())

    def run(self):
        os.environ["PYLON_CAMEMU"] = "0"
        self.cam.Open()
        self.cam.PixelFormat = "RGB8"
        self.cam.StartGrabbingMax(1)

        while self.cam.IsGrabbing():
            grabResult = self.cam.RetrieveResult(5000, py.TimeoutHandling_ThrowException)
            if grabResult.GrabSucceeded():
                img = grabResult.Array
                print((img))

            grabResult.Release()
        self.cam.Close()

if __name__ == "__main__":
    p = CameraEngine()
    p.start()
    p.join()

Expected output

  cam.PixelFormat = "RGB8"
[[[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 ...

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]

 [[0 0 0]
  [0 0 0]
  [0 0 0]
  ...
  [0 0 0]
  [0 0 0]
  [0 0 0]]]

actual output

[program doesn't output anything]

When running on a simple sequential program or with a multiprocess implementation without classes the output is as expected:

import os
import multiprocessing

def camera_process():
    os.environ["PYLON_CAMEMU"] = "0"
    cam = py.InstantCamera(py.TlFactory.GetInstance().CreateFirstDevice())
    cam.Open()
    cam.PixelFormat = "RGB8"
    cam.StartGrabbingMax(1)

    while cam.IsGrabbing():
        grabResult = cam.RetrieveResult(5000, py.TimeoutHandling_ThrowException)
        if grabResult.GrabSucceeded():
            img = grabResult.Array
            print((img))

        grabResult.Release()
    cam.Close()

if __name__ == "__main__":
    p = multiprocessing.Process(target=camera_process)
    p.start()
    p.join()

Is your camera operational in Basler pylon viewer on your platform

Yes

Hardware setup & camera model(s) used

Operating system is Ubuntu 22.04, processor is X86_64, ram 8 Gb. Camera model is Basler ace 2 R a2A5320-23ucBAS, Connection is with USB

Runtime information:

python: 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0]
platform: linux/x86_64/6.8.0-48-generic
pypylon: 4.0.0 / 8.0.0.10
yGifoom commented 1 week ago

Issue was solved by instantiating the cam object in run method. We were creating the object in a process and running it in another, which I believe is a known issue

thiesmoeller commented 1 week ago

Check also this possible solution to have the camera centralized and just move the images to subprocesses https://github.com/basler/pypylon/issues/513#issuecomment-1346405311