How to... Connect to a Daheng Imaging camera through Python

Download the right software + sdk

Go to the Daheng Imaging Software page: https://en.daheng-imaging.com/list-59-1.html. From here download the file named Galaxy Windows SDK (V2). For this you will have to first make an account.

Test if connection can be made

In order to test if the camera can be reached and to change the camera settings you can start up the now downloaded program called Galaxy Viewer. Here you should be able to find your camera and connect to it. Important settings you can change are the Exposure time under Acquisition control and the Gain under Analog control.

Create Python program

Next you can try connecting to the camera through Python. There are two viable approaches to this, incase one doesnt work. Manual or Harvester:

Manually
After installing and confirming a connection to the camera, you need to find the folder “gxipy” in the galaxy folder installed on your pc. The default location would look something like this:
C:\Program Files\Daheng Imaging\GalaxySDK\Development\Samples\Python\gxipy

Copy the entire folder into your project so that you can access it with you .py files.

Using OpenCV and the class below you are ready to receive images.
Use the startStream function to enable the camera and the getFrame function to receive the image.

Daheng class code
import gxipy as gx
import cv2, os

class Daheng_Camera():
    # Custom exception
    class DahengException(Exception):
        pass
    device_manager = None
    cam = None
    GAIN_MAX = None
    EXPOSURE_MAX = None
  
  def __init__(self):
      # Initialize the camera system
      self.device_manager = gx.DeviceManager()
      self.device_manager.update_device_list()
      
      dev_num = self.__getNumberOfCameras()
      if dev_num == 0:
          raise self.DahengException("No Daheng cameras detected")
      
      self.cam = self.device_manager.open_device_by_index(1)
      
      self.cam.ExposureAuto.set(False) # Sets auto exposure off (if you want to handle it manually)
      self.cam.GainAuto.set(False) # Sets auto gain on/off (if you want to handle it manually)
      
      self.__setSensorArea() # Set full sensor area (MUST HAVE FOR FULL RESOLUTION)
      
  
  def __getNumberOfCameras(self):      
      return self.device_manager.get_device_number()
  
  def __setSensorArea(self):
      # Set full sensor area
      self.cam.Width.set(self.cam.WidthMax.get())
      self.cam.Height.set(self.cam.HeightMax.get())
      self.cam.OffsetX.set(0)
      self.cam.OffsetY.set(0)
      
      # Disable trigger mode for continuous capture
      self.cam.TriggerMode.set(gx.GxSwitchEntry.OFF)
      
  def loadConfigFile(self, filePath):
      # Load configuration file
      if os.path.exists(filePath):
          self.cam.import_config_file(filePath)
          print("Camera settings loaded from:", filePath)
      else:
          print("Config file not found:", filePath)    
  
  def getFrame(self):
      raw_image = self.cam.data_stream[0].get_image()
      if raw_image is None:
          return None
     
      raw_image = raw_image.get_numpy_array()
      # Convert Bayer to RGB 
      image = cv2.cvtColor(raw_image, cv2.COLOR_BAYER_GR2RGB)
  
      return image
  
  def startStream(self):
      self.cam.stream_on() # Set camera ON
      self.flushBuffer
      
  def stopStream(self):
      self.flushBuffer
      self.cam.stream_off() # Set camera ON
      
  def flushBuffer(self):
      # Flush buffer
      for _ in range(5):  # Adjust count if needed
          try:
              self.cam.StreamGetImage(timeout=50)
          except:
              break  # No more frames to discard    
      
  def changeExposure(self, exposure):
      self.cam.ExposureTime.set(exposure+24) # Exposure cant be lower than 24, so this makes sure it cant go wrong  
     
  def changeGain(self, gain):
      self.cam.Gain.set(gain)
      
  def closeConnection(self):
      self.cam.stream_off()
      self.cam.close_device()
  • Old images issue
    It might occure that you receive old images, that is because the buffer of the camera wont empty itself. So if this is a issue, stopStream when you dont need the camera, and or empty the buffer with the flushBuffer function.
Example Code
  def main():
     cam = Daheng_Camera()
     cam.startStream()

     while(True): 
       frame = cam.getFrame()
       resized_image = cv2.resize(frame, (640, 640), interpolation=cv2.INTER_LINEAR)
    
       cv2.imshow("Daheng Camera View", resized_image)    
       if cv2.waitKey(1) & 0xFF == ord('q'):
          break
    
     cam.stopStream()         `

Harvester:
For this you first need to pip install the Harvesters library with “pip install harvesters”. The following code allows you to make a single image using Python.

from harvesters.core import Harvester
import cv2

CTI_FILE_PATH = "C:/Program Files/Daheng Imaging/GalaxySDK/GenTL/Win64/GxGVTL.cti"  # The filepath to the CTI file

with Harvester() as h:
    h.add_file(CTI_FILE_PATH)
    h.update()
    with h.create() as ia:
        ia.start()
        with ia.fetch() as buffer:
            component = buffer.payload.components[0]
            width = component.width
            height = component.height
            bayer = component.data.reshape((height, width))
            img = cv2.cvtColor(bayer, cv2.COLOR_BayerRG2BGR)
            img = img[..., ::-1]
            cv2.imshow("image", img)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

Added more information (manual) and code for the Daheng camera, incase Harvester doesnt work.

1 Like