工业视觉显示编程:实现工业相机画面实时显示同时叠加测量数据
工业相机画面叠加测量数据,最容易写成“OpenCV imshow加putText”样——开发机上看没问题,上嵌入式平台直接掉到个位数帧率。根因是视频解码/格式转换和文字渲染全挤在CPU一条线上,还没做硬件图层分离。正经做法是视频走视频层、文字框线走OSD层,显示控制器做硬件混合,两边只在“同一帧时间戳”上对齐。
一、采集与显示解耦
GigE/USB3 Vision相机先过厂商SDK或Aravis取流,V4L2子系统走REQBUFS+mmap拿DMA缓冲。
ioctl(fd, VIDIOC_REQBUFS, &req); // DMA缓冲
for(i=0;i<req.count;i++){
ioctl(fd, VIDIOC_QUERYBUF, &buf);
map[i] = mmap(...);
ioctl(fd, VIDIOC_QBUF, &buf); // 还回队列
}
ioctl(fd, VIDIOC_STREAMON, &type);
采集线程只做“取帧→丢给显示层→还缓冲”,不在这里画框、不在这里跑算法。测量算法另起线程,结果写共享结构体带帧序号。
二、双图层:视频层+OSD层
小项目可以fb0叠加凑合,但1080p以上CPU转YUYV→RGB会爆。量产走DRM Plane:
Plane 0(视频层):相机YUV帧,dma-buf零拷贝送入
Plane 1(OSD层):ARGB8888透明图层,画框/文字/数值
Z-order和Global Alpha由显示控制器混合输出
/* OSD层只更新变化区 */
drmModeSetPlane(drm_fd, osd_plane, crtc,
osd_bo_handle, 0,
x, y, w, h, // 目标位置
0,0,w<<16,h<<16);
OSD缓冲用ARGB,文字区域alpha=255,空白区alpha=0,硬件混合时不影响视频层。
三、测量数据绑定帧时间戳
叠加错位大多不是画歪了,是“新数据套旧帧”。规则:
相机每帧带硬件时间戳(GigE走PTP或SDK取帧时间)
算法结果结构带frame_id
OSD刷新时取“当前显示帧对应frame_id的最新结果”
没新结果就沿用上一帧标注,不清屏
typedef struct {
uint64_t frame_id;
uint64_t ts_ns;
float width_mm;
float pos_x, pos_y; // 像素坐标
uint8_t ok;
} meas_t;
meas_t latest; // 算法线程写
__atomic_store(&disp_meas, &latest);
显示线程按当前video plane的frame_id挑结果,别按“最新算完的”挑。
四、坐标映射:先标定再画
测距/定位框必须过相机内参+手眼标定,否则中心准、边缘偏。广角镜头径向畸变能让边缘偏10像素以上。
棋盘格标定内参和畸变系数
显示用去畸变后的图,标注坐标统一在校正图里
像素→世界坐标走仿射/单应矩阵
九点标定够平面定位,3D场景走内外参
/* 像素坐标→显示坐标(已校正图) */
int dx = (int)(meas.pos_x);
int dy = (int)(meas.pos_y);
draw_rect(osd_buf, dx-20, dy-20, 40, 40);
draw_text(osd_buf, dx+24, dy, "%.2fmm", meas.width_mm);
若视频层是原图不去畸变,框坐标要做畸变逆变换,别两套混用。
五、OSD渲染性能要点
文字别每帧sprintf全屏重画,只擦改动区
固定标签(如“宽度”“坐标”)预渲染到位图
数值变化区局部blit
字体用SDL_ttf或freetype渲到offscreen,再拷进OSD plane
中文/特殊符号别用默认点阵,直接花屏
stride按真实行字节算,YUYV是width2,RGB565是width2,RGB888是width*3
六、多相机/外部触发同步
产线运动物体要硬触发:
传感器信号接相机Line1触发,曝光对齐工件到位
多相机走PTP或外部同步信号
软件时间戳只作参考,别拿来当几何对齐基准
不同相机帧率不一致时,OSD按各自frame_id取最近测量结果,不强制“同帧”。
七、落坑清单
相机回调里直接画框→采集线程被渲染拖死
fb0全屏重绘OSD→1080p掉帧
YUYV当RGB565拷→花屏
stride按width算→斜移错位
OSD每帧全清重画→CPU空转
测量数据不绑frame_id→框套错帧
原图未去畸变直接画→边缘偏
文字用默认ASCII点阵→中文乱码
多相机用软件时钟对齐→时间戳漂
DQBUF后忘QBUF→几帧后卡死
八、落地顺序
V4L2/SDK取流,mmap缓冲跑通预览
先fb0出图验证格式和stride
算法线程独立,结果带frame_id写共享区
标定向校正,像素坐标映射世界坐标
OSD走独立ARGB图层,只更新变化区
DRM双plane:视频层YUV+OSD层ARGB
dma-buf共享去掉memcpy
硬触发+帧时间戳对齐,OSD按frame_id取数
工业视觉叠加的本质是“视频和标注分两层、时间绑同一帧”:相机流走DMA到视频plane,测量数据走OSD plane硬件混合,算法结果不直接进采集回调。框准不准看标定,画面卡不卡看有没有把OSD全屏重画、有没有把格式转换扔给CPU。小屏调试fb0够用,上量平台必须拆plane——显示控制器混一次比CPU逐像素合成快一个数量级,也更稳。





