
做AOI(自动光学检测)的朋友可能都经历过这样一个阶段:拿到一个YOLO模型,训练,部署,检测框出来了,缺陷标出来了,任务完成了。

但如果你正在做高密度PCB检测、Micro-LED晶圆质检、或者任何需要“持续理解缺陷分布”的项目,你会发现——一个检测框,越来越不够用了。
AOI检测的重点正在从“某个模型能跑多少帧”,转向“系统能不能持续得到一致、足够新的产品状态”。YOLO仍然重要,但它不该独自承担缺陷分类、定位、尺寸测量和工艺溯源的全部任务。
这不是YOLO不行了。恰恰相反,YOLO——尤其是YOLO26——仍然是工业端侧缺陷检测最常用、最有效的一类工具。但当AOI的任务从“这片板子有没有缺陷”变成“这片板子有什么缺陷、在哪、多大、同一位置上一批有没有出现过、是焊膏印刷问题还是回流焊问题”时,一个检测框已经不足以支撑后续的质量决策。
2026年,AOI正在经历一场从“跑一个模型”到“多模型融合”的范式转移。这场转移的背后,是检测、跟踪、分割、深度估计与VLM开始协作——而YOLO26的路线图,恰好为这场转移提供了关键的技术底座。

AOI的核心任务,长期以来被定义为“在图像中找到缺陷的位置和类别”。
YOLO能回答两个问题:画面里有什么缺陷,以及它大致在哪里。对于固定工位、固定缺陷类型、固定相机的AOI任务,这已经足够。
但今天的高端AOI面临的是更复杂的连续质量管控任务。检测到一个焊点空洞之后,系统还要知道:它是不是上一块板同一个位置的缺陷,尺寸是否符合IPC标准,是否在历史批次中反复出现,是否与前一工位的工艺参数相关。
这些问题分别需要时间信息、几何信息和工艺语义信息。
以Micro-LED芯片阵列检测为例,单颗芯片尺寸仅几十微米,阵列密度极高。传统AOI依赖单一检测模型输出缺陷框,但高密度阵列中相邻芯片的缺陷极易混淆,缺陷的尺度、位置和批次间关联难以建立。
AOI需要维护的已不是一个检测框列表,而是一个产品状态条目:缺陷ID、类别、二维与三维位置、尺寸、置信度、检测时间戳和关联的工艺参数。它可以随新批次持续更新,也可以在不同工位间传递。这个状态才是质量工程师和MES系统真正可以消费的输入。
伪代码:AOI缺陷状态管理
class DefectState:
"""AOI缺陷状态条目——多模型融合后的统一输出"""
def __init__(self):
self.defects = {} # defect_id -> DefectEntry
class DefectEntry:
def __init__(self, defect_id, category, bbox, confidence):
self.id = defect_id
self.category = category # YOLO检测结果
self.bbox_2d = bbox # 二维框
self.position_3d = None # Depth/Stereo提供
self.area_pixel = None # Segmentation提供
self.depth_mm = None # Depth估计提供
self.timestamp = now() # 时间戳
self.track_id = None # Tracker提供
self.semantic_judgment = None # VLM提供
self.confidence = confidence # 多模型交叉验证后的置信度AOI的多模型融合,不是把五份检测结果摆在一起,而是让不同的模型回答不同的问题。
在工业缺陷检测场景中,这一逻辑正在被越来越多的方案验证:

注意,YOLO26的路线图显示,其深度估计任务已经进入预训练阶段,支持逐像素距离预测,为AOI的3D检测提供了原生支持。
举一个实际AOI场景:YOLO26给出焊点空洞的候选框,分割模型精确定义空洞边界并计算面积占比,深度估计判断空洞是否贯穿焊点,当缺陷形态复杂或标准模糊时,VLM给出是否符合IPC-610标准的最终判断。
这解释了AOI领域的一个关键趋势:多模型不是“大模型替代小模型”。更合理的组合往往是快模型持续跑产线节拍,慢模型在需要精细判断时介入。检测模型提供速度和确定性,大模型提供理解和柔性。
伪代码:AOI多模型协同推理
class AOIMultiModelPipeline:
"""AOI多模型协同流水线——让不同模型回答不同问题"""
def __init__(self):
self.detector = YOLO("yolo26n.pt") # 检测:是什么
self.segmenter = SegmentationModel() # 分割:边界怎样
self.depth_estimator = YOLO("yolo26n-depth.pt") # 深度:离多远/多深
self.tracker = SORT() # 跟踪:还是不是它
self.vlm = VLMClient() # VLM:意味着什么
def process_board(self, image, board_id):
# Step 1: 检测——YOLO26快速检出候选缺陷
det_results = self.detector(image, conf=0.25)
defects = []
for det in det_results:
# Step 2: 分割——精确定义缺陷边界
mask = self.segmenter(image, det.bbox)
# Step 3: 深度——获取缺陷深度信息(3D AOI场景)
depth_map = self.depth_estimator(image)
depth_value = depth_map[det.bbox]
# Step 4: VLM——模糊/新型缺陷语义判断(仅低置信度触发)
if det.conf < 0.7 or det.category == "unknown":
semantic = self.vlm.analyze(image, det.bbox,
prompt="判断该缺陷是否达到报废标准,并说明原因")
else:
semantic = None
defects.append({
"category": det.category,
"bbox": det.bbox,
"mask": mask,
"depth": depth_value,
"area_px": mask.area(),
"confidence": det.conf,
"vlm_judgment": semantic
})
# Step 5: 跟踪——与历史批次同一位置关联
for defect in defects:
defect.track_id = self.tracker.update(defect.bbox, board_id)
return self._build_board_state(board_id, defects)不同模型没有必要同频执行。

若把这些模块都固定成同一帧率,不仅浪费边缘端算力,也会让检测队列越积越长。
例如AOI系统可以让YOLO26持续运行检测,分割只在检出缺陷后对候选区域执行,VLM只在新缺陷类型、低置信度或客户标准变更时处理关键图像。每个模块的频率必须由产线节拍、缺陷率和当前资源决定,而不是由“模型能跑多快”单独决定。
伪代码:AOI按需调度器
class AOIScheduler:
"""AOI模型调度器——不同模型不同频率,按需触发"""
def __init__(self):
self.detector = YOLO("yolo26n.pt")
self.segmenter = SegmentationModel()
self.depth_estimator = YOLO("yolo26n-depth.pt") if USE_3D else None
self.vlm = VLMClient()
self.tracker = SORT()
# 调度策略
self.detect_every_n_frames = 1 # 每帧检测
self.segment_on_defect = True # 检出缺陷时才分割
self.depth_on_3d_required = True # 需要三维信息时才开启
self.vlm_on_low_conf = True # 低置信度时才调用VLM
def run_pipeline(self, frame, frame_id):
# 1. 检测——每帧都跑
detections = self.detector(frame, conf=0.25)
# 2. 跟踪——每帧更新
self.tracker.update(detections)
# 3. 分割——只在检出缺陷时触发
if detections and self.segment_on_defect:
for det in detections:
det.mask = self.segmenter(frame, det.bbox)
# 4. 深度——只在需要3D信息时触发(如靠近目标或配置开启)
depth_map = None
if self.depth_estimator and self.depth_on_3d_required:
depth_map = self.depth_estimator(frame)
# 5. VLM——只在低置信度、新型缺陷或语义歧义时触发
for det in detections:
if det.conf < 0.7 or det.category == "unknown":
det.vlm_result = self.vlm.analyze(
frame, det.bbox,
prompt="分析该缺陷类型、严重程度和是否符合IPC标准"
)
return self._merge_results(frame_id, detections, depth_map)模型数量增加后,瓶颈很容易从NPU算力转到数据路径。
YOLO26在工业AOI中的优势正在于此——端到端无NMS推理和移除DFL模块,使模型导出更干净,ONNX/TensorRT等平台一键导出无障碍。
在PCB AOI场景中,YOLO26已成功微调用于检测6类裸PCB板缺陷,无NMS端到端检测头大幅简化了部署流程。对于AOI系统而言,每类缺陷的召回率直接对应产线的漏检率(escape rate)——漏检的缺陷将流向下一道工序。
但即便是YOLO26这样的高效模型,在多模型融合架构中也需要精心设计数据流。一帧相机数据若先被CPU复制给检测,再复制给分割、深度和VLM,内存带宽、格式转换和同步等待很快就会拖慢系统。
YOLO26对INT8量化的原生支持,使其在边缘端部署时能够进一步降低延迟和内存占用。在汽车零部件缺陷检测的实战中,YOLO26系统已成功在某知名车企的生产线上稳定运行8个月,检测速度达到每秒15-20帧。
伪代码:共享输入,避免重复拷贝
class AOISharedBuffer:
"""共享帧Buffer——避免多模型间的数据重复拷贝"""
def __init__(self):
self.frame_buffer = None # 统一的图像Tensor
self.buffer_owner = None # 当前持有者
self.timestamp = None
self.lock = threading.Lock()
def acquire(self, model_name):
"""模型获取帧数据(共享读取,不拷贝)"""
with self.lock:
if self.frame_buffer is None:
return None
# 返回引用,而非拷贝
return self.frame_buffer
def release(self, model_name):
"""模型释放帧数据"""
with self.lock:
# 减少引用计数,不释放原始Buffer
pass
class AOIPipeline:
def process_frame(self, raw_frame):
# 写入共享Buffer(零拷贝)
shared = AOISharedBuffer()
shared.frame_buffer = raw_frame # 仅保存引用
# 多模型并行读取同一份数据
det_thread = Thread(target=self.detector.predict, args=(shared,))
depth_thread = Thread(target=self.depth_estimator.predict, args=(shared,))
det_thread.start()
depth_thread.start()
# ...
# 所有模型读完后再释放
# 避免在模型读取期间修改Buffer单模型难免会在边界条件下出错。检测分数中等时,若分割结果清晰、深度值合理、与历史批次同一位置的缺陷记录一致,系统对该缺陷的信任可以提高;反过来,如果检测框突然出现、深度跳变、轨迹无法关联,就应降低可信度或要求重新观察。
这种融合不是把几个confidence取平均。它要同时考虑几何一致性、时间连续性、观测质量和任务约束。
在AOI场景中,一个缺陷如果连续出现在多块板的同一位置,且形态相似,系统可以给出“疑似工艺偏差”的预警;如果只是孤立出现,则标记为偶发缺陷。每条条件都应该带有时间戳,避免用第100帧的检测去融合第98帧的深度或第101帧的跟踪状态。
伪代码:AOI交叉验证融合
class AOIFusionEngine:
"""多模型交叉验证融合——不是取平均,而是验证一致性"""
def fuse(self, det_result, seg_result, depth_result, history, vlm_result):
"""融合多模型结果,输出最终可信度"""
base_conf = det_result.confidence
# 条件1:分割一致性——缺陷边界清晰且面积合理
if seg_result and seg_result.area > 20:
base_conf *= 1.1
# 条件2:深度一致性——深度值在合理范围内
if depth_result and 0.1 < depth_result < 10:
base_conf *= 1.1
# 条件3:历史一致性——同一位置历史缺陷记录
historical = history.get(det_result.bbox, None)
if historical:
if historical.category == det_result.category:
base_conf *= 1.2 # 历史一致,信任度提升
else:
base_conf *= 0.8 # 历史不一致,怀疑
if historical.count > 5:
# 连续多块板同一位置出现,预警工艺问题
self.alert_工艺偏差(det_result.bbox)
# 条件4:VLM语义验证
if vlm_result:
if vlm_result.severity == "critical":
base_conf *= 1.3
elif vlm_result.severity == "acceptable":
base_conf *= 0.7
# 时间一致性检查——确保所有结果来自同一帧
assert det_result.timestamp == seg_result.timestamp == depth_result.timestamp
return min(base_conf, 1.0)2026年的AOI系统,正在从单一检测模型走向多模型融合架构。

YOLO仍然是AOI检测的核心,但它正在从“唯一的模型”变成“多模型系统中的一员”。未来的AOI系统,不是某个模型跑多快,而是检测、分割、深度估计与VLM开始协作,共同维护一个一致的产品质量状态。
最终形态:由调度器维护统一的产品状态
未来的AOI系统不一定把所有模型写死成一条流水线。Scheduler可以根据任务和状态决定调用路径:
伪代码:AOI调度器维护产品状态
class AOISceneState:
"""AOI最终输出:统一的产品质量状态"""
def __init__(self):
self.board_id = None
self.defects = [] # 缺陷列表
self.pass_fail = "PASS" # 整板判定
self.timestamp = now()
self.metadata = {} # 工艺参数、批次信息等
class AOIAgent:
"""AOI智能调度器——按需调用模型,维护统一状态"""
def process(self, board_image, board_id, task):
# 判断任务类型
if task == "quick_scan":
# 只需快速筛查
results = self.lightweight_model(board_image)
return self._build_state(results)
elif task == "defect_analysis":
# 检出缺陷后详细分析
detections = self.yolo26(board_image)
for det in detections:
# 按需调用
if det.conf < 0.7:
det.vlm_result = self.vlm(board_image, det.bbox)
if self.need_3d:
det.depth = self.depth_estimator(board_image, det.bbox)
if self.need_precision:
det.mask = self.segmenter(board_image, det.bbox)
return self._build_state(detections)
elif task == "conflict_resolution":
# 结果冲突时调用VLM重新判断
return self.vlm(board_image, task.context)端侧视觉真正的进化,不是从“一个模型”走向“很多模型”,而是从“单次推理”走向“持续维护环境状态”。
对于AOI系统来说,这意味着:
最值得避免的做法,是把模型简单堆在一起、让它们以相同频率跑、再等待一堆互不一致的结果。更可靠的架构是:小模型按高频维护基础状态,大模型按事件补充语义,不同模型共享输入并带上时间戳,最后由融合层输出一个一致、实时、可检查的产品状态。
在AOI这个领域,真正的挑战不是让一个模型变得更强,而是让多个模型各司其职、协同工作——从“检出一个缺陷”走向“维护一个产品状态”。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。