SDK 简介
简介
功能说明
Smart Vision SDK为开发者提供:
- 操作获取相机照片数据的API接口。所获相机照片数据用于后续人工智能模型推理。
- IO/TCP信号输出API接口。信号输出可发送NG/Alarm/Alarm Clear信号。
Smart Vision SDK提供了C++和python两种类型的接口。开发者可以根据自身情况选择使用。
开发环境
Smart Vision SDK运行于Aidlux智能相机环境中。
类别 | 要求 |
---|---|
操作系统 | Ubuntu22.04 |
Aidlux | aidlux_2.x.x.x |
支持语言接口 | Python3.10.12/ C++ |
限制
只能运行在开发环境所要求的运行条件下。
安装/卸载
可通过应用中心安装或卸载Smart Vision SDK。关于应用中心操作介绍,请参考相应文档。
也可以通过命令在线安装或卸载,例如:
安装:
sudo aid-pkg install smartvision-sdk
卸载:
sudo aid-pkg remove smartvision-sdk
打开相机流程介绍
流程图
流程详细步骤介绍
- 实例化Camera类,创建一个Camera对象。
- 调用Camera对象的Open()函数打开相机(可选择是否带参)。
- 有参模式打开相机需要事先实例化结构体DeviceParam,设置相机配置文件,并将该对象作为入参传入Open()函数。具体可参考有参模式打开相机API接口介绍。关于相机配置文件,请参考相机配置文件。
- 无参模式打开相机则可以直接调用start_camera_without_parameter()函数,入参仅需要回调函数名。具体可参考无参模式打开相机API接口介绍。
- 如果成功打开相机,则打开流开关。否则退出。
- 设置抓图开关及循环业务流,在循环中持续抓取回调函数中的图片数据。具体可参考代码样例。
- 根据业务需求关闭流开关,退出业务。
- 无参模式即打开相机的时候不需要传入相机配置参数,SDK使用相机当前配置的参数来打开相机。
- 有参模式即打开相机的时候需要传入相机配置参数,SDK使用传入的配置的参数来打开相机。。
- 从使用场景的角度,配置相机可通过SVE界面设置,相对更方便易懂。因此使用无参模式配合SVE界面设置更灵活易用。
- 有参模式可作为后台编程的一种灵活可选项。
日志功能
SDK日志功能分为:
- 打印日志,即控制台输出
- 保存日志,即日志保存到文件
- 动态设置日志等级,即可通过命令动态改变当前日志等级配置(影响文件输出)
- 关闭日志,即关闭日志文件输出
动态修改日志级别
格式:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool <Command> <Module> <Key> <Value>
其中,Command为:set或者'-s'。
Module为smartvisionsdk_<pid>。
Key为log_level。
Value为:
off:关闭日志
err:打印错误日志
warn:打印警告日志
info:打印信息日志
例如:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool set smartvisionsdk_1234 log_level info
其中,查询当前引用smartvision sdk的执行程序的pid可通过以下命令:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool query smartvisionsdk camera_process_id
关于rtcm_tool工具更多用法,请参考其帮助信息。
修改日志文件路径
格式:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool <Command> <Module> <Key> <Value>
其中,Command为:set或者'-s'。
Module为smartvisionsdk_<pid>。
Key为log_file_path。
Value为日志文件路径。如:/home/aidlux/,表示将在/home/aidlux路径下创建日志文件。(注:SDK初始日志默认存储在/tmp/smartvisionsdk/目录下)
例如:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool set smartvisionsdk_1234 log_file_path /home/aidlux/
日志文件路径默认值为应用程序所在路径。
其中,查询当前引用smartvision sdk的执行程序的pid可通过以下命令:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool query smartvisionsdk camera_process_id
关于rtcm_tool工具更多用法,请参考其帮助信息。
查询日志级别配置
格式:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool <Command> <Module> <Key>
其中,Command为:query或者'-q'。
Module为smartvisionsdk_<pid>。
Key为log_level。
例如:
/opt/aidlux/cpf/aid-rtcm/tools/rtcm_tool query smartvisionsdk_1234 log_level
日志保存于应用执行程序同一目录。例如:
$ ls -rlt
-rwxr-xr-x. 1 aidlux aidlux 127032 Jun 21 11:50 demo
-rw-r--r--. 1 aidlux aidlux 919473 Jun 21 13:34 aidclog_smartvisionsdk_logger_115125_429_2024-06-21.aidclog
C++示例代码
MIPI相机
#include "smart_vision.hpp"
using namespace std;
using namespace Aidlux::SmartVision;
int stop_sign = 0;
const char* camera_path = "/home/aidlux/param.json";
int8_t preview = 1; // 0: 不打开预览 1: 打开预览
bool data_sign = false;
int idx = 0;
cv::Mat sdk_frame;
// 回调函数my_get_img_cb定义
int8_t my_get_img_cb(const Aidlux::SmartVision::Image & cap_img, const SVSdkMemfdInfo &idx)
{
t_count++;
cout << "Image - w: " << cap_img.w << ", h: " << cap_img.h << "Image - w: " << cap_img.srcWidth << ", h: " << cap_img.srcHeight << ", length: " << cap_img.length << ", rt fps: " << cap_img.rt_fps << ", ma fps: " << cap_img.ma_fps << endl;
// 添加处理程序,当data_sign为真才处理
if(data_sign){
bool res = yuv_to_bgr(sdk_frame, cap_img.srcHeight, cap_img.srcWidth, cap_img.planeOffset, (void *)cap_img.data, idx);
data_sign = false;
}
return 0;
}
int main(int argc, char * argv[]) {
configure_camera_parameter(camera_path, 1, 0);
if (start_camera_without_parameter(my_get_img_cb, preview, idx) != 0)
{
printf("Start camera %d failed.\n", idx);
CLOGI("Start camera %d failed.", idx);
return -1;
}
start_camera_capture(idx);
string file_name;
while(!stop_sign){
data_sign = true;
while(data_sign && (!stop_sign)){
usleep(10000);
}
if(stop_sign)
break;
}
stop_camera_capture(idx);
close_camera(idx);
return 0;
}
C++示例代码精解
首先是激活配置文件相机配置文件
configure_camera_parameter(camera_path, 1, 0);
然后调用start_camera_without_parameter函数打开相机。
如果是无参设置,则直接传入回调函数名my_get_img_cb。(注:MIPI相机相关配置。) 如果是有参设置,则还需要实例化结构体DeviceParam,并设置相机配置文件名及路径。然后在open()函数中传入DeviceParam实例和回调函数名。
// 无参设置
int res = start_camera_without_parameter(my_get_img_cb, 1, 0);
// 有参设置
int res = start_camera_with_parameter(cb, conf_file, 1, 0)`;
其次,如果打开相机成功,则调用start_camera_capture函数打开流开关。
接着设计while循环语句,在循环体内,源源不断获取从回调函数中拷贝出来的图像数据。
由于所获数据是YUV原始数据,需要转换为BGR格式,因此需要调用yuv_to_bgr API进行转换。
// sdk_frame为mat对象,转换后的数据存入sdk_frame对象带出。 cap_img.data则为原始数据指针
// mem_info.srcSliceHeight为YUV数据的高度,mem_info.srcYPlaneStride为YUV数据的宽度
yuv_to_bgr(sdk_frame, mem_info.srcSliceHeight, mem_info.srcYPlaneStride, mem_info.planeOffset, (void*)cap_img.data, idx=0);
转换出来的数据用于AI推理及结果预览等。
最后,当不再需要获取数据的时候,调用stop_camera_capture函数关闭流开关,调用close_camera函数关闭摄像头,最后退出程序。
Python示例代码
from pysmartvision import smartvisionsdk
import numpy as np
import time
import os
# 全局变量
stop_sign = False
camera_path = "/home/aidlux/param.json"
preview = 1 # 1: 打开预览, 0: 不打开
data_sign = False
idx = 0
sdk_frame = None
def yuv_to_bgr(yuv_data, height, width, plane_offsets, dtype=np.uint8):
"""
将 YUV 数据(NV12/NV21)转换为 BGR 图像
注意:这里简化处理,实际需根据 planeOffset 和 data 结构解析
"""
# 假设是 NV12 格式 (Y + UV)
y_size = width * height
uv_size = width * height // 2
y = np.frombuffer(yuv_data[0:y_size], dtype=dtype).reshape((height, width))
uv = np.frombuffer(yuv_data[y_size:y_size+uv_size], dtype=dtype).reshape((height//2, width//2, 2))
yuv = cv2.merge([y, uv[:,:,0], uv[:,:,1]])
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_NV12)
return bgr
# 回调函数
def my_get_img_cb(cap_img: Image):
global data_sign, sdk_frame, stop_sign
print(f"Image - w: {cap_img.w}, h: {cap_img.h}, "
f"srcWidth: {cap_img.srcWidth}, srcHeight: {cap_img.srcHeight}, "
f"length: {cap_img.length}, rt_fps: {cap_img.rt_fps}, ma_fps: {cap_img.ma_fps}")
if data_sign:
try:
bgr_img = yuv_to_bgr(cap_img.data, cap_img.srcHeight, cap_img.srcWidth, cap_img.planeOffset)
sdk_frame = bgr_img
data_sign = False
except Exception as e:
print(f"YUV to BGR conversion error: {e}")
return 0
def main():
global stop_sign, data_sign, idx
ret = smartvisionsdk.configure_camera_parameter(camera_path, 1, idx)
if ret != 0:
print(f"Failed to configure camera {idx}, error: {ret}")
return -1
ret = smartvisionsdk.start_camera_without_parameter(my_get_img_cb, preview, idx)
if ret != 0:
print(f"Start camera {idx} failed.")
return -1
start_camera_capture(idx)
print("Camera started. Waiting for frames...")
try:
while not stop_sign:
data_sign = True
# 等待数据处理完成,最多等待5秒
timeout = 0
while data_sign and not stop_sign:
time.sleep(0.1) # 替代msleep(100)
timeout += 1
if timeout > 50: # 5秒超时
print("Frame processing timeout")
break
except KeyboardInterrupt:
print("User interrupted")
stop_sign = True
stop_camera_capture(idx)
close_camera(idx)
print("Camera stopped.")
return 0
if __name__ == "__main__":
main()
Python示例代码精解
首先是激活配置文件相机配置文件
configure_camera_parameter(camera_path, 1, 0)
然后调用open()函数打开相机。
如果是无参设置,则直接传入回调函数名my_get_img_cb。
如果是有参设置,则还需要实例化结构体DeviceParam,并设置相机配置文件名及路径。然后在open()函数中传入DeviceParam实例和回调函数名。
// 无参设置
res = start_camera_without_parameter(my_get_img_cb, 1, 0)
// 有参设置
res = start_camera_with_parameter(cb, conf_file, 1, 0)
其次,如果打开相机成功,则调用start_capture函数打开流开关。
接着设计while
循环语句,在循环体内,源源不断获取从回调函数中拷贝出来的图像数据。而在回调函数中,则通过接口get_cvimage获取图像数据。(注:该图像数据已转为BGR
数据)
im = smartvisionsdk.get_cvimage(cap_img)
所获图像数据用于AI推理等。
最后,当不再需要获取数据的时候,调用stop_capture函数关闭流开关,退出主程序。