Metadata-Version: 2.1
Name: fluxeem_driver
Version: 1.0.3
Summary: Fluxeem Event Camera Python SDK
Home-page: https://github.com/fluxeem/fluxeem_driver_python
Author: Fluxeem
Author-email: Fluxeem <info@fluxeem.com>
Maintainer-email: Fluxeem <info@fluxeem.com>
License: MIT
Project-URL: Homepage, https://github.com/fluxeem/fluxeem_driver_python
Project-URL: Documentation, https://github.com/fluxeem/fluxeem_driver_python/docs
Project-URL: Repository, https://github.com/fluxeem/fluxeem_driver_python
Project-URL: Issues, https://github.com/fluxeem/fluxeem_driver_python/issues
Keywords: event camera,camera,event,vision,sensor,fluxeem,neuromorphic
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.20.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov>=2.0; extra == "dev"
Requires-Dist: black>=22.0; extra == "dev"
Requires-Dist: flake8>=4.0; extra == "dev"
Requires-Dist: mypy>=0.950; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=4.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=1.0; extra == "docs"
Requires-Dist: sphinx-autodoc-typehints>=1.12; extra == "docs"
Provides-Extra: viz
Requires-Dist: opencv-python>=4.5; extra == "viz"
Requires-Dist: matplotlib>=3.4; extra == "viz"

<div align="center">
  <img src="docs/img/html_title.png" alt="Fluxeem Logo" width="260" />
</div>

<h1 align="center">Fluxeem Python SDK</h1>

<p align="center">
  面向 Fluxeem 事件相机的 Python SDK，提供设备连接、事件流采集、RAW 文件读取回放、工具参数控制与跨版本 wheel 打包能力。
</p>
<p align="center">
  <a href="https://fluxeem.github.io/fluxeem_driver/tutorial_python_index.html">在线文档</a> ·
  <a href="https://www.fluxeem.com">官网</a>
</p>
<p align="center">
  <a href="https://github.com/fluxeem/fluxeem_driver_python/releases"><img src="https://img.shields.io/github/v/release/fluxeem/fluxeem_driver_python" alt="Release"></a>
  <a href="https://github.com/fluxeem/fluxeem_driver_python/blob/main/pyproject.toml"><img src="https://img.shields.io/badge/license-MIT-blue" alt="License"></a>
  <a href="https://img.shields.io/badge/python-3.8%20to%203.13-brightgreen"><img src="https://img.shields.io/badge/python-3.8%20to%203.13-brightgreen" alt="Python"></a>
</p>

## 主要功能

- 事件相机发现、打开、关闭与生命周期管理。
- 实时事件流读取、回调注册、录制与配置导入导出。
- RAW 文件读取、时间/事件数定位、区间抽取。
- 基于 NumPy 的事件可视化与统计工具函数（事件帧转换、RGB渲染、统计计算）。
- 事件处理工具函数（时间/空间滤波、降采样、合并、事件率计算）。
- 事件文件保存与加载（文本格式）。
- 相机配置导入导出（JSON格式）。
- 固件升级支持。
- CMake + pybind11 构建体系，支持 Python 3.8 至 3.13。
- 支持 `cibuildwheel` 批量构建 Windows wheel。

## 使用简介

### 1. 安装并使用 SDK

如果你只需要在 Python 中快速接入 Fluxeem 事件相机，请优先使用现成 wheel 或直接安装源码包。

本仓库当前发布名与导入包名均为 `fluxeem_driver`。

安装示例：

```powershell
python -m pip install .\wheelhouse\fluxeem_driver-1.0.0-cp310-cp310-win_amd64.whl
```

导入示例：

```python
import fluxeem_driver
```

### 2. 安装 USB 驱动（首次使用时执行一次）

首次使用前，请下载并安装对应平台的 USB 驱动安装包：

- **GitHub Releases**：<https://github.com/fluxeem/fluxeem_driver/releases>
- **官网下载**：<https://fluxeem.com/downloads.html>

下载后按安装包内的说明完成安装即可，此步骤仅需执行一次。


### 3. 从源码构建使用

如果你需要修改 Python 包装层、调试 pybind11 绑定、维护跨版本 wheel 或参与发布流程，请继续阅读下面的构建说明。

- [构建要求](#构建要求)
- [Windows 源码编译](#windows-源码编译)
- [Linux 源码编译](#linux-源码编译)

## 仓库结构

| 目录 | 说明 |
| --- | --- |
| [fluxeem_driver/](fluxeem_driver/) | Python 包、包装器、类型标注与运行时库 |
| [src/](src/) | pybind11 绑定源码 |
| [examples/](examples/) | Python 示例程序（实时预览、回放、同步、工具控制） |
| [tests/](tests/) | 单元测试 |
| [tools/](tools/) | 构建辅助脚本（如 cibuildwheel bootstrap） |
| [wheelhouse/](wheelhouse/) | 本地构建 wheel 产物目录 |
| [CMakeLists.txt](CMakeLists.txt) | C++ 扩展构建配置 |
| [setup.py](setup.py) | setuptools 与 CMake 桥接入口 |
| [pyproject.toml](pyproject.toml) | 项目元数据与构建配置 |

## 支持平台与产物

| 平台 | 典型产物 | 说明 |
| --- | --- | --- |
| Windows x64 | `.whl` | 支持 `cp38` 到 `cp313`，可通过 `cibuildwheel` 批量构建 |
| Linux x86_64 | 源码安装 / wheel | 使用 CMake 与系统工具链构建扩展 |

## 构建要求

基础要求：

- Python 3.8 或更高版本。
- CMake 3.15 或更高版本。
- 支持 C++20 的编译器。
- 已安装 Fluxeem Driver SDK（`fluxeem_driver`）。
- pybind11 2.11 或更高版本。

可选依赖：

- OpenCV：运行实时可视化、回放相关示例。
- pytest：运行测试。
- cibuildwheel：批量构建多 Python 版本 wheel。

SDK 路径查找规则：

- 优先使用环境变量 `FLUXEEM_DRIVER_DIR`。
- Windows 默认回退路径：`C:\Program Files\fluxeem_driver`、`C:\Program Files (x86)\fluxeem_driver`。
- Linux 默认回退路径：`/usr/local`。

## 构建参数

| 参数 | 默认值 | 说明 |
| --- | --- | --- |
| `FLUXEEM_DRIVER_DIR` | 自动探测 | 指向已安装 `fluxeem_driver` SDK 根目录 |
| `FLUXEEM_BUNDLE_DRIVER_RUNTIME` | `ON` | 是否把 SDK 运行时库打包到 Python 包旁 |
| `CMAKE_GENERATOR` | 自动探测 | Windows 下可指定生成器（如 VS/Ninja） |

## Windows 源码编译

推荐在 PowerShell 中执行，先激活目标 Python 环境。

### 1. 安装构建依赖

```powershell
python -m pip install --upgrade pip setuptools wheel build cmake pybind11 ninja
```

### 2. 设置 SDK 路径（非默认安装目录时）

```powershell
$env:FLUXEEM_DRIVER_DIR = "C:\Program Files\fluxeem_driver"
```

### 3. 编译并安装

```powershell
python setup.py build_ext --inplace
python -m pip install .
```

### 4. 开发模式安装（可选）

```powershell
python setup.py build_ext --inplace
python -m pip install -e ".[dev,viz]"
```

## Linux 源码编译

以下命令以 Ubuntu 为例。

### 1. 安装系统依赖

```bash
sudo apt-get update
sudo apt-get install -y \
  build-essential \
  cmake \
  pkg-config \
  libusb-1.0-0-dev \
  python3-dev
```

### 2. 设置 SDK 路径

```bash
export FLUXEEM_DRIVER_DIR=/usr/local
```

### 3. 编译并安装

```bash
python -m pip install --upgrade pip setuptools wheel build cmake pybind11 ninja
python setup.py build_ext --inplace
python -m pip install .
```

## 快速开始

### 1. 实时读取相机事件

```python
import sys
import fluxeem_driver

camera_manager = fluxeem_driver.EvCameraService()
camera_descs = camera_manager.list_cameras()

for camera_desc in camera_descs:
    print(camera_desc)

if not camera_descs:
    raise RuntimeError("No camera found")

serial = sys.argv[1] if len(sys.argv) > 1 else camera_descs[0].serial
camera = camera_manager.open(serial)
if camera is None:
    raise RuntimeError(f"Failed to open camera: {serial}")

camera.start(batch_events_num=5000)
events = camera.get_events()
if events is not None:
    print(len(events), events.dtype.names)
camera.stop()
```

### 2. 读取 RAW 文件

```python
import fluxeem_driver

with fluxeem_driver.FileReader("recording.raw") as reader:
    if not reader.is_loaded():
        raise RuntimeError("Failed to load raw file")

    while not reader.reached_end():
        events = reader.get_events(10000)
        if events is not None and len(events):
            print(events[0])
```

### 3. 事件可视化与统计

```python
from fluxeem_driver import utils

frame = utils.events_to_frame(events, width=1280, height=720)
rgb = utils.events_to_rgb_frame(events, width=1280, height=720)
stats = utils.get_event_statistics(events)
print(stats["count"], stats["polarity_ratio"])
```

### 4. 使用回调函数

```python
import fluxeem_driver

camera_manager = fluxeem_driver.EvCameraService()
camera = camera_manager.open(camera_manager.list_cameras()[0].serial)

def on_event_batch(events):
    print(f"Received {len(events)} events")

# 注册回调（拷贝模式，回调外可安全使用 events）
callback_id = camera.register_event_batch_callback(on_event_batch)

# 或使用无拷贝模式（仅在回调内有效）
callback_id = camera.register_event_batch_callback_nocopy(on_event_batch)

camera.start(batch_events_num=5000)
# ... 处理事件 ...
camera.stop()

# 注销回调
camera.unregister_event_batch_callback(callback_id)
```

### 5. 工具参数控制

```python
import fluxeem_driver
from fluxeem_driver import ToolType

camera_manager = fluxeem_driver.EvCameraService()
camera = camera_manager.open(camera_manager.list_cameras()[0].serial)

# 获取工具
bias_tool = camera.get_tool(ToolType.TOOL_BIAS)
roi_tool = camera.get_tool_by_id("roi")

# 读取参数
value = bias_tool.get("param_name")

# 设置参数
result = bias_tool.set("param_name", new_value)
if result.ok:
    print("设置成功")
else:
    print(f"设置失败: {result.error.message}")
```

## API 参考

### 核心类型

| 类型 | 说明 |
| --- | --- |
| `Event2D` | 事件数据结构，包含 `x`, `y`, `polarity`, `timestamp` 字段 |
| `CameraDescription` | 相机描述信息，包含 `serial`, `product`, `manufacturer`, `vid`, `pid`, `interface_type`, `firmware_version` |
| `EvFileInfo` | 文件信息，包含 `width`, `height`, `max_events`, `start_timestamp`, `end_timestamp`, `serial_number`, `local_time` |
| `EvCameraStatisticInfo` | 相机统计信息，包含 `bandwidth_byte`, `events_count` |
| `EventTriggerIn` | 触发事件，包含 `id`, `polarity`, `timestamp` |

### 枚举类型

| 枚举 | 值 | 说明 |
| --- | --- | --- |
| `InterfaceType` | `USB`, `MIPI` | 接口类型 |
| `CameraStatus` | `STOPPED`, `STARTED` | 相机状态 |
| `StreamStatus` | `STOP`, `RUNNING`, `SUSPEND` | 流状态 |
| `ToolType` | `TOOL_BIAS`, `TOOL_TRIGGER_IN`, `TOOL_SYNC`, `TOOL_ANTI_FLICKER`, `TOOL_EVENT_TRAIL_FILTER`, `TOOL_EVENT_RATE_CONTROL`, `TOOL_ROI` | 工具类型 |
| `ParamType` | `INT`, `FLOAT`, `BOOL`, `STRING`, `ENUM` | 参数类型 |
| `BatchConditionType` | `NO_CONDITION`, `N_EVENTS`, `N_US` | 批次条件类型 |
| `LogLevelType` | `LOG_OFF`, `LOG_FATAL`, `LOG_ERROR`, `LOG_WARNING`, `LOG_INFO`, `LOG_DEBUG` | 日志级别 |
| `CameraType` | `EVK4`, `EVK5`, `DvsLume`, `RDK3` | 相机型号 |

### Camera 类

相机控制的主要接口。

#### 属性

| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `is_open` | `bool` | 相机连接是否打开 |

#### 连接管理

| 方法 | 说明 |
| --- | --- |
| `open(serial=None, auto_select_first=True)` | 打开相机连接，返回 `bool` |
| `open_camera(serial)` | 通过序列号打开相机 |
| `close()` | 关闭相机连接 |
| `is_connected()` | 检查相机是否物理连接 |
| `get_description()` | 获取相机描述信息 |
| `get_width()` | 获取传感器宽度 |
| `get_height()` | 获取传感器高度 |
| `get_resolution()` | 获取传感器分辨率 `(width, height)` |

#### 相机发现

| 方法 | 说明 |
| --- | --- |
| `update_cameras()` | 刷新已连接相机列表，返回数量 |
| `get_camera_descs()` | 获取已发现的相机描述列表 |
| `refresh()` | 刷新并返回相机描述列表 |
| `list_cameras()` | 返回当前已发现的相机描述列表 |

#### 事件流控制

| 方法 | 说明 |
| --- | --- |
| `start(batch_events_num=1000, batch_events_time=0)` | 启动事件流，返回 `bool` |
| `stop()` | 停止事件流，返回 `bool` |
| `set_batch_events_num(n)` | 设置每批事件数量 |
| `set_batch_events_time(n)` | 设置批时间窗口（微秒） |
| `get_next_batch()` | 获取下一批事件，返回 `numpy.ndarray` 或 `None` |
| `get_events()` | `get_next_batch()` 的别名 |
| `get_events_as_dict()` | 以字典形式获取事件 `{"x", "y", "polarity", "timestamp"}` |

#### 回调函数

| 方法 | 说明 |
| --- | --- |
| `register_event_batch_callback(callback)` | 注册事件回调（拷贝模式），返回回调 ID |
| `register_event_batch_callback_nocopy(callback)` | 注册事件回调（无拷贝模式，仅在回调内有效） |
| `unregister_event_batch_callback(callback_id)` | 注销事件回调 |
| `add_event_callback(callback)` | `register_event_batch_callback` 的别名 |
| `remove_event_callback(callback_id)` | `unregister_event_batch_callback` 的别名 |
| `register_trigger_in_callback(callback)` | 注册触发回调，返回回调 ID |
| `unregister_trigger_in_callback(callback_id)` | 注销触发回调 |
| `add_trigger_in_callback(callback)` | `register_trigger_in_callback` 的别名 |
| `remove_trigger_in_callback(callback_id)` | `unregister_trigger_in_callback` 的别名 |
| `set_statistics_callback(callback)` | 设置统计信息回调 |

#### 录制

| 方法 | 说明 |
| --- | --- |
| `start_recording(file_path)` | 开始录制事件到文件，返回 `bool` |
| `stop_recording()` | 停止录制，返回 `bool` |

#### 配置

| 方法 | 说明 |
| --- | --- |
| `export_camera_config(json_path)` | 导出相机配置到 JSON 文件 |
| `import_camera_config(json_path)` | 从 JSON 文件导入相机配置 |
| `export_config(json_path)` | `export_camera_config` 的别名 |
| `load_config(json_path)` | `import_camera_config` 的别名 |

#### 工具控制

| 方法 | 说明 |
| --- | --- |
| `get_tools_info()` | 获取所有可用工具信息列表 |
| `get_tool(tool)` | 通过 `ToolType` 枚举或工具 ID 字符串获取工具 |
| `get_tool_by_id(tool_id)` | 通过工具 ID 获取工具（如 `"bias"`, `"roi"`） |
| `get_tool_by_name(tool_name)` | `get_tool_by_id` 的别名（已弃用） |
| `firmware_upgrade(image_path)` | 执行固件升级 |

### CameraTool 类

工具参数控制接口。

| 方法 | 说明 |
| --- | --- |
| `info()` | 获取工具信息 `ToolInfo` |
| `schema()` | 获取参数描述符列表 `List[ParamDescriptor]` |
| `get(name)` | 获取参数值 |
| `set(name, value)` | 设置参数值，返回 `ParamResult` |
| `apply(values)` | 批量设置参数 |
| `to_json()` | 导出为 JSON |
| `from_json(json_obj)` | 从 JSON 导入 |

### ParamDescriptor 类

参数描述符。

| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `str` | 参数名 |
| `type` | `ParamType` | 参数类型 |
| `description` | `str` | 参数描述 |
| `unit` | `str` | 单位 |
| `constraint` | `ParamConstraint` | 参数约束 |

### ParamConstraint 类

参数约束。

| 方法 | 说明 |
| --- | --- |
| `get_int_range()` | 获取整数范围 `ParamIntRange` |
| `get_float_range()` | 获取浮点范围 `ParamFloatRange` |
| `get_bool_def()` | 获取布尔默认值 `ParamBoolDef` |
| `get_enum_def()` | 获取枚举定义 `ParamEnumDef` |
| `get_string_def()` | 获取字符串默认值 `ParamStringDef` |

### ParamResult 类

参数操作结果。

| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `ok` | `bool` | 操作是否成功 |
| `error` | `ParamError` | 错误信息 |

### EvCameraService 类

相机管理器。

| 方法 | 说明 |
| --- | --- |
| `refresh()` | 刷新已连接相机，返回数量 |
| `list()` | 返回已发现的相机描述列表 |
| `list_cameras()` | 刷新并返回相机描述列表 |
| `open(serial)` | 打开相机，返回 `Camera` 或 `None` |

### FileReader 类

RAW 文件读取器。

#### 属性

| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `file_path` | `str` | 文件路径 |

#### 文件操作

| 方法 | 说明 |
| --- | --- |
| `load()` | 打开并索引文件，返回 `bool` |
| `close()` | 释放文件读取器 |
| `is_loaded()` | 检查文件是否已加载 |
| `get_resolution()` | 获取传感器分辨率 `(width, height)` |
| `get_file_info()` | 获取文件信息 `EvFileInfo` |
| `get_start_timestamp()` | 获取起始时间戳（微秒） |
| `get_end_timestamp()` | 获取结束时间戳（微秒） |
| `get_max_events()` | 获取事件总数 |
| `reached_end()` | 检查是否已读取所有事件 |
| `reset()` | 重置读取器到文件开头 |

#### 事件读取

| 方法 | 说明 |
| --- | --- |
| `get_events(n=1000)` | 读取下 n 个事件，返回 `numpy.ndarray` 或 `None` |
| `get_events_in_time_window(interval)` | 读取指定时间窗口内的事件（微秒） |
| `get_events_as_dict(n=1000)` | 以字典形式读取事件 |
| `seek_time(timestamp)` | 跳转到指定时间戳 |
| `seek_n_events(n)` | 跳转到第 n 个事件 |
| `get_current_timestamp()` | 获取当前位置的时间戳 |
| `get_current_event_num()` | 获取当前位置的事件索引 |
| `extract_events(start_time, end_time, output_path)` | 提取指定时间范围的事件到文件 |
| `get_decode_statistics()` | 获取解码统计信息 `(bandwidth_bytes, events_count)` |

### Utils 工具函数

#### 事件可视化

| 函数 | 说明 |
| --- | --- |
| `events_to_frame(events, width, height, polarity=None)` | 将事件累积为 2D 浮点帧 |
| `events_to_rgb_frame(events, width, height, normalize=True)` | 渲染为 RGB 图像（红=ON，蓝=OFF） |

#### 事件统计

| 函数 | 说明 |
| --- | --- |
| `get_event_statistics(events)` | 计算基本统计信息 |
| `calculate_event_rate(events, window_size=1000)` | 计算事件率（事件/秒） |

#### 事件滤波

| 函数 | 说明 |
| --- | --- |
| `filter_events_by_time(events, start_time, end_time)` | 按时间范围过滤事件 |
| `filter_events_by_roi(events, x_min, x_max, y_min, y_max)` | 按矩形区域过滤事件 |

#### 事件处理

| 函数 | 说明 |
| --- | --- |
| `downsample_events(events, factor=2)` | 空间降采样事件 |
| `merge_event_batches(batches)` | 合并多个事件批次 |

#### 文件 I/O

| 函数 | 说明 |
| --- | --- |
| `save_events_to_file(events, file_path, file_info=None)` | 保存事件到文本文件 |
| `load_events_from_file(file_path)` | 从文本文件加载事件，返回 `(events, metadata)` |

### Logger 类

日志控制。

| 方法 | 说明 |
| --- | --- |
| `Logger.instance()` | 获取日志实例 |
| `set_log_level(level)` | 设置日志级别 |
| `get_log_level()` | 获取当前日志级别 |
| `set_log_file(log_file)` | 设置日志文件 |

### 辅助函数

| 函数 | 说明 |
| --- | --- |
| `get_version()` | 获取 SDK 版本号 |
| `get_build_date()` | 获取构建日期 |
| `tool_type_to_string(type)` | 工具类型转字符串 |
| `tool_id(type)` | 获取工具 ID |
| `param_type_to_string(type)` | 参数类型转字符串 |

## 示例程序

运行示例：

```bash
python examples/live_viewer.py
python examples/callback_event_monitor.py
python examples/tool_control.py
python examples/hardware_sync.py
python examples/file_playback.py recording.raw
python examples/slow_motion.py recording.raw
```

OpenCV 依赖安装：

```bash
python -m pip install opencv-python
```

## 测试

运行内置单元测试：

```bash
python -m unittest discover -s tests -v
```

或使用 pytest：

```bash
python -m pytest
```

## 常见问题

### 导入报错：`No module named fluxeem_driver.fluxeem_core`

通常是 C++ 扩展未正确编译或未安装，请重新执行：

```bash
python setup.py build_ext --inplace
python -m pip install .
```

### 构建报错：`fluxeem_driver SDK was not found`

请确认：

- 已安装 Fluxeem Driver SDK。
- `FLUXEEM_DRIVER_DIR` 指向 SDK 安装根目录。
- SDK 目录下存在 `share/cmake/fluxeem_driver`。

### 找不到相机设备

请确认设备连接、驱动安装和权限设置；若设备已被其他进程占用，请先关闭占用进程再重试。

### OpenCV 导入异常

请确认运行示例的 Python 环境与安装 `opencv-python` 的环境一致。

## 许可证

本项目使用 MIT 协议发布。

## 联系方式

- 项目主页：https://github.com/fluxeem/fluxeem_driver_python
- 问题反馈：https://github.com/fluxeem/fluxeem_driver_python/issues
- 联系邮箱：info@fluxeem.com
