Based on contributions by Joel.
Daheng Imaging cameras can be accessed from Python either through Daheng’s own gxipy SDK, or through the vendor-neutral Harvester/GenICam library. This how-to covers both, so you have a fallback if one approach doesn’t work for your setup.
What you need
- A Daheng Imaging camera.
- A Daheng Imaging account to download the Galaxy Windows SDK (V2).
- Galaxy Viewer (included in the SDK) to test the connection and check camera settings.
- OpenCV:
pip install opencv-python - For the Harvester approach:
pip install harvesters
Steps
1. Download the SDK and test the connection
Go to the Daheng Imaging Software page and download the Galaxy Windows SDK (V2) (an account is required). Install it, then open Galaxy Viewer to confirm your camera is detected and can connect. From here you can also change camera settings such as Exposure time (under Acquisition control) and Gain (under Analog control).
There are two ways to then talk to the camera from Python: manually via the gxipy module bundled with the SDK, or via the generic Harvester/GenICam library. Try Harvester first (step 3); fall back to the manual approach (step 2) if it doesn’t work for your camera.
2. Manual approach with gxipy
After installing the SDK, locate the gxipy folder inside your Galaxy installation, by default something like:
C:\Program Files\Daheng Imaging\GalaxySDK\Development\Samples\Python\gxipy
Copy the entire folder into your project so your scripts can import it.
The class below wraps camera setup, streaming, and image retrieval, converting the raw Bayer image to RGB with OpenCV.
import gxipy as gx
import cv2
import os
class DahengCamera:
class DahengException(Exception):
pass
def __init__(self):
# Initialize the camera system
self.device_manager = gx.DeviceManager()
self.device_manager.update_device_list()
dev_num = self.__get_number_of_cameras()
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) # auto exposure off (set exposure manually)
self.cam.GainAuto.set(False) # auto gain off (set gain manually)
self.__set_sensor_area() # full sensor area — required for full resolution
def __get_number_of_cameras(self):
return self.device_manager.get_device_number()
def __set_sensor_area(self):
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)
self.cam.TriggerMode.set(gx.GxSwitchEntry.OFF) # continuous capture, no trigger
def load_config_file(self, file_path):
if os.path.exists(file_path):
self.cam.import_config_file(file_path)
print("Camera settings loaded from:", file_path)
else:
print("Config file not found:", file_path)
def get_frame(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
return cv2.cvtColor(raw_image, cv2.COLOR_BAYER_GR2RGB)
def start_stream(self):
self.cam.stream_on()
self.flush_buffer()
def stop_stream(self):
self.flush_buffer()
self.cam.stream_off()
def flush_buffer(self):
for _ in range(5): # adjust count if needed
try:
self.cam.StreamGetImage(timeout=50)
except Exception:
break # no more frames to discard
def change_exposure(self, exposure):
self.cam.ExposureTime.set(exposure + 24) # exposure can't go below 24
def change_gain(self, gain):
self.cam.Gain.set(gain)
def close_connection(self):
self.cam.stream_off()
self.cam.close_device()
Example usage:
def main():
cam = DahengCamera()
cam.start_stream()
while True:
frame = cam.get_frame()
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.stop_stream()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Old/stale images: if you keep receiving old frames, the camera’s internal buffer isn’t being emptied. Call
stop_stream()when you’re not actively grabbing frames, and/or callflush_buffer()to discard queued frames.
3. Harvester approach
Install the Harvesters library:
pip install harvesters
The following code opens a single image using the GenTL producer that ships with the Galaxy SDK.
from harvesters.core import Harvester
import cv2
CTI_FILE_PATH = "C:/Program Files/Daheng Imaging/GalaxySDK/GenTL/Win64/GxGVTL.cti"
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()
For a continuous-capture version and more background on Harvester/GenICam in general, see How to get an image from a GenICam-compatible camera (e.g. a Genie Nano) using Harvester.
Common mistakes
- Forgetting to actually call
flush_buffer()(i.e. calling it without parentheses) — this silently does nothing instead of discarding stale frames. - Pointing
CTI_FILE_PATHat the wrong GenTL producer file; it must be the.ctifile bundled with the Galaxy SDK, not a generic one from another vendor.
Related
Rewritten and consolidated (Sept 2026) from the original student how-to’s: How to… Connect to a Daheng Imaging camera through Python.