AravisProject / aravis

A vision library for genicam based cameras
GNU Lesser General Public License v2.1
897 stars 333 forks source link

Using multiple cameras at the same time (python) #754

Open javi-desp opened 1 year ago

javi-desp commented 1 year ago

Describe the bug

I'm using Aravis with python, and I'm facing problems while receiving data from 2 cameras at the same time. At first I get more or less 3/4 frame rate and i receive the images with an offset of 2s.

however when i try the arv-viewer I don't have this issue... Any idea?

To Reproduce

my python code:

class Camera():
  def __init__(self):
      self.rds = redis.Redis(host='localhost', port=6379, db=20)
      Aravis.update_device_list()
      n_devices = Aravis.get_n_devices()

      self.camera = Aravis.Camera.new (Aravis.get_device_id(1))
      self.camera.set_region (0,0,1440,980)
      #self.camera.set_frame_rate (200.0)
      self.camera.set_exposure_time_auto(0) #SET MANUAL
      self.camera.set_gain_auto(1) #SET AUTO
      self.camera.set_exposure_time(3105)
      self.camera.uv_set_usb_mode(Aravis.UvUsbMode(0))
      self.camera.set_pixel_format (Aravis.PIXEL_FORMAT_RGB_8_PACKED)
      Aravis.make_thread_high_priority(1)

      self.shutted_down = False
      self.payload = self.camera.get_payload ()
      self.x, self.y, self.width, self.height = self.camera.get_region ()
      print("!")
      self.create_stream_camera()

  def create_stream_camera(self):
      self.stream = self.camera.create_stream (None, None)
      #PREPARE 10 BUFFERS WITH A IMAGE PAYLOAD SIZE
      for i in range(0,10):
          self.stream.push_buffer (Aravis.Buffer.new_allocate (self.payload))
      self.camera.start_acquisition ()

  def get_images(self):
      self.frames = 0
      self.start_time = time.time()
      while True:
          time.sleep(0.0015)
          image = self.stream.try_pop_buffer()
          if image != None:
              self.stream.push_buffer(image)
              self.data_from_buffer = image.get_data()
              #########################################
              self.frames+=1
              if time.time() - self.start_time > 1:
                  print(" FPS = ", self.frames)
                  self.frames = 0
                  self.start_time = time.time()
              #########################################

  def run(self):
      self.frames = 0
      self.start_time = time.time()
      self.data_from_buffer = None
      threading.Thread(target=self.get_images, daemon = True).start()
      while True:
          time.sleep(0.001)
          if self.data_from_buffer != None:
              try:
                      if Aravis.PIXEL_FORMAT_MONO_8 == self.camera.get_pixel_format():
                          img_data_greyscale = np.ndarray(buffer=self.data_from_buffer, dtype=np.uint8, shape=(self.camera.get_region()[3], self.camera.get_region()[2], 1))
                          three_channel_gray_img= cv2.cvtColor(img_data_greyscale, cv2.COLOR_GRAY2BGR)
                      elif Aravis.PIXEL_FORMAT_MONO_16 == self.camera.get_pixel_format():
                          img_data_greyscale = np.ndarray(buffer=self.data_from_buffer, dtype=np.uint16, shape=(self.camera.get_region()[3], self.camera.get_region()[2], 1))
                          three_channel_gray_img= cv2.cvtColor(img_data_greyscale, cv2.COLOR_GRAY2BGR)
                      elif Aravis.PIXEL_FORMAT_RGB_8_PACKED == self.camera.get_pixel_format():
                          decoded = np.frombuffer(self.data_from_buffer, dtype=np.uint8)
                          img_data_rgb = decoded.reshape((self.camera.get_region()[3], self.camera.get_region()[2],3))
                          img_data= cv2.cvtColor(img_data_rgb, cv2.COLOR_BGR2RGB)
                          img_data_gray= cv2.cvtColor(img_data, cv2.COLOR_RGB2GRAY)
                          three_channel_gray_img = np.stack((img_data_gray,)*3, axis=-1)
                      else:
                          print("SEND ERROR --> ")
                          exit()
                      cv2.imshow("capture ", img_data)
                      cv2.waitKey(1)
              except KeyboardInterrupt as e:
                  print("LOL")
                  print(e)
                  print("SEND ALARM")
                  self.camera.stop_acquisition ()
                  exit()
          else:
              pass

  if __name__ == '__main__':
      camera_controller = Camera()
      camera_controller.run()
EmmanuelP commented 1 year ago

Hi @javi-desp , it would help if you could modify your example and make it runnable without modification.

When you say you are acquiring multiple cameras simultaneously, is it from the same program, or several instances ?

javi-desp commented 1 year ago

Hey, The problem was with my computer, it turns out that when using the USB ports from the same hub, apart from reducing the number of received frames per second (fps), there was a delay of about 1 second in sending images, which made it impossible to control the images in real time. In the end, I fixed it by inserting a separate USB3 module.

I don't know if this is normal...