工业质检方案:相机触发同步、图像预处理加速、缺陷检测模型部署、结果上报
工业质检,说白了就是让机器代替人眼去看产品。我做了这么多年嵌入式,发现很多团队把精力全砸在模型精度上,结果上了产线发现相机触发抖一下、图像传输慢半拍,整个系统就废了。今天咱们就聊聊,怎么在Jetson上把这一整套流程跑通。
1. 相机触发同步:别让图像“迟到”
工业相机和手机相机不一样。产线上产品是流水线过来的,你得在它刚好经过的时候拍。这就涉及到触发同步。
硬件触发 vs 软件触发
我个人习惯用硬件触发。Jetson的GPIO接上相机的触发线,PLC给一个脉冲,相机就拍。延迟通常在微秒级。软件触发呢?走USB或以太网,延迟可能到毫秒级。产线跑得快的时候,差几毫米产品就偏了。
核心要点:硬件触发用GPIO,软件触发用API。产线速度超过0.5m/s时,必须上硬件触发。
多相机同步
有些场景需要多个角度同时拍。比如手机外壳检测,正面、侧面、背面都要看。这时候所有相机得共用一个触发信号。我遇到过一个问题:两个相机虽然同时触发,但曝光时间不同,结果图像时间戳对不上。后来我加了一个硬件帧同步器,所有相机用同一个时钟源,问题就解决了。
小技巧:Jetson的GPIO可以配置为上升沿或下降沿触发。我一般用上升沿,抗干扰能力强一些。
2. 图像预处理加速:别让CPU干苦力
图像预处理,比如去噪、增强、缩放,这些操作在CPU上跑很慢。Jetson有GPU和VIC(视频图像合成器),得用起来。
用VIC做硬件加速
Jetson的VIC模块可以处理色彩空间转换、缩放、旋转。我写了一个pipeline:相机采集的RAW图,直接送到VIC转成RGB,再缩放到模型需要的尺寸。整个过程不经过CPU,延迟从15ms降到了3ms。
// 使用VIC进行图像缩放和色彩转换
#include <nvbuf_utils.h>
#include <cuda.h>
// 创建输入和输出buffer
int input_fd = nv_buffer_create(...);
int output_fd = nv_buffer_create(...);
// 配置VIC转换参数
struct NvBufferTransformParams params;
params.transform_flag = NVBUFFER_TRANSFORM_FILTER;
params.transform_filter = NvBufferTransform_Filter_Smart;
params.src_rect = {0, 0, 1920, 1080};
params.dst_rect = {0, 0, 640, 640};
// 执行转换
NvBufferTransform(input_fd, output_fd, ¶ms);
注意:VIC的输入buffer必须是NV12或YUV420格式。如果相机输出是BGR,得先转格式。我踩过这个坑,折腾了两天才发现。
GPU并行处理
有些预处理操作,比如直方图均衡化、高斯滤波,用CUDA写kernel跑在GPU上,比CPU快几十倍。我一般把预处理分成两步:VIC做格式转换和缩放,GPU做滤波和增强。这样流水线就满了。
3. 缺陷检测模型部署:TensorRT是标配
模型训练好之后,部署到Jetson上必须用TensorRT优化。不优化的话,推理速度可能只有几帧每秒,根本没法用。
模型转换流程
- 训练好的模型(比如ONNX格式)导出
- 用TensorRT的trtexec工具转成engine文件
- 在Jetson上加载engine进行推理
# 将ONNX模型转为TensorRT engine
trtexec --onnx=defect_model.onnx \
--saveEngine=defect_model.engine \
--fp16 \
--workspace=1024 \
--minShapes=input:1x3x640x640 \
--optShapes=input:4x3x640x640 \
--maxShapes=input:8x3x640x640
动态batch
产线上有时候一次来一个产品,有时候来一批。用动态batch可以自适应。我设置min=1, opt=4, max=8。这样单件时延迟低,批量时吞吐高。
经验之谈:FP16精度对缺陷检测来说足够了。我对比过FP32和FP16,准确率只差了0.1%,但速度提升了1.8倍。INT8虽然更快,但需要校准数据集,而且有些模型会掉点严重。
多模型并行
有些场景需要多个模型协同。比如先检测外观缺陷,再检测尺寸偏差。我用了Jetson的Multi-Process Service (MPS),让两个模型同时跑在不同的CUDA stream上,互不干扰。
4. 结果上报:别让数据“烂”在设备里
检测结果得上报到MES系统或者上位机。上报方式有很多种,我推荐用MQTT或者HTTP。
MQTT vs HTTP
| 特性 | MQTT | HTTP |
|---|---|---|
| 实时性 | 高(推送模式) | 中(轮询模式) |
| 带宽占用 | 低(二进制协议) | 高(文本协议) |
| 可靠性 | QoS 0/1/2 | 依赖TCP |
| 适用场景 | 实时告警、状态上报 | 批量数据、日志上传 |
我个人习惯用MQTT上报缺陷告警,用HTTP上报统计数据和日志。这样实时性和可靠性都兼顾了。
# MQTT上报缺陷结果
import paho.mqtt.client as mqtt
import json
client = mqtt.Client()
client.connect("192.168.1.100", 1883, 60)
def report_defect(product_id, defect_type, confidence):
msg = {
"product_id": product_id,
"defect_type": defect_type,
"confidence": confidence,
"timestamp": time.time()
}
client.publish("factory/defect", json.dumps(msg), qos=1)
避坑指南:我曾经把MQTT的QoS设成0,结果网络抖动丢了几条缺陷数据,产线没及时停机,废了一批产品。后来改成QoS 1,虽然多了一点延迟,但数据一条没丢。
本地缓存
万一网络断了怎么办?我加了一个本地SQLite缓存。上报失败时先存本地,网络恢复后再补报。这样即使断网半小时,数据也不会丢。
整体流程总结
把上面四个环节串起来,就是一套完整的工业质检方案。我画了一张图,方便你理解整个数据流。
嗯,这套方案我在三个项目里验证过。一个是手机屏幕检测,一个是PCB焊点检测,还有一个是食品包装检测。效果都还不错,产线节拍能跑到60件/分钟以上。
最后说一句:工业质检不是模型精度越高越好,而是整个系统稳不稳定。我见过太多团队模型精度99.9%,但相机触发抖一下、网络丢个包,实际良率反而下降了。把基础打牢,比什么都重要。