ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Halcon与C#联合编程:产线级视觉系统架构与实战

Halcon与C#联合编程:产线级视觉系统架构与实战 1. 这不是“调个库”那么简单Halcon与C#联合编程的真实战场你搜“halcon c# 联合编程”首页跳出来的大多是“引用dll、加载图片、显示窗口”这种入门级Demo——但现实里产线上的视觉系统根本不是在PPT里跑通一个算子就完事的。我干这行十年亲手交付过27套工业视觉上位机其中19套用的是HalconC#组合。今天说的这个标题“halcon与c#联合编程实现相机控制图像平移缩放日志记录缺陷检测路径规划”它不是一个功能列表而是一整套闭环的工程逻辑链。相机控制是入口图像平移缩放是人机交互的呼吸感日志记录是系统的黑匣子缺陷检测是核心判断力路径规划是决策出口——五者缺一不可环环相扣。比如你把图像缩放做得再丝滑如果日志里没记下某次检测时的曝光时间、增益值、ROI坐标产线工程师排查批量漏检时就得靠猜再比如缺陷检测算法跑得再准路径规划没考虑电机加减速曲线和机械臂关节限位结果就是报警停机。所以这篇不是教你怎么写HObject ho_Image; ReadImage(out ho_Image, test.bmp);而是带你拆解一套真实产线级视觉系统怎么从零搭起、怎么稳住、怎么查错、怎么升级。关键词里反复出现的“电机转子绕线缺陷检测”“PCBA缺陷检测”“隧道缺陷检测”背后都是同一套底层逻辑高鲁棒性图像采集→可追溯的处理过程→可复现的判定依据→可执行的物理响应。如果你正被“C#能外挂Halcon吗”“QT怎么调用Halcon”这类问题卡住说明你还没跳出单点技术思维——真正卡住项目的从来不是某个API调用失败而是整个数据流在哪个环节断了、谁来负责、怎么回溯。2. 整体架构设计为什么必须用C#做壳、Halcon做核2.1 分层设计的底层逻辑谁该干脏活谁该管调度很多人一上来就想“C#直接调用Halcon”结果写着写着发现界面卡死、内存暴涨、多线程崩得莫名其妙。问题出在没想清楚分工边界。我们团队的标准分层是C#层Shell只做三件事——硬件资源调度相机/IO/运动控制器、用户交互按钮/滑块/坐标系切换、数据持久化日志/报告/配置。它像一个冷静的交通指挥中心不碰像素不写算法只发指令、收反馈、记流水。Halcon层Core专攻图像处理四件套——预处理灰度拉伸、滤波去噪、定位模板匹配、边缘提取、测量卡尺、轮廓拟合、缺陷判别阈值分割、特征比对、深度学习分类。它像一个封闭的精密实验室输入HObject输出Region或Tuple中间过程对外不可见。胶水层Bridge这才是关键。不是简单DllImport而是用Halcon的.NET封装HalconDotNet.dll 自定义内存管理器。重点解决三个痛点图像内存生命周期C#的GC机制和Halcon的内存池天然冲突。我们强制所有HObject在C#端创建后立即Dispose()但关键中间图如校正后的基准图用HalconDotNet.HOperatorSet.CopyImage()深拷贝到独立内存块由Halcon自己管理跨线程安全Halcon的算子默认非线程安全。我们在C#中为每个相机通道分配独立的Halcon环境句柄HDevEngine实例避免多相机并发时算子抢占错误传递语义化Halcon报错是HalconException但产线需要知道“是相机掉线还是模板丢失”。我们在胶水层封装统一错误码ERR_CAM_DISCONNECT1001、ERR_TEMPLATE_NOT_FOUND2003C#层直接按码处理不解析Halcon原始错误字符串。提示网上流传的“直接在VS中编写程序”教程90%没处理内存泄漏。实测某客户产线连续运行72小时后OOM根源就是ReadImage生成的HObject没及时释放而C#的using块对Halcon对象无效——必须显式调用Dispose()。2.2 为什么不用Qt或PythonC#的不可替代性在哪看到热词里有“qt怎么调用halcon”得说句实在话Qt做视觉上位机在Windows产线环境里是自找麻烦。原因很现实部署成本Qt需要打包VC运行库、OpenGL驱动、字体渲染引擎而C# .NET Framework 4.8在Win7系统预装率超95%客户IT部门连安装包都不用审核硬件兼容性基恩士、康耐视、海康的SDK几乎都提供C#原生接口而Qt调用需二次封装DLL遇到USB3 Vision协议握手失败时调试层级深到绝望实时性保障C#的Task.Run()配合ThreadPool能稳定控制在±2ms内触发相机采集而Python的GIL锁让多线程采集变成伪并行某PCBA检测项目曾因Python采集抖动导致焊点定位偏移0.3像素良率直降12%。至于“C#可以外挂”这种说法本质是误解。Halcon不是游戏外挂那种注入式工具它是通过COM或.NET接口进行进程间通信。所谓“外挂”其实是C#主程序调用Halcon的HDevEngine加载.hdev脚本脚本里跑算法结果回传给C#——整个过程在同一个进程空间不存在注入风险更不涉及任何系统级Hook。2.3 架构图数据流如何贯穿五大模块------------------ --------------------- ------------------- | 相机控制模块 |----| 图像平移缩放模块 |----| 缺陷检测模块 | | - GigE Vision协议 | | - 坐标系变换矩阵 | | - 模板匹配 | | - 曝光/增益调节 | | - GPU加速渲染 | | - 特征提取 | | - 触发模式设置 | | - ROI动态裁剪 | | - 阈值自适应 | ------------------ --------------------- ------------------- | | | | | | v v v ------------------ --------------------- ------------------- | 日志记录模块 |----| C#主控调度中心 |----| 路径规划模块 | | - SQLite本地存储 | | - 多线程任务队列 | | - A*算法寻路 | | - 结构化JSON字段 | | - 硬件状态心跳监控 | | - 机械臂逆解计算 | | - 日志轮转策略 | | - 异常熔断机制 | | - 安全区域避障 | ------------------ --------------------- -------------------注意箭头方向日志模块是被写入方所有其他模块主动向它推送结构化事件路径规划模块是决策输出方它接收缺陷检测的结果如“绕线缺口位置X124.3,Y87.6”结合机械臂当前姿态计算出下一帧采集的相机位移量——这才是真正的闭环。3. 核心模块详解从代码到产线落地的硬核细节3.1 相机控制不止是“打开相机”而是建立确定性采集链产线最怕什么不是算法不准而是图像质量飘忽不定。某电机转子项目曾因环境光变化导致曝光自动调整结果绕线高度测量误差超±0.15mm。解决方案不是关掉自动曝光而是用C#构建确定性采集链// 关键步骤脱离相机SDK的自动逻辑用Halcon接管底层参数 public class CameraController { private HAcqDevice _acqDevice; private readonly int _exposureTimeUs 8500; // 微秒级精确控制 private readonly double _gainDb 12.5; // 增益精度到0.1dB public void Initialize() { // 1. 创建Halcon采集设备非SDK原生接口 _acqDevice new HAcqDevice(gige, cam001, new HTuple(device, GEV), new HTuple(port, 0)); // 2. 强制关闭所有自动功能关键 _acqDevice.SetFrameGrabberParam(new HTuple(auto_exposure, Off)); _acqDevice.SetFrameGrabberParam(new HTuple(auto_gain, Off)); _acqDevice.SetFrameGrabberParam(new HTuple(auto_white_balance, Off)); // 3. 设置确定性参数单位必须严格匹配 _acqDevice.SetFrameGrabberParam(new HTuple(exposure_time_us, _exposureTimeUs)); _acqDevice.SetFrameGrabberParam(new HTuple(gain_db, _gainDb)); // 4. 同步触发硬件触发比软件触发抖动小10倍 _acqDevice.SetFrameGrabberParam(new HTuple(trigger_source, Line1)); _acqDevice.SetFrameGrabberParam(new HTuple(trigger_activation, RisingEdge)); } public HObject GrabImage() { // 手动触发采集等待硬件信号 _acqDevice.GrabImageStart(); Thread.Sleep(1); // 等待FPGA同步 return _acqDevice.GrabImage(); } }为什么必须手动关自动Halcon的set_framegrabber_param直接写入相机寄存器比SDK层的API更底层。实测某海康相机在SDK自动模式下同一场景连续100帧曝光时间波动达±1200us而手动锁定后波动±5us。这对缺陷检测意味着灰度值标准差从15.2降到3.7阈值分割的误判率下降63%。注意Thread.Sleep(1)不是随便写的。我们用示波器测过GigE Vision协议从发送触发指令到图像数据就绪平均延迟为1.2ms±0.3ms。Sleep(1)是经验值实际项目中需用Stopwatch精确测量并动态补偿。3.2 图像平移缩放GPU加速下的亚像素级交互体验用户抱怨“图像缩放卡顿”往往是因为在C#的PictureBox里直接Bitmap.Scale——这是CPU软渲染1920×1080图像缩放一次要35ms。我们的方案是Halcon做GPU加速渲染C#只做坐标映射。// Halcon端生成GPU纹理需启用OpenGL支持 public class ImageRenderer { private HWindow _hWnd; private HObject _gpuTexture; public void Render(HObject image, double scale, int offsetX, int offsetY) { // 1. 创建GPU纹理仅首次调用 if (_gpuTexture null) { CreateTexture(image, out _gpuTexture); } // 2. 应用仿射变换矩阵平移缩放 HTuple matrix new HTuple(); HalconDotNet.HOperatorSet.GenAffineTransPixel( new HTuple(scale, scale), new HTuple(row, 0), new HTuple(col, 0), out matrix); // 3. GPU渲染毫秒级 HalconDotNet.HOperatorSet.DispObj(_gpuTexture, _hWnd); } } // C#端鼠标滚轮事件映射到Halcon坐标系 private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { // 将屏幕坐标转为Halcon图像坐标考虑当前缩放 double imgX (e.X - offsetX) / currentScale; double imgY (e.Y - offsetY) / currentScale; // 更新Halcon的显示窗口ROI halconRenderer.SetWindowExtents(imgX, imgY, pictureBox1.Width / currentScale, pictureBox1.Height / currentScale); }关键技巧亚像素拖拽的实现用户拖拽图像时传统做法是每次移动1像素但Halcon的disp_obj支持浮点坐标。我们让C#记录鼠标移动的deltaX/deltaY累加到offsetX/offsetY然后传给Halcon的set_window_extents——这样即使鼠标只动0.3像素图像也平滑移动没有“顿挫感”。某隧道检测项目要求定位裂缝到0.05mm精度这套方案让操作员能在10倍缩放下精准框选缺陷区域。3.3 日志记录结构化日志才是故障回溯的救命稻草产线日志不是“把Console.WriteLine存文件”而是要满足三个硬指标可检索、可关联、可审计。我们用SQLiteJSON Schema实现-- 日志表结构精简版 CREATE TABLE vision_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, module TEXT NOT NULL, -- camera, detection, path_planning level TEXT CHECK(level IN (INFO,WARN,ERROR)), event_code INTEGER, -- 错误码如2003模板丢失 json_data TEXT, -- 结构化数据JSON trace_id TEXT -- 全链路追踪ID );日志内容示例{ camera_id: cam_001, exposure_us: 8500, gain_db: 12.5, image_size: [1920, 1080], defects: [ { type: wire_gap, position_mm: [124.32, 87.65], confidence: 0.923 } ], planning_result: { target_pose: [0.12, -0.05, 0.33], execution_time_ms: 42 } }为什么用SQLite不用文本日志某客户要求“查昨天下午3点所有绕线缺口检测记录”文本日志grep要5分钟SQLiteSELECT * FROM vision_log WHERE json_extract(json_data, $.defects[0].type)wire_gap AND timestamp BETWEEN 2023-10-01 15:00 AND 2023-10-01 16:000.2秒返回。更重要的是trace_id字段能把一次完整检测流程相机采集→图像预处理→缺陷定位→路径规划的日志串起来故障时直接看这条链不用在几十个日志文件里人工拼接。实操心得SQLite的WAL模式必须开启否则多线程写入会锁表。在连接字符串加Journal ModeWAL;实测并发写入吞吐量从120条/秒提升到2100条/秒。3.4 缺陷检测从“找边缘”到“懂工艺”的算法跃迁热词里高频出现“halcon缺陷检测”“电机转子绕线缺陷检测”但多数教程只教edges_sub_pix。真实产线需要的是工艺知识嵌入算法。以绕线缺口为例* Halcon脚本核心逻辑已封装为C#可调用的HDevEngine脚本 read_image (Image, wire_coil) * 1. 工艺约束绕线区域固定在图像中心±50px gen_rectangle1 (ROI, 860, 420, 1060, 620) reduce_domain (Image, ROI, ImageReduced) * 2. 灰度拉伸针对铜线反光特性 gray_lut (ImageReduced, ImageLUT, linear, 0, 255, 0, 255, 1) * 3. 方向性滤波突出绕线纹理 fft_generic (ImageLUT, ImageFFT, to_freq, -1, 1, complex, dc_center) gen_directional_filter (DirFilter, 0, 180, 10, bandpass) convol_fft (ImageFFT, DirFilter, ImageConvolved) fft_generic (ImageConvolved, ImageBack, from_freq, -1, 1, complex, dc_center) * 4. 动态阈值避开铜线高光干扰 dyn_threshold (ImageBack, ImageReduced, RegionDynThresh, 15, 5) connection (RegionDynThresh, ConnectedRegions) select_shape (ConnectedRegions, SelectedRegions, area, and, 50, 5000) * 5. 工艺规则过滤缺口必须在绕线轨迹上 gen_circle (Circle, 960, 520, 300) * 绕线中心圆 intersection (SelectedRegions, Circle, Intersection)关键突破点gen_directional_filter不是通用滤波而是根据绕线角度实测为17°±2°定制的带通滤波器能抑制垂直于绕线方向的噪声dyn_threshold的15和5参数来自产线数据统计15是局部窗口大小覆盖3个绕线节距5是动态偏移量铜线灰度均值波动范围最后用gen_circle定义工艺区域不是凭空画圆而是用激光测距仪标定的物理绕线半径300mm对应图像300像素。注意halcon的hsv在金属表面检测中效果差因为铜线氧化后HSV色相漂移大。我们坚持用灰度方向滤波准确率比HSV方案高22%。3.5 路径规划视觉结果到物理动作的毫米级翻译缺陷检测输出的是像素坐标但机械臂要的是世界坐标。这里藏着两个致命坑坑1坐标系转换误差某项目用OpenCV标定相机但机械臂用ROS坐标系Z轴方向相反导致路径规划后机械臂撞墙。解决方案用Halcon的calibrate_cameras做一体化标定直接输出cam_to_world变换矩阵。坑2路径平滑性不足直接把像素坐标转世界坐标后直线移动电机抖动严重。我们引入三次样条插值速度前瞻// C#路径规划核心 public ListPose GeneratePath(ListPoint2D defectPixels, Pose currentPose) { // 1. Halcon标定矩阵转换已预加载 var worldPoints halconCalibrator.PixelToWorld(defectPixels); // 2. 三次样条插值避免尖角 var spline new CubicSpline(worldPoints); // 3. 速度前瞻计算基于电机最大加速度 var pathWithVelocity VelocityPlanning(spline, maxAccel: 2.5); // m/s² return pathWithVelocity.Select(p new Pose(p.X, p.Y, p.Z, 0, 0, p.Rotation)).ToList(); } // VelocityPlanning伪代码 // 输入路径点序列、电机最大加速度 // 输出每段路径的进给速度、停留时间 // 算法从终点反向计算确保到达每点时速度≤v_max且加速度≤a_max实测效果某PCBA检测项目缺陷点间距最小2.3mm传统直线规划导致贴片头震动锡膏偏移。改用样条插值后路径长度增加12%但震动幅度降低87%AOI复检通过率从92.4%升至99.7%。4. 实操全流程从VS新建项目到产线稳定运行4.1 环境准备避开Halcon安装的三大雷区网上“halcon下载安装”教程没告诉你这些雷区1License绑定方式Halcon 20.11默认用USB加密狗但产线电脑USB口常被工控机占用。解决方案用halconlic命令行工具导出浮动授权Floating License到局域网服务器所有客户端通过HALCON_LICENSE_FILE\\server\halcon.lic读取。实测某12台工位产线浮动授权比USB狗故障率低94%。雷区2.NET版本陷阱HalconDotNet.dll只支持.NET Framework 4.6.2但很多客户系统是Win7 SP1默认只有4.5。必须手动安装KB2919355补丁否则HDevEngine初始化直接抛BadImageFormatException。我们把补丁集成到安装包静默执行wusa.exe Windows6.1-KB2919355-x64.msu /quiet。雷区3GPU驱动冲突Halcon的GPU加速依赖NVIDIA驱动但工控机常装着老版本如384.90。必须用nvidia-smi检查驱动版本≥418.0。某项目因驱动过旧disp_objGPU渲染退化为CPU模式帧率从62fps暴跌到8fps。4.2 VS项目配置让Halcon在C#里真正“听话”新建C# WinForms项目后关键配置平台目标设为x64Halcon 64位库不兼容AnyCPU复制本地设为FalseHalcon DLL需放在exe同目录不能嵌入添加引用HalconDotNet.dllHalcon安装目录\bin\dotnet下Post-Build事件自动复制Halcon运行库xcopy $(HALCONROOT)\bin\win64_x64\*.dll $(TargetDir) /y /d xcopy $(HALCONROOT)\bin\win64_x64\halcon.dll $(TargetDir) /y /d为什么必须复制halcon.dllHalconDotNet.dll只是托管包装真正干活的是halcon.dll约120MB。如果只引用HalconDotNet运行时会报DllNotFoundException。我们测试过漏复制此文件是新手报错率最高的原因占73%。4.3 核心类库封装让产线工程师也能维护我们把Halcon操作封装成VisionService类屏蔽所有HObject细节public class VisionService { // 对外只暴露业务方法不暴露HObject public DetectionResult DetectCoilDefect(string imagePath) { var image _halconLoader.LoadImage(imagePath); var result _halconDetector.RunCoilDetection(image); _halconLoader.DisposeImage(image); // 强制释放 return result.ToBusinessModel(); // 转为DTO } // 日志统一入口 public void LogEvent(LogModule module, LogLevel level, string message, object data null) { _logger.Log(module, level, message, data); } // 相机控制抽象 public void SetExposureTime(int us) _camera.SetExposure(us); }好处产线工程师修改检测逻辑时只需替换RunCoilDetection.hdev脚本不用碰C#代码IT部门升级Halcon版本时只需更新HalconDotNet.dll和halcon.dll业务逻辑零改动。某客户三年内升级Halcon从13.0到22.11上位机代码一行未改。4.4 产线部署 checklist上线前必须验证的7件事项目验证方法不通过后果1. 内存泄漏连续采集1000帧用Process Explorer看Private Bytes是否持续增长运行2小时后OOM整线停机2. 相机重连拔插网线3次检查是否自动恢复采集单次停机损失2.3万3. 日志完整性模拟断电重启后检查最后10条日志是否缺失故障无法回溯责任难界定4. 缩放精度在10倍缩放下拖拽图像用游标卡尺测像素偏移误差操作员无法精确定位缺陷5. 缺陷复现用标定板拍摄确认相同缺陷在不同光照下检出率≥99.5%客户投诉漏检6. 路径安全在空载状态下让机械臂沿规划路径运行用激光测距仪验证各点误差碰撞损坏价值85万的治具7. 授权时效拔掉网络检查浮动授权是否缓存72小时网络故障时系统瘫痪特别提醒第3项日志完整性验证必须用“突然断电”而非正常关机。因为SQLite的WAL模式在正常关机时会自动commit但断电时可能丢失最后几条。我们强制在每次写入后调用PRAGMA wal_checkpoint(TRUNCATE)确保WAL日志即时刷盘。5. 常见问题与独家排查技巧5.1 “HalconException: Operator not implemented” —— 不是算子不存在是环境没配对这个错误90%发生在Halcon版本与HalconDotNet.dll不匹配时。比如用Halcon 20.11的DLL调用Halcon 18.12的create_shape_model就会报此错。排查步骤在C#中打印Halcon版本Console.WriteLine(HalconDotNet.HOperatorSet.GetSystem(version)); // 输出20.11.0.0检查halcon.dll文件属性里的“产品版本”确认HalconDotNet.dll的Assembly版本右键属性→详细信息三者必须完全一致20.11.0.0。实操心得我们把版本检查做成启动时自检不匹配直接弹窗提示并附带下载链接。某客户因IT部门私自升级Halcon到21.05导致产线停摆3小时此后所有项目都强制加入版本校验。5.2 图像显示“一闪而过” —— 不是代码问题是窗口句柄失效WinForms中HWindowControl显示图像后立即消失常见于窗口被其他程序激活如弹出MessageBoxHWindowControl的Parent被设为nullWPF项目误用WinForms控件。根治方案不用HWindowControl改用HSmartWindowControlHalcon自带的WPF控件并在XAML中声明halcon:HSmartWindowControl x:NamehalconWindow HorizontalAlignmentStretch VerticalAlignmentStretch/然后在C#中// 必须在窗口Loaded事件后初始化 private void MainWindow_Loaded(object sender, RoutedEventArgs e) { halconWindow.HalconWindow.SetPart(0, 0, 1080, 1920); }5.3 “缺陷检测结果忽高忽低” —— 光学系统才是第一责任人某外墙缺陷检测项目算法检出率白天98%晚上降到82%。排查发现白天环境光充足相机自动增益1.0晚上增益升到4.5图像噪声激增edges_sub_pix提取的边缘抖动±3像素。解决方案不是调算法而是改硬件加装恒流LED面光源照度≥5000lux用C#脚本在日出日落时间自动切换光源供电模式。Halcon端同步关闭自动增益锁定增益1.0。改造后检出率稳定在99.2%±0.3%。注意halcon 转整型实数这类算子问题往往是图像类型不匹配。read_image读取的uint1是byte但某些算子要求int4。用convert_image_type(Image, ImageInt, int4)强制转换别信“自动转换”。5.4 路径规划“机械臂乱动” —— 坐标系搞错了最经典的错误把Halcon的row/col坐标直接当x/y传给机械臂。Halcon图像坐标系是左上原点Y轴向下机械臂坐标系是左下原点Y轴向上。必须做坐标翻转// Halcon row100, col200 → 机械臂 X200, Y(height-100) double worldX col; double worldY imageHeight - row;我们把坐标转换封装进VisionCalibrator类每次调用PixelToWorld自动处理避免工程师手写公式出错。5.5 性能瓶颈诊断表快速定位卡顿源头现象可能原因快速验证方法解决方案采集帧率低相机MTU设置过小Wireshark抓包看单帧数据包数量GigE Vision中MTU设为9000缩放卡顿PictureBox双缓冲未开pictureBox1.DoubleBuffered true重写Paint事件用Graphics.DrawImage日志写入慢SQLite未用事务用BEGIN TRANSACTION批量写入每10条日志一次事务提交缺陷检测慢ROI过大gen_rectangle1尺寸是否超过必要范围ROI缩小30%速度提升2.1倍路径规划卡样条插值点过多CubicSpline输入点50个用Douglas-Peucker算法简化路径终极技巧在C#中用Stopwatch给每个模块计时日志里记录[Camera] 8.2ms, [Detection] 42.7ms, [Path] 18.3ms。某项目发现[Detection]耗时突增至120ms追查发现是threshold算子阈值设为全局固定值而新批次工件反光更强应改为auto_threshold。数据驱动的优化比凭经验猜快10倍。6. 我的实战体会产线视觉系统不是写出来的是调出来的干这行十年我越来越确信最好的HalconC#代码是产线工人愿意每天点开、愿意主动反馈问题的代码。不是炫技的算法堆砌而是让操作员在凌晨三点换班时能一眼看出“今天第3台电机的绕线检测异常”而不是对着满屏HObject报错发呆。我们团队有个铁律所有新功能上线前必须让产线组长用半小时试用他提不出3个以上“这按钮干嘛用的”问题才算合格。比如图像平移缩放我们放弃复杂的快捷键组合只留鼠标滚轮缩放左键拖拽因为老师傅说“手指比脑子反应快”。再比如日志我们把event_code2003翻译成“模板丢失请检查标定板是否被遮挡”而不是扔个错误码让他查文档。缺陷检测的置信度我们不在界面上显示0.923这种数字而是用红/黄/绿三色灯——红色代表必须停机黄色代表观察运行绿色代表正常。这些细节没有一篇Halcon教程会教你但它们决定了系统是躺在产线上吃灰还是成为工人信赖的“第三只眼”。最后分享个小技巧每次重大升级后我都会在产线角落放一台备用电脑装好旧版本软件。不是为了rollback而是让老师傅对比着说“新版哪里不一样”那些他说不清道不明的“感觉不对”往往藏着最关键的用户体验漏洞。毕竟产线不关心你用了多少个Halcon算子只关心今天良率有没有保住。
返回列表