5 SDK开发指南
本章介绍SDK概述、功能说明和开发示例。
5.1 SDK概述
介绍SDK的定义和组成,帮助用户更好的了解SDK。
5.1.1 SDK 简介
ED-AIC1000的SDK是一组软件工具开发包(Software Development Kit),给用户提供上层应用所需的接口,便于对Camera进行二次开发。
ED-AIC1000的SDK功能包含12-Pin M12接口中的状态指示灯的控制、报警指示灯的控制、1路DO的控制、RGB灯光、灯源、工作模式、增益、曝光时间、图像处理、自动变焦和解码的控制。
SDK在整个Camera系统中的位置如下图所示。

5.1.2 SDK组成
Camera的SDK是由多个头文件和库文件组成的,具体文件名和安装路径如下表。
| 功能类型 | 文件类型 | 文件名 | 安装路径 |
|---|---|---|---|
| IO控制 | 头文件 | io.h | /usr/include/eda/ |
| 库文件(C++) | libeda_io.so | /usr/lib/ | |
| 库文件(Python) | libedaio.so | /lib/python3/dist-packages/ | |
| Camera Sensor控制 | 头文件 | camera.h cameramanger.h | /usr/include/eda/ |
| 库文件(C++) | libeda_camera.so | /usr/lib/ | |
| 库文件(Python) | libedacamera.so | /lib/python3/dist-packages/ |
在开发过程中用户可以根据实际需要实现的功能,参考下文对应的功能代码来完成上层应用的开发。
5.2 功能说明
本章介绍各项功能对应代码的编写方法,帮助用户编写上层应用所需要的代码。
5.2.1 I/O控制(C++)
本节介绍指示灯控制、输出控制、灯光控制、对焦位置控制和相机拍照模式控制等的具体操作。
5.2.1.1 流程图

5.2.1.2 获取实例并初始化
在操作I/O前需要先获取I/O实例并对实例进行初始化,操作步骤如下。
- 获取I/O实例。
eda::Edalo* em = eda::Edalo::getInstance();
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 对实例进行初始化。
em->setup();
| 参数 | 返回值 |
|---|---|
| 无 | void |
5.2.1.3 控制I/O状态
通过I/O来控制状态指示灯的点亮/熄灭、报警指示灯的点亮/熄灭和1路输出信号的使能/禁用。
前提条件:
已完成实例的初始化。
操作说明:
- 控制状态指示灯
em->openWorkLed(); // 打开工作指示灯
em->closeWorkLed(); // 关闭工作指示灯
| 参数 | 返回值 |
|---|---|
| 无 | void |
- 控制警报指示灯
em->openAlarmLed(); // 打开报警指示灯
em->closeAlarmLed(); // 关闭报警指示灯
| 参数 | 返回值 |
|---|---|
| 无 | void |
- 控制1路输出信号
em->setDo1High(); // 设置output1输出为高
em->setDo1Low(); // 设置output1输出为低
| 参数 | 返回值 |
|---|---|
| 无 | void |
5.2.1.4 控制灯光
Camera侧面灯和区域灯均可控制。
前提条件:
已完成实例的初始化。
操作说明:
● 控制侧灯颜色
em->setRgbLight(LightColor light);
| 参数 | 返回值 |
|---|---|
| LightColor::Off:关闭 LightColor::Red:红色 LightColor::Green:绿色 LightColor::Blue:蓝色 LightColor::Yellow:黄色 LightColor::White:白色 | void |
● 控制区域灯源,分为3个区域(上方、中间和下方),每一个区域均支持独立控制。
- 开启区域光源(默认状态为开启状态)
em->enableLightSection(LightSection section);
| 参数 | 返回值 |
|---|---|
| LightSection::Bottom:下方区域灯源 LightSection::Middle:中间区域灯源 LightDection::Top:上方区域灯源 |
|
- 关闭区域光源
em->disableLightSection(LightSection section);
| 参数 | 返回值 |
|---|---|
| LightSection::Bottom:下方区域灯源 LightSection::Middle:中间区域灯源 LightDection::Top:上方区域灯源 |
|
提示
- 区域灯源的使能/禁用不是打开/关闭灯源,灯源与摄像头是联动的,只有当灯源已使能且摄像头打开的条件下灯源才会亮。
控制区域灯源亮度
em->setBrightnessValue(brightness);
| 参数 | 返回值 |
|---|---|
|
|
5.2.1.5 控制对焦模组
Camera默认配备马达自动对焦模组,提供自动对焦功能。
- 初始化马达对焦模块
em->initMotorVfm();
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 调远马达对焦模块的焦距
em->setMotorVfmFar(int distance);
| 参数 | 返回值 |
|---|---|
|
|
- 调近马达对焦模块的焦距
em->setMotorVfmNear(int distance);
| 参数 | 返回值 |
|---|---|
|
|
5.2.1.6 控制相机
Camera拍照的模式支持设置,包含连续模式、软/硬触发模式和软件触发模式。
- 设置连续拍照模式下,连续触发的时间间隔
em->setContinuousInterval(int ms);
| 参数 | 返回值 |
|---|---|
|
|
提示
连续触发的时间间隔应根据当前曝光时间合理配置;曝光时间越长,建议设置越大的连续触发时间间隔。
- 若连续触发时间间隔较小,但实际曝光时间偏大,设备可能在上一帧曝光尚未完成时收到新的触发信号,从而导致触发异常、丢帧或图像采集失败。
- 建议满足:实际曝光时间 ≤ 连续触发间隔 + 1 ms。
在触发时间间隔固定的情况下,实际采集帧率并非随曝光时间连续变化,而是受实际硬件影响呈阶梯式变化。适当减小曝光时间有助于提升实际采集帧率,但达到当前帧率档位后,继续减小曝光时间通常不会带来进一步提升。
- 设置软\硬触发模式下,单次触发相机拍摄次数
em->setTriggerNum(int count);
| 参数 | 返回值 |
|---|---|
|
|
- 设置为软件触发模式,兼容软/硬触发模式
em->callTrigger();
| 参数 | 返回值 |
|---|---|
| 无 | void |
5.2.1.7 代码示例
IO控制Class(C++)
typedef void (*IoTrigger)(int level);
class EdaIo{
public:
static EdaIo* getInstance();
static void close_io();
~EdaIo();
/**
* @brief 打开工作指示灯
*
*/
void openWorkLed();
/**
* @brief 关闭工作指示灯
*
*/
void closeWorkLed();
/**
* @brief 打开alarm 指示灯
*
*/
void openAlarmLed();
/**
* @brief 关闭alarm 指示灯
*
*/
void closeAlarmLed();
/**
* @brief
*
* @param section: LightSection::Top 上方区域, LightSection::Middle 中间区域, LightSection::Bottom 下方区域
* @return int
*/
int enableLightSection(LightSection section);
/**
* @brief
*
* @param section LightSection::Top 上方区域, LightSection::Middle 中间区域, LightSection::Bottom 下方区域
* @return int
*/
int disableLightSection (LightSection section);
/**
* @brief 触发相机
*/
void callTrigger();
/**
* @brief 设置连续触发时间间隔
*
* @param intervalMs 间隔时间,单位毫秒
* @return int
*/
int setContinuousInterval(int intervalMs);
/**
* @brief 设置触发次数
*
* @param count 触发次数
* @return int
*/
int setTriggerNum(int count);
/**
* @brief 初始化马达对焦模组
*
* @return int
*/
int initMotorVfm();
/**
* @brief 调远马达对焦模块的焦距
*
* @param distance 0~46000
* @return int
*/
int setMotorVfmFar(int distance);
/**
* @brief 调近马达对焦模块的焦距
*
* @param distance 0~46000
* @return int
*/
int setMotorVfmNear(int distance);
/**
* @brief 设置output1 输出为高
*
*/
void setDo1High();
/**
* @brief 设置output1 输出为低
*
*/
void setDo1Low();
/**
* @brief set RGB light
*
* @param light LightColor::Red 红色, LightColor::Green 绿色, LightColor::Blue 蓝色, LightColor::Yellow 黄色, LightColor::White 白色, LightColor::Off 关闭
* @return void
*/
void setRgbLight(LightColor light);
/**
* @brief
*
* @param brightness 光源亮度,范围0~100,默认亮度50
* @return int
*/
int setBrightnessValue(int value);
/**
* @brief
*
* @param mode Mode::Continuous 连续模式,Mode::Software 软触发模式, Mode::IoLevelUp 上升沿触发,Mode::IoLevelDown 下降沿触发,Mode::IoLevelBoth Level触发
* @return int
*/
int setWorkMode(Mode mode);
/**
* @brief 初始化IO 设置
*
*/
void setup();
};
5.2.2 I/O控制(Python)
本节介绍指示灯控制、输出控制、灯光控制、对焦位置控制和相机拍照模式控制等的具体操作。
5.2.2.1 流程图

5.2.2.2 导入模块
在操作I/O前需要先导入模块。
from libedaio import Edalo, registerInput, registerTrigger, registerTune
5.2.2.3 获取实例并初始化
在导入模块后需要先获取I/O实例并对实例进行初始化,操作步骤如下。
- 获取IO实例。
edalo = Edalo.getInstance()
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 对实例进行初始化。
edalo.setup()
| 参数 | 返回值 |
|---|---|
| 无 | None |
5.2.2.4 控制I/O状态
通过I/O来控制状态指示灯的点亮/熄灭、报警指示灯的点亮/熄灭和1路输出信号的使能/禁用。
前提条件:
已完成实例的初始化。
操作说明:
- 控制状态指示灯
edalo.openWorkLed() # 打开工作指示灯
edalo.closeWorkLed() # 关闭工作指示灯
| 参数 | 返回值 |
|---|---|
| 无 | None |
- 控制警报指示灯
edalo.openAlarmLed() # 打开报警指示灯
edalo.closeAlarmLed() # 关闭报警指示灯
| 参数 | 返回值 |
|---|---|
| 无 | None |
- 控制1路输出信号
edalo.setDo1High() # 设置第一路输出为高
edalo.setDo1Low() # 设置第一路输出为低
| 参数 | 返回值 |
|---|---|
| 无 | None |
5.2.2.5 控制灯光
Camera侧面灯和区域灯均可控制。
前提条件:
已完成实例的初始化。
操作说明:
● 控制侧灯颜色
edalo.setRgbLight(LightColor.Red)
| 参数 | 返回值 |
|---|---|
| LightColor.Off:关闭 LightColor.Red:红色 LightColor.Green:绿色 LightColor.Blue:蓝色 LightColor.Yellow:黄色 LightColor.White:白色 | None |
● 控制区域灯源,分为3个区域(上方、中间和下方),每一个区域均支持独立控制。
- 开启区域光源(默认状态为开启状态)
edalo.enableLightSection(LightSection.Top)
| 参数 | 返回值 |
|---|---|
| LightSection.Bottom:下方区域灯源 LightSection.Middle:中间区域灯源 LightSection.Top:上方区域灯源 |
|
- 关闭区域光源
edalo.disableLightSection(LightSection.Top)
| 参数 | 返回值 |
|---|---|
| LightSection.Bottom:下方区域灯源 LightSection.Middle:中间区域灯源 LightSection.Top:上方区域灯源 |
|
提示
- 区域灯源的使能/禁用不是打开/关闭灯源,灯源与摄像头是联动的,只有当灯源已使能且摄像头打开的条件下灯源才会亮。
控制区域灯源亮度
edalo.setBrightnessValue(brightness)
| 参数 | 返回值 |
|---|---|
|
|
5.2.2.6 控制对焦模组
Camera默认配备马达自动对焦模组,提供自动对焦功能。
- 初始化马达对焦模块
edalo.initMotorVfm()
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 调远马达对焦模块的焦距
edalo.setMotorVfmFar(distance)
| 参数 | 返回值 |
|---|---|
|
|
- 调近马达对焦模块的焦距
edalo.setMotorVfmNear(distance)
| 参数 | 返回值 |
|---|---|
|
|
5.2.2.7 控制相机
Camera拍照的模式支持设置,包含连续模式、软/硬触发模式和软件触发模式。
- 设置连续拍照模式下,连续触发的时间间隔
edalo.setContinuousInterval(ms)
| 参数 | 返回值 |
|---|---|
|
|
提示
连续触发的时间间隔应根据当前曝光时间合理配置;曝光时间越长,建议设置越大的连续触发时间间隔。
- 若连续触发时间间隔较小,但实际曝光时间偏大,设备可能在上一帧曝光尚未完成时收到新的触发信号,从而导致触发异常、丢帧或图像采集失败。
- 建议满足:实际曝光时间 ≤ 连续触发间隔 + 1 ms。
在触发时间间隔固定的情况下,实际采集帧率并非随曝光时间连续变化,而是受实际硬件影响呈阶梯式变化。适当减小曝光时间有助于提升实际采集帧率,但达到当前帧率档位后,继续减小曝光时间通常不会带来进一步提升。
- 设置软/硬触发模式下,单次触发相机拍摄次数
edalo.setTriggerNum(count)
| 参数 | 返回值 |
|---|---|
|
|
- 设置为软件触发模式,兼容软/硬触发模式
edalo.callTrigger()
| 参数 | 返回值 |
|---|---|
| 无 | None |
5.2.2.8 代码示例
IO控制(Python3)
from libedaio import Edalo, registerInput, registerTrigger, registerTune
from libedaio import LightSection, Mode, LightColor
def func_trigger(v):
print("[Debug] Trigger: trigger button!", v)
eda = Edalo.getInstance() # 获取IO控制实例
eda.setup() # 初始化
eda.openWorkLed() # 设置状态指示灯
eda.openAlarmLed() # 打开警告指示灯
# eda.closeAlarmLed() # 关闭警告指示灯
eda.setDo1High() # 设置第一路输出
eda.setRgbLight(LightColor.Red) # 设置侧灯
5.2.3 Camera Sensor控制(C++)
本节介绍打开摄像头、设置相机曝光时间和设置相机增益等的具体操作。
5.2.3.1 流程图

5.2.3.2 操作步骤
在操作Camera之前,需要先获取I/O实例并初始化,再进行如下操作。
- 获取实例
eda::Camera* t_camera = eda::loadDefault();
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 查询Sensor类型。
t_camera->getName()
| 参数 | 返回值 |
|---|---|
| 无 | eda::CameraName::SC132GS |
- 打开摄像头并设置分辨率。
t_camera->open(width, height);
| 参数 | 返回值 |
|---|---|
|
|
提示
- 调用前必须先成功获取I/O库实例并完成初始化。
- 函数会根据传入的 width和 height设定图像采集的目标尺寸。
- 由于底层传感器和驱动存在对齐限制,实际生效的参数会自动进行向下对齐处理:
- 宽度对齐:按 32像素 边界向下对齐。
- 高度对齐:按 16像素 边界向下对齐。
- 对齐后的采集区域将自动居中放置在传感器画面中。
- 最终输出的图像分辨率将等于对齐后的尺寸,该尺寸可能略小于或等于传入的参数值。
- 设置增益和曝光参数。
- 设置增益
t_camera->setGain(gain);
| 参数 | 返回值 |
|---|---|
|
|
- 设置曝光
t_camera->setExposure(exposure);
| 参数 | 返回值 |
|---|---|
|
|
提示
- 实际曝光时间 = 曝光值 × rowTime,SC132gs.rowTime = 6.17us,由于传感器硬件公差,实际生效值可能存在轻微偏差。
- 当前可配置的最大曝光时间受限于相机的工作模式及触发间隔(实际曝光时间 ≤ 连续触发间隔 + 1 ms)。
- 通过回调方式获取摄像头数据。
t_camera->registerImageHandler(image_callback);
| 参数 | 返回值 |
|---|---|
| image_callback:用户定义的图像数据回调函数 |
|
提示
回调函数中,推荐只获取数据不处理逻辑。
- 获取图像数据(获取一帧图像)。
t_camera->getImageData(char* img_buff, int img_len);
| 参数 | 返回值 |
|---|---|
|
|
提示
- 获取相机最近采集的一帧图像数据,并将其复制到用户提供的缓冲区。
- 调用前应确保相机已开始采集,并且已经获取到至少一帧图像数据。
- 仅获取,不触发相机。
5.2.3.3 代码示例
typedef int (*img_Callback)(char* img_buff, int img_len);
enum CameraName {
SC132GS
};
class Camera {
public:
/**
* @brief 初始化摄像头
* @param width
* @param height
* @return int
*/
virtual int open(int width, int height) = 0;
/**
* @brief 关闭摄像头
* @return int
*/
virtual int close() = 0;
/**
* @brief 设置曝光时间
* @param exp_value
* @return int
*/
virtual int setExposure(int exp_value) = 0;
/**
* @brief 获取曝光时间
* @param exp_value
* @return int
*/
virtual int getExposure(int* exp_value) = 0;
/**
* @brief 设置增益
* @param gain_value
* @return int
*/
virtual int setGain(int gain_value) = 0;
/**
* @brief 获取增益
* @param gain_value
* @return int
*/
virtual int getGain(int* gain_value) = 0;
/**
* @brief 注册回调函数,获取图像数据
* @param callback
* @return int
*/
virtual int registerImageHandler(img_Callback callback) = 0;
virtual CameraName name() = 0;
};
5.2.4 Camera Sensor控制(Python)
本节介绍导入模块、打开摄像头、设置相机曝光时间和设置相机增益等的具体操作。
5.2.4.1 流程图

5.2.4.2 操作步骤
在操作Camera之前,需要先导入模块再获取I/O实例并初始化,具体操作如下。
- 导入模块。
from libedacamera import EdaCamera
- 获取Camera实例。
eda = EdaCamera.loadDefault()
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 查询Sensor类型。
eda.getName()
| 参数 | 返回值 |
|---|---|
| 无 | eda.CameraName.SC132GS |
- 打开摄像头并设置分辨率。
ret = eda.open(t_width, t_height)
| 参数 | 返回值 |
|---|---|
|
|
提示
- 调用前必须先成功获取I/O库实例并完成初始化。
- 函数会根据传入的 width和 height设定图像采集的目标尺寸。
- 由于底层传感器和驱动存在对齐限制,实际生效的参数会自动进行向下对齐处理:
- 宽度对齐:按 32像素 边界向下对齐。
- 高度对齐:按 16像素 边界向下对齐。
- 对齐后的采集区域将自动居中放置在传感器画面中。
- 最终输出的图像分辨率将等于对齐后的尺寸,该尺寸可能略小于或等于传入的参数值。
- 设置增益和曝光参数。
- 设置增益
eda.setGain(t_gain)
| 参数 | 返回值 |
|---|---|
|
|
- 设置曝光
eda.setExposure(t_exposure)
| 参数 | 返回值 |
|---|---|
|
|
提示
- 实际曝光时间 = 曝光值 × rowTime,SC132gs.rowTime = 6.17us,由于传感器硬件公差,实际生效值可能存在轻微偏差。
- 当前可配置的最大曝光时间受限于相机的工作模式及触发间隔(实际曝光时间 ≤ 连续触发间隔 + 1 ms)。
- 通过回调方式获取摄像头数据。
eda.registerImageHandler(func_image_data)
| 参数 | 返回值 |
|---|---|
| func_image_data:用户定义的图像数据回调函数 |
|
提示
回调函数中,推荐只获取数据不处理逻辑。
- 获取图像数据(获取一帧图像)。
eda.getImageData(img_buff, img_len)
| 参数 | 返回值 |
|---|---|
|
|
提示
- 获取相机最近采集的一帧图像数据,并将其复制到用户提供的缓冲区。
- 调用前应确保相机已开始采集,并且已经获取到至少一帧图像数据。
- 仅获取,不触发相机。
5.2.4.3 代码示例
PYBIND11_MODULE(libedacamera, m) {
m.doc() = "EDATec Camera";
m.add_object("_cleanup", py::capsule(cleanup_callback));
py::enum_<eda::ImageEncode>(m, "ImageEncode")
.value("GRAY", eda::ImageEncode::GRAY)
.value("COLOR", eda::ImageEncode::COLOR);
auto pyEdaCamera = py::class_<EdaCamera, std::shared_ptr<EdaCamera>>(m, "EdaCamera");
pyEdaCamera.def("open", &EdaCamera::open)
.def_static("loadDefault", []() {
if(!gEda){
gEda = new EdaCamera(eda::loadDefault());
}
return gEda;
})
.def("close", &EdaCamera::close)
.def("setExposure", &EdaCamera::setExposure)
.def("getExposure", &EdaCamera::getExposure)
.def("setExposureRange", &EdaCamera::setExposureRange)
.def("getExposureRange", &EdaCamera::getExposureRange)
.def("setGain", &EdaCamera::setGain)
.def("getGain", &EdaCamera::getGain)
.def("getName", &EdaCamera::getName)
.def("registerImageHandler", &EdaCamera::registerImageHandler,py::arg("callback"))
.def("getImageData", [](EdaCamera *self, py::buffer img_buff, int img_len){
py::buffer_info info = img_buff.request();
char *img_data = static_cast<char*>(info.ptr);
return self->getImageData(img_data, img_len);
}, py::arg("img_buff"), py::arg("img_len"))
.def("setImageEncode", &EdaCamera::setImageEncode, py::arg("encode"))
.def("getImageEncode", &EdaCamera::getImageEncode)
.def("setWhiteBalance", &EdaCamera::setWhiteBalance)
.def("getWhiteBalance", &EdaCamera::getWhiteBalance);
}
5.2.5 Decoder (C++)
本节介绍设置码制、设置读码时长和设置最大解码数量等的具体操作。
5.2.5.1 流程图

5.2.5.2 操作步骤
在操作读码之前,需要先初始化读码器,再设置读码参数。
- 初始化读码器。
initDecoder();
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 设置码制,默认支持的码制为Code128、Data Matrix和QR,码制支持按需设置。
| 代码 | 描述 |
|---|---|
| int enableDecoderC128() | 使能Code128码制 |
| int disableDecoderC128() | 禁用Code128码制 |
| int enableDecoderC93() | 使能Code93码制 |
| int disableDecoderC93() | 禁用Code93码制 |
| int enableDecoderC39() | 使能Code39码制 |
| int disableDecoderC39() | 禁用Code39码制 |
| int enableDecoderI25() | 使能Interleaved 2 of 5码制 |
| int disableDecoderI25() | 禁用Interleaved 2 of 5码制 |
| int enableDecoderUpc() | 使能UPC码制 |
| int disableDecoderUpc() | 禁用UPC码制 |
| int enableDecoderEan() | 使能EAN码制 |
| int disableDecoderEan() | 禁用EAN码制 |
| int enableDecoderQr() | 使能QR码制 |
| int disableDecoderQr() | 禁用QR码制 |
| int enableDecoderDm() | 使能Data Matrix码制 |
| int disableDecoderDm() | 禁用Data Matrix码制 |
| int enableDecoderPdf() | 使能PDF417码制 |
| int disableDecoderPdf() | 禁用PDF417码制 |
| int enableDecoderAll() | 使能所有码制 |
| int disableDecoderAll() | 禁用所有码制 |
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 设置解码时长。
int setDecoderTimeout(int ms);
| 参数 | 返回值 |
|---|---|
|
|
提示
运行解码函数的时间超过解码时长设定值后会退出解码。
- 设置最大解码数量。
int setDecoderResultMax(int max);
| 参数 | 返回值 |
|---|---|
|
|
提示
运行解码函数时,解码的数量超过设定值后会退出解码。
- 配置相似条码使能。
int disableIdenticalSymbols(int enable);
| 参数 | 返回值 |
|---|---|
|
|
提示
条形码在受损情况下可能会被识别为多个相同的码,会输出多个重复的内容,通过设置可以关闭或者使能。
- 运行解码函数。
int decoder(uint8_t* image, int width, int height, std::vector<DEC_RESULT>&results);
| 参数 | 返回值 |
|---|---|
|
|
提示
从图像数据中解码并输出条码类型、条码内容和条码的位置,返回值为解码的数量。其中返回结果DEC_RESULT字段说明:
code_length:条码内容长度code_string:条码内容字符串center_x:目标中心点X坐标center_y:目标中心点Y坐标code_type:枚举类型,例如 CODE_TYPE_QRbounds:4个角点坐标列表
示例:
static const std::unordered_map<CodeType, const char*> code_type_names = {
{CODE_TYPE_C128, "C128"},
{CODE_TYPE_C93, "C93"},
{CODE_TYPE_C39, "C39"},
{CODE_TYPE_I25, "I25"},
{CODE_TYPE_UPC, "UPC"},
{CODE_TYPE_EAN, "EAN"},
{CODE_TYPE_QR, "QR"},
{CODE_TYPE_DM, "DM"},
{CODE_TYPE_PDF, "PDF"},
};
std::vector<DEC_RESULT> results_vec;
const int count = decoder(gray.data(), width, height, results_vec);
std::cout << "decode_count=" << count << "\n";
for (int i = 0; i < count && i < 16; ++i) {
const auto& r = results_vec[i];
std::cout << "[" << i << "]";
std::cout << "type=" << code_type_names.at(r.code_type);
std::cout << ", text=" << r.code_string;
std::cout << ", center=(" << r.center_x << "," << r.center_y << ")\n";
std::cout << " bounds=";
for (int j = 0; j < 4; ++j) {
std::cout << "(" << r.bounds.point[j].x << "," << r.bounds.point[j].y << ")";
if (j < 3) {
std::cout << ",";
}
}
std::cout << "\n";
}
- 关闭读码器。
int destroyDecoder();
| 参数 | 返回值 |
|---|---|
| 无 |
|
5.2.5.3 代码示例
#ifdef __cplusplus
extern "C" {
#endif
enum CodeType {
CODE_TYPE_C128 = 4,
CODE_TYPE_C93 = 3,
CODE_TYPE_C39 = 2,
CODE_TYPE_I25 = 5,
CODE_TYPE_UPC = 11,
CODE_TYPE_EAN = 12,
CODE_TYPE_QR = 18,
CODE_TYPE_DM = 15,
CODE_TYPE_PDF = 17,
};
typedef struct DEC_POINT {
int x;
int y;
} DEC_POINT;
typedef struct DEC_BOUNDS {
DEC_POINT point[4];
} DEC_BOUNDS;
typedef struct DEC_RESULT {
int code_length;
char code_string[512];
int center_x;
int center_y;
CodeType code_type;
DEC_BOUNDS bounds;
} DEC_RESULT;
int initDecoder(void);
int decoder(uint8_t* image, int width, int height, std::vector<DEC_RESULT>& results);
int destroyDecoder(void);
int enableDecoderC128();
int disableDecoderC128();
int enableDecoderC93();
int disableDecoderC93();
int enableDecoderC39();
int disableDecoderC39();
int enableDecoderI25();
int disableDecoderI25();
int enableDecoderUpc();
int disableDecoderUpc();
int enableDecoderEan();
int disableDecoderEan();
int enableDecoderQr();
int disableDecoderQr();
int enableDecoderDm();
int disableDecoderDm();
int enableDecoderPdf();
int disableDecoderPdf();
int enableDecoderAll();
int disableDecoderAll();
int setDecoderTimeout(int timeout);
int setDecoderResultMax(int max);
int disableIdenticalSymbols(int enable);
#ifdef __cplusplus
}
#endif
5.2.6 Decoder (Python)
本节介绍设置码制、设置读码时长和设置最大解码数量等的具体操作。
5.2.6.1 流程图

5.2.6.2 操作步骤
在操作读码之前,需要先导入模块再初始化读码器,具体操作如下。
- 导入模块。
import libedaaidc
- 初始化读码器。
libedaaidc.initDecoder()
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 设置码制,默认支持的码制为Code128、Data Matrix和QR,码制支持按需设置。
| 代码 | 描述 |
|---|---|
| libedaaidc.enableDecoderC128() | 使能Code128码制 |
| libedaaidc.disableDecoderC128() | 禁用Code128码制 |
| libedaaidc.enableDecoderC93() | 使能Code93码制 |
| libedaaidc.disableDecoderC93() | 禁用Code93码制 |
| libedaaidc.enableDecoderC39() | 使能Code39码制 |
| libedaaidc.disableDecoderC39() | 禁用Code39码制 |
| libedaaidc.enableDecoderI25() | 使能Interleaved 2 of 5码制 |
| libedaaidc.disableDecoderI25() | 禁用Interleaved 2 of 5码制 |
| libedaaidc.enableDecoderUpc() | 使能UPC码制 |
| libedaaidc.disableDecoderUpc() | 禁用UPC码制 |
| libedaaidc.enableDecoderEan() | 使能EAN码制 |
| libedaaidc.disableDecoderEan() | 禁用EAN码制 |
| libedaaidc.enableDecoderQr() | 使能QR码制 |
| libedaaidc.disableDecoderQr() | 禁用QR码制 |
| libedaaidc.enableDecoderDm() | 使能Data Matrix码制 |
| libedaaidc.disableDecoderDm() | 禁用Data Matrix码制 |
| libedaaidc.enableDecoderPdf() | 使能PDF417码制 |
| libedaaidc.disableDecoderPdf() | 禁用PDF417码制 |
| libedaaidc.enableDecoderAll() | 使能所有码制 |
| libedaaidc.disableDecoderAll() | 禁用所有码制 |
| 参数 | 返回值 |
|---|---|
| 无 |
|
- 设置解码时长。
libedaaidc.setDecoderTimeout(ms)
| 参数 | 返回值 |
|---|---|
|
|
提示
运行解码函数时,解码的数量超过设定值后会退出解码。
- 设置最大解码数量。
libedaaidc.setDecoderResultMax(max)
| 参数 | 返回值 |
|---|---|
|
|
提示
运行解码函数时,解码的数量超过设定值后会退出解码。
- 配置相似条码使能。
libedaaidc.disableIdenticalSymbols(enable)
| 参数 | 返回值 |
|---|---|
|
|
提示
条形码在受损情况下可能会被识别为多个相同的码,会输出多个重复的内容,通过设置可以关闭或者使能。
- 运行解码函数。
results = libedaaidc.decoder(image, width, height)
| 参数 | 返回值 |
|---|---|
|
|
提示
从图像数据中解码并输出条码类型、条码内容和条码的位置,返回值为解码的数量。其中返回为列表形式,常见字段说明如下:
code_length:条码内容长度code_string:条码内容字符串center_x:目标中心点X坐标center_y:目标中心点Y坐标code_type:枚举类型,例如 CODE_TYPE_QRbounds:4个角点坐标列表
示例:
results = libedaaidc.decoder(image, width, height)
print(f"decode_count={len(results)}")
for i, r in enumerate(results):
code_type = r["code_type"]
code_type_name = code_type.name if hasattr(code_type, "name") else str(code_type)
print(f"[{i}] type={code_type_name}, text={r['code_string']}, center=({r['center_x']},{r['center_y']})")
print(f"bounds={r['bounds']}")
for j, b in enumerate(r['bounds']):
print(f"point[{j}]={b['x']},{b['y']}")
- 关闭读码器。
libedaaidc.destroyDecoder()
| 参数 | 返回值 |
|---|---|
| 无 |
|
5.2.6.3 代码示例
PYBIND11_MODULE(libedaaidc, m) {
m.doc() = "EDATEC AIDC wrapper";
py::enum_<CodeType>(m, "CodeType")
.value("CODE_TYPE_C128", CODE_TYPE_C128)
.value("CODE_TYPE_C93", CODE_TYPE_C93)
.value("CODE_TYPE_C39", CODE_TYPE_C39)
.value("CODE_TYPE_I25", CODE_TYPE_I25)
.value("CODE_TYPE_UPC", CODE_TYPE_UPC)
.value("CODE_TYPE_EAN", CODE_TYPE_EAN)
.value("CODE_TYPE_QR", CODE_TYPE_QR)
.value("CODE_TYPE_DM", CODE_TYPE_DM)
.value("CODE_TYPE_PDF", CODE_TYPE_PDF);
m.def("initDecoder", []() {
return initDecoder();
});
m.def("destroyDecoder", []() {
return destroyDecoder();
});
m.def("decoder", [](py::buffer image, int width, int height) {
py::buffer_info info = image.request();
auto* data = static_cast<uint8_t*>(info.ptr);
std::vector<DEC_RESULT> results;
int count = decoder(data, width, height, results);
py::list pyResults;
if (count <= 0) {
return pyResults;
}
for (int i = 0; i < count; ++i) {
auto& r = results[i];
py::dict item;
// 基本字段
item["code_length"] = r.code_length;
item["code_string"] = std::string(r.code_string, r.code_length);
item["center_x"] = r.center_x;
item["center_y"] = r.center_y;
item["code_type"] = py::cast(r.code_type);
// bounds -> list of points
py::list points;
for (int i = 0; i < 4; ++i) {
py::dict pt;
pt["x"] = r.bounds.point[i].x;
pt["y"] = r.bounds.point[i].y;
points.append(pt);
}
item["bounds"] = points;
pyResults.append(item);
}
return pyResults;
}, py::arg("image"), py::arg("width"), py::arg("height"));
m.def("enableDecoderC128", []() {
return enableDecoderC128();
});
m.def("disableDecoderC128", []() {
return disableDecoderC128();
});
m.def("enableDecoderC93", []() {
return enableDecoderC93();
});
m.def("disableDecoderC93", []() {
return disableDecoderC93();
});
m.def("enableDecoderC39", []() {
return enableDecoderC39();
});
m.def("disableDecoderC39", []() {
return disableDecoderC39();
});
m.def("enableDecoderI25", []() {
return enableDecoderI25();
});
m.def("disableDecoderI25", []() {
return disableDecoderI25();
});
m.def("enableDecoderUpc", []() {
return enableDecoderUpc();
});
m.def("disableDecoderUpc", []() {
return disableDecoderUpc();
});
m.def("enableDecoderEan", []() {
return enableDecoderEan();
});
m.def("disableDecoderEan", []() {
return disableDecoderEan();
});
m.def("enableDecoderQr", []() {
return enableDecoderQr();
});
m.def("disableDecoderQr", []() {
return disableDecoderQr();
});
m.def("enableDecoderDm", []() {
return enableDecoderDm();
});
m.def("disableDecoderDm", []() {
return disableDecoderDm();
});
m.def("enableDecoderPdf", []() {
return enableDecoderPdf();
});
m.def("disableDecoderPdf", []() {
return disableDecoderPdf();
});
m.def("enableDecoderAll", []() {
return enableDecoderAll();
});
m.def("disableDecoderAll", []() {
return disableDecoderAll();
});
m.def("setDecoderTimeout", [](int timeout) {
return setDecoderTimeout(timeout);
});
m.def("setDecoderResultMax", [](int max) {
return setDecoderResultMax(max);
});
m.def("disableIdenticalSymbols", [](int enable) {
return disableIdenticalSymbols(enable);
});
}
