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.

Подробная документация по использованию: docs/USAGE.md.

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
uv run python examples/gige_grab.py --ip 192.168.10.20

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.2.tar.gz (113.3 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.2-py3-none-any.whl (62.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hgrabber_sdk-0.1.2.tar.gz
  • Upload date:
  • Size: 113.3 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.2.tar.gz
Algorithm Hash digest
SHA256 bd01359e74fff5b7e98913f16c7558b487b57e25226b0b4915d3a29b5b2a2b76
MD5 ca678980a85a15fb55fedabb7d48117f
BLAKE2b-256 3b5973dfe38a8d1a4db5faadacafaf615fa83e698a51ec3d78eca0fc7fa2307a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: hgrabber_sdk-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 62.4 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d0fdc2fa7461eefd390298ac5748ee740cd0c4555c7d4456a644c9011b8c0b9a
MD5 1f8e9085822a1af50c59f356be63ca17
BLAKE2b-256 f453e8edb157a7d7095a05a63e55c5257dbe417051b2e8780dea85a3757107e1

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