Skip to main content

Pythonic Hikrobot MVS camera SDK wrapper for USB3 and GigE cameras

Project description

hgrabber-sdk

Small Python wrapper around Hikrobot MVS MvCameraControl for USB3 and GigE cameras.

The package vendors the official generated Python MvImport files from:

C:\Program Files (x86)\MVS\Development\Samples\Python\MvImport

The native Hikrobot MVS runtime is not bundled in this package. Install MVS separately on the target machine, or point the package at the native library with HIK_CAMERA_SDK_MVS_LIBRARY.

Setup with uv

This project is configured for uv and pins Python through .python-version.

pip install hgrabber-sdk
uv sync --dev
uv run python -c "import hgrabber_sdk; print(hgrabber_sdk.__all__)"
uv run pytest
uv run python examples/list_devices.py

The import check does not load the native Hikrobot runtime. Commands that enumerate or open cameras load MvCameraControl lazily.

Native MVS runtime

Install Hikrobot MVS from the official installer for the target OS.

The loader checks these locations in order:

  • HIK_CAMERA_SDK_MVS_LIBRARY: full path to MvCameraControl.dll or libMvCameraControl.so.
  • Windows: the standard MVS runtime folder under Common Files\MVS\Runtime, then normal PATH.
  • Linux: MVCAM_COMMON_RUNENV pointing to a runtime root that contains 64/libMvCameraControl.so, aarch64/libMvCameraControl.so, or another matching architecture directory. Common install paths such as /opt/MVS/lib are also checked.

Windows override example:

$env:HIK_CAMERA_SDK_MVS_LIBRARY = "C:\Program Files (x86)\Common Files\MVS\Runtime\Win64_x64\MvCameraControl.dll"

Linux root example:

export MVCAM_COMMON_RUNENV=/opt/MVS/lib

Linux exact library override:

export HIK_CAMERA_SDK_MVS_LIBRARY=/opt/MVS/lib/64/libMvCameraControl.so

Build and publish

Build a pure Python wheel. It contains the wrapper code only, not Hikrobot's native runtime:

uv sync --dev
uv build
uv run --dev twine check dist\*

Upload to TestPyPI first, then PyPI:

uv run --dev twine upload --repository testpypi dist\*.whl
uv run --dev twine upload dist\*.whl

Linux Docker Smoke Test

Build the Linux image and run package tests without native MVS libraries:

docker build -t hgrabber-sdk-linux .
docker run --rm hgrabber-sdk-linux

To test the native Hikrobot SDK and camera discovery, install or extract the Linux MVS runtime on the host and mount the runtime directory into /opt/mvs. The mounted directory must contain the architecture subdirectory expected by the loader, for example:

/path/to/mvs-runtime/
  64/libMvCameraControl.so

GigE camera discovery is easiest with host networking:

docker run --rm --network host \
  -e MVCAM_COMMON_RUNENV=/opt/mvs \
  -v /path/to/mvs-runtime:/opt/mvs:ro \
  hgrabber-sdk-linux \
  python examples/linux_smoke.py

For USB cameras, run on a real Linux host and pass USB devices through:

docker run --rm --network host --privileged \
  -e MVCAM_COMMON_RUNENV=/opt/mvs \
  -v /dev/bus/usb:/dev/bus/usb \
  -v /path/to/mvs-runtime:/opt/mvs:ro \
  hgrabber-sdk-linux \
  python examples/linux_smoke.py

Docker Desktop/WSL may not expose industrial USB/GigE cameras reliably; use a native Linux host for hardware validation.

Supported flows

  • USB3 and GigE discovery by serial number, user name, model name, or GigE IP.
  • Synchronous grabbing with GetImageBuffer.
  • Async polling worker.
  • asyncio methods for non-blocking application code.
  • Native SDK image callback mode.
  • Continuous acquisition.
  • Software trigger.
  • Hardware line trigger: Line0, Line1, Line2, Line3, with activation, delay, cache, debouncer.
  • GigE action trigger: Action1 with device/group keys and broadcast address.
  • PTP helpers for GigE: enable GevIEEE1588, wait for Master/Slave, latch timestamp, scheduled action command.
  • Multi-camera group API.
  • Direct GenICam feature passthrough for extra settings.

Quick start

from hgrabber_sdk import HikCamera

config = (
    HikCamera.builder("left")
    .usb("02K09720174")
    .settings(exposure_us=8000, gain=4.0, pixel_format="BayerRG8")
    .continuous()
    .build()
)

with HikCamera(config) as camera:
    frame = camera.grab(timeout_ms=1000)
    print(frame.width, frame.height, frame.pixel_format, frame.image.shape)

Software trigger

from hgrabber_sdk import HikCamera

config = (
    HikCamera.builder("top")
    .gige("192.168.10.20")
    .software_trigger()
    .settings(exposure_us=6000, gain=2.0)
    .build()
)

with HikCamera(config) as camera:
    frame = camera.grab()  # sends TriggerSoftware, then waits for the frame

Threaded streaming

from hgrabber_sdk import HikCamera

def on_frame(frame):
    print(frame.camera_name, frame.frame_number, frame.device_timestamp)

config = HikCamera.builder("preview").usb("SERIAL").continuous().build()

with HikCamera(config) as camera:
    camera.start_stream(on_frame)
    frame = camera.next_frame(timeout_ms=1000)

start_async and stop_async are kept as compatibility aliases for the threaded API.

Asyncio grabbing

All blocking SDK calls have asyncio wrappers. They run the MVS calls in worker threads, so MV_CC_GetImageBuffer, software trigger, PTP waits, and action commands do not block the event loop.

import asyncio
from hgrabber_sdk import HikCamera


async def main():
    config = (
        HikCamera.builder("cam")
        .gige("192.168.10.20")
        .software_trigger()
        .build()
    )

    async with HikCamera(config) as camera:
        frame = await camera.async_grab(timeout_ms=1000)
        print(frame.frame_number)


asyncio.run(main())

For continuous streaming into an asyncio.Queue:

async with HikCamera(config) as camera:
    frames = await camera.async_start_stream(queue_size=4)
    frame = await asyncio.wait_for(frames.get(), timeout=2.0)
    await camera.async_stop_stream(frames)

Native SDK callback

config = (
    HikCamera.builder("callback")
    .gige("192.168.10.21")
    .sdk_callback()
    .continuous()
    .build()
)

Callback mode registers MV_CC_RegisterImageCallBackEx before MV_CC_StartGrabbing.

Line trigger

config = (
    HikCamera.builder("io")
    .usb("SERIAL")
    .line_trigger("Line0", activation="RisingEdge", delay_us=0, line_debouncer_us=50)
    .build()
)

For line-scan cameras, set another trigger selector:

.line_trigger("Line1", selector="LineStart")

Multi-camera GigE action/PTP

from hgrabber_sdk import HikCamera, HikCameraGroup

left = (
    HikCamera.builder("left")
    .gige("192.168.10.21")
    .ptp(wait_synchronized=True)
    .action_trigger(device_key=1, group_key=1, group_mask=1)
    .build()
)
right = (
    HikCamera.builder("right")
    .gige("192.168.10.22")
    .ptp(wait_synchronized=True)
    .action_trigger(device_key=1, group_key=1, group_mask=1)
    .build()
)

with HikCameraGroup([left, right]) as cameras:
    cameras.start_async(queue_size=4)
    results = cameras.issue_action_after(delay_ticks=10_000_000)
    frames = {name: camera.next_frame(timeout_ms=2000) for name, camera in cameras.cameras.items()}

Asyncio group variant:

async with HikCameraGroup([left, right]) as cameras:
    queues = await cameras.async_start_stream(queue_size=4)
    await cameras.async_issue_action_after(delay_ticks=10_000_000)
    frames = {
        name: await asyncio.wait_for(queue.get(), timeout=2.0)
        for name, queue in queues.items()
    }

delay_ticks is in camera timestamp ticks. On most GigE Vision PTP setups this is nanoseconds, but validate this against the exact camera model before using scheduled actions in production.

Raw feature passthrough

Any extra GenICam feature can be passed through the builder:

config = (
    HikCamera.builder("cam")
    .gige("192.168.10.20")
    .feature("GammaEnable", True)
    .feature("Gamma", 0.7)
    .feature("AcquisitionBurstFrameCount", 3)
    .build()
)

String values are first attempted as enum symbols and then as string nodes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hgrabber_sdk-0.1.0.tar.gz (106.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hgrabber_sdk-0.1.0-py3-none-any.whl (61.2 kB view details)

Uploaded Python 3

File details

Details for the file hgrabber_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: hgrabber_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 106.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for hgrabber_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 642f6a68701b1bdf0c024c9d369f3fb42f4e5588eb0da326f132d4cd2fc9b8d2
MD5 18f509ad0ed96c3b2a2b54d189382897
BLAKE2b-256 b4fae9591d8db71a027afa1ad9a70398aabc8ac6f424840a68d989353c87f21e

See more details on using hashes here.

File details

Details for the file hgrabber_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hgrabber_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 61.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for hgrabber_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 80b681986f88467941ab8ddc640ea840a73047c4fd1ca33d7bbae7fafdca6c0b
MD5 12027f08e9b804b804482c469403840e
BLAKE2b-256 76b939e42d8dbd5eab951ca97dff92f9cd9a59b832b22ef57752ba3356c5b496

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page