引言
很多刚接触机器视觉的同学,一上来就被"装环境"这件事劝退了:装完 OpenCV 编译报错、链接报错、跑起来又闪退。其实这些问题大多源于对工程组织方式不熟悉,而不是代码本身难。
本文面向有 C++ 基础、但刚接触机器视觉和 OpenCV 的读者,解决一个具体问题:如何从零搭建一套可以复用的 AOI(自动光学检测)开发环境。读完本文你能学到三件事:一是理解 AOI 是什么、用在哪里;二是明白为什么工业界选 C++ + OpenCV;三是亲手完成"安装环境 → 用 CMake 组织工程 → 编译运行第一个读图程序"的完整闭环,并避开最常见的几个坑。
什么是 AOI
AOI(Automated Optical Inspection,自动光学检测),是用工业相机拍摄被测物体,再用图像处理算法自动判断产品是否有缺陷的技术。它代替人眼完成重复、高速、客观的质量检查,是智能制造里的"电子质检员"。
典型的应用场景包括:
| 场景 | 检测内容 |
|---|---|
| PCB 板检测 | 焊点虚焊、连锡、元件缺失、极性反装 |
| SMT 贴片 | 贴片偏移、错料、立碑、少件 |
| 显示面板 | 亮点、暗点、划痕、Mura 污渍 |
| 外观检测 | 划伤、毛刺、脏污、尺寸测量 |
一条 AOI 流水线大致分为四步:打光与成像 → 图像预处理 → 特征提取与判定 → 结果输出。其中图像处理部分,绝大多数项目都离不开 OpenCV。所以学 AOI,第一步不是急着写检测算法,而是先把 OpenCV 这套开发环境搭稳。
为什么选择 OpenCV + C++
OpenCV 是目前最流行的开源计算机视觉库,覆盖图像读写、滤波、形态学、轮廓分析、特征匹配、相机标定等 AOI 常用的几乎全部基础能力,且跨平台、有活跃社区。
而工业落地更偏爱 C++,原因很实在:
- 性能:AOI 往往要求每秒检测多件产品,C++ 贴近硬件、没有 GC 停顿,配合 OpenCV 的 SIMD 优化能榨干 CPU。
- 可控性:内存、线程、时延都可精细管理,满足产线实时性要求。
- 部署:C++ 程序可编译为独立可执行文件或动态库,方便集成到产线上位机软件。
一句话总结:用 Python 做原型验证很快,但真正上产线的高性能检测,通常还是 C++。 本文用 OpenCV 4.x 作为示例。
环境安装:Windows 与 Ubuntu
Windows 下安装
最省心的方式是使用官方预编译包:
- 到 OpenCV 官网下载 Windows 版
opencv-4.x.x-windows.exe,解压到例如D:\opencv。 - 解压后目录结构里有
build\x64\vc16\bin(动态库.dll)和build\include(头文件)。 - 把
D:\opencv\build\x64\vc16\bin加入系统环境变量PATH,否则运行时找不到opencv_world4xx.dll。 - 用 CMake 配置工程时,指定
OpenCV_DIR指向解压目录里的build文件夹即可。
建议配一个本地安装的 Visual Studio(社区版即可)作为编译器,CMake 用它生成解决方案。
Ubuntu 下安装
Ubuntu 可以用 apt 一键安装,也可以源码编译(需要定制模块时再考虑)。入门推荐 apt:
sudo apt update
sudo apt install -y libopencv-dev cmake g++ pkg-config
安装完成后用 pkg-config 验证:
pkg-config --modversion opencv4
能打印出 4.x.x 就说明安装成功。Ubuntu 官方源里的 libopencv-dev 通常自带 opencv4.pc,供 pkg-config 查询编译参数。
用 CMake 组织工程
CMake 是跨平台的构建工具,作用是"用一份配置生成各平台的构建文件":Windows 上生成 VS 工程,Linux 上生成 Makefile。工业项目几乎都用它,所以第一步就养成好习惯。
一个最小工程长这样:
aoi-demo/
├── CMakeLists.txt
├── main.cpp
└── sample.jpg # 任意一张测试图片
CMakeLists.txt 内容如下:
cpp
cmake_minimum_required(VERSION 3.10)
# 项目名
project(aoi_hello)
# OpenCV 4 要求至少 C++11,这里统一用 C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找 OpenCV(默认会找系统里已安装的 OpenCV)
find_package(OpenCV REQUIRED)
# 生成可执行文件 app,源码是 main.cpp
add_executable(app main.cpp)
# 链接 OpenCV 库
target_link_libraries(app ${OpenCV_LIBS})
核心就三件事:find_package(OpenCV REQUIRED) 找到 OpenCV,add_executable 声明目标,target_link_libraries 完成链接。
第一个程序:读取并显示一张图片
main.cpp 完整代码如下:
cpp
#include <opencv2/opencv.hpp> // OpenCV 主头文件
#include <iostream>
using namespace cv; // 常用:Mat、imread 等都在 cv 命名空间
using namespace std;
int main(int argc, char** argv)
{
// 1. 读取图片:IMREAD_COLOR 表示按 3 通道彩色图读取
// 路径请改成你自己电脑上的图片路径
Mat img = imread("sample.jpg", IMREAD_COLOR);
// 2. 判断是否读取成功:empty() 为 true 说明没读到
if (img.empty())
{
cout << "图片读取失败,请检查路径是否正确!" << endl;
return -1;
}
// 3. 打印图片基本信息(宽 x 高、通道数)
cout << "图片尺寸: " << img.cols << " x " << img.rows << endl;
cout << "通道数: " << img.channels() << endl;
// 4. 显示图片,窗口标题为 "AOI 第一张图"
imshow("AOI 第一张图", img);
// 5. 等待按键:参数 0 表示无限等待,直到用户按下任意键
// 没有这一句,窗口会一闪而过甚至直接退出
waitKey(0);
return 0;
}
编译运行
Linux / Ubuntu(直接用 g++ 编译):
g++ main.cpp -o app $(pkg-config --cflags --libs opencv4)
./app
Linux / Ubuntu(用 CMake,推荐):
mkdir build && cd build
cmake ..
make
./app
Windows(用 CMake + VS):
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022"
# 打开生成的 .sln 编译,或在命令行执行 cmake --build . --config Release
逐段讲解
Mat img = imread(...):Mat是 OpenCV 里表示图像的核心类,本质是一块二维像素矩阵。imread负责把磁盘图片解码成Mat。img.empty():这是必须写的防御性检查 。读图失败时img是空的,若直接拿去显示或计算会崩溃。失败常见原因是路径不对或文件不存在。imshow与waitKey:imshow只是"把图画到窗口",真正让窗口刷新、响应鼠标键盘的是waitKey。它同时承担"等待按键"和"事件循环"两个职责,缺一不可。IMREAD_COLOR:读图模式标志。另有IMREAD_GRAYSCALE(灰度,用于大多数检测算法)、IMREAD_UNCHANGED(保留透明通道)等,AOI 里灰度图用得非常多。
运行效果
程序正确运行后,会弹出标题为"AOI 第一张图"的窗口,展示你的测试图片;控制台打印类似:
图片尺寸: 640 x 480
通道数: 3
按键盘任意键,窗口关闭,程序正常退出(返回码 0)。如果打印"图片读取失败",说明图片没找到,按下一节的排查思路检查即可。
常见坑与注意事项
- 找不到头文件
opencv2/opencv.hpp:g++ 编译时没加pkg-config --cflags,或 CMake 里没执行find_package。本质是编译器不知道头文件在哪,补上 include 路径即可。 undefined reference to cv::...:这是典型的链接错误 ,说明编译通过了但没链 OpenCV 库。检查pkg-config --libs是否带上,或 CMake 是否写了target_link_libraries。imshow窗口一闪而过 / 闪退 :几乎都是漏写waitKey。没有它,程序执行完直接返回,窗口来不及显示。- 图片路径含中文 :OpenCV 的
imread在部分平台(尤其 Windows 默认编码下)对中文路径支持不好,可能读出来是空。优先把图片放到工程目录、用英文文件名 ;确需中文路径时再考虑imdecode配合ifstream读取的方案。 - Windows 下报找不到
opencv_world4xx.dll:运行期动态库不在PATH里,把bin目录加进环境变量即可。 - 图片路径用相对路径却读不到:相对路径的基准是"程序运行时的工作目录",不是源码目录。IDE 里运行时注意设置工作目录,或改用绝对路径排查。
小结
本文完成了 AOI 开发的第一块地基:理解了 AOI 是什么、为什么选 C++ + OpenCV,并且在 Windows / Ubuntu 上装好环境,用 CMake 组织了一个最小工程,跑通了"读图 → 判空 → 显示 → 等待按键"的完整流程,还梳理了六个高频坑。
这一步看起来简单,却是后续所有检测算法的前提。环境稳了,接下来无论是灰度化、二值化、形态学去噪,还是轮廓提取与缺陷判定,都能在这套骨架上顺畅展开。建议你现在就动手:建好工程、放一张测试图、把程序跑起来,遇到报错先对照"常见坑"逐一排查------亲手排掉一个坑,比看十遍教程都管用。