RK3588学习日记(一) OpenCV 摄像头入门从环境搭建到读取并保存第一帧这一篇只做基础验证安装 OpenCV、编译示例、生成测试图片、读取图片以及从摄像头读取一帧并保存结果。暂不讨论 V4L2 细节、DMA-BUF、RGA 或 NPU。1. 这一篇要验证什么在后续学习 V4L2、MPP、RGA 和 RKNN 之前先确认三件事开发板上的 OpenCV 头文件和库可以正常链接程序能把图片读进cv::Mat完成简单处理并写回文件VideoCapture能打开摄像头读到有效帧并输出尺寸和处理结果。没有摄像头时也可以先用示例生成测试图片完成前两项。2. 准备环境在 Debian/Ubuntu 类系统上安装编译工具和 OpenCV 开发包sudoaptupdatesudoaptinstall-ybuild-essential cmake pkg-config libopencv-dev检查 OpenCV 版本pkg-config--modversionopencv4能输出版本号只说明pkg-config找到了 OpenCV最终是否能编译还要由 CMake 的find_package(OpenCV REQUIRED)验证。3. 编译示例以下命令从示例目录执行cdexamples/01_opencvmkdir-pbuildcdbuild cmake..make-j$(nproc)CMake 做了两件事查找 OpenCV并把main.cpp编译成opencv_demo。也可以使用目录里的 Makefile但本文统一使用 CMake 命令。如果编译失败先检查pkg-config--cflags--libsopencv44. 没有摄像头时先生成测试图片./opencv_demo --make-sample sample.jpg示例会生成一张 800×600 的测试图里面包含渐变、圆形、直线和文字。然后处理这张图片./opencv_demo sample.jpg程序会在当前工作目录生成output_img_gray.jpg 灰度图 output_img_blur.jpg 高斯模糊结果 output_img_edge.jpg Canny 边缘结果 output_img_annotated.jpg 画框和文字后的图像这里的img来自程序内部的图片输入标签不是文件名的一部分。实测参考RK3588 / OpenCV 4.5.4[save] 测试图片已生成sample.jpg [img] sample.jpg800 x 600通道数 3 [save] output_img_gray/blur/edge/annotated.jpg生成的文件可用ls -l sample.jpg output_img_*.jpg确认再用下面第 6 节的方法拉回电脑查看。5. 用 VideoCapture 打开摄像头图片链路跑通后再进入摄像头采集。第一步不是猜节点编号而是确认设备身份和采集能力。5.1 先找到摄像头节点RK3588 板子上/dev/video0不一定是摄像头。同一块板会出现大量 video 节点MIPI/CSI 摄像头对应 ISP 与 CIF 通道USB 摄像头对应 UVC 通道还有独立的视频编解码节点如/dev/video-dec0、/dev/video-enc0。直接扫描ls-l/dev/video*但有设备节点不等于能采集。用v4l2-ctl看每个节点的驱动名和卡片类型才能分清哪个是真摄像头v4l2-ctl --list-devices v4l2-ctl-d/dev/video21--info# 看 driver/card/capabilitiesv4l2-ctl-d/dev/video21 --list-formats-ext# 看支持的格式与分辨率以一块插入 USB 摄像头的板子为例lsusb会看到设备而v4l2-ctl --info显示Driver name : uvcvideo Card type : USB Camera: USB Camera Capabilities : Video Capture / Metadata Captureuvcvideo是 USB 摄像头驱动MIPI 摄像头则会是rkisp/rkcif相关的驱动名。把你的实际节点号替换进后面的命令即可。5.2 读取一帧./opencv_demo--camera/dev/video21示例也支持设备索引当摄像头是0或1这类索引时./opencv_demo--camera0程序收到--camera后会按设备路径或数字索引打开摄像头连续读取最多 10 帧让自动曝光和自动白平衡有机会稳定检查最后一帧是否为空打印实际帧宽和高度保存原始帧并执行灰度、模糊、边缘和标注处理。对应的核心逻辑是cv::VideoCapture cap;if(camera_spec.size()1std::isdigit(camera_spec[0]))cap.open(std::stoi(camera_spec));elsecap.open(camera_spec);if(!cap.isOpened()){std::cerr无法打开摄像头\n;return1;}cv::Mat frame;for(inti0;i10cap.read(frame);i){// 预热帧}if(frame.empty()){std::cerr没有读到有效帧\n;return1;}注意这里的VideoCapture是 OpenCV 对摄像头后端的封装。它能否打开某个 MIPI 或 USB 摄像头取决于系统驱动、设备节点和 OpenCV 构建时的后端支持。板端实测时USB 摄像头通过VideoCapture成功取到一帧 640×480 的 BGR 图并处理而板载 MIPI 摄像头rkisp_mainpath因当前 DTS 未配置 sensor 节点即使节点存在也无法出流。下文「常见问题」会再说明这两种情况。6. 一帧图像和 cv::Mat拿到一帧后后续处理就是在不同的cv::Mat之间完成像素变换。OpenCV 默认把彩色图像按 BGR 顺序存储cv::Mat gray;cv::cvtColor(frame,gray,cv::COLOR_BGR2GRAY);cv::Mat blurred;cv::GaussianBlur(gray,blurred,cv::Size(5,5),0);cv::Mat edges;cv::Canny(blurred,edges,50,150);示例还会复制原图进行标注避免直接改写采集到的原始帧cv::Mat annotatedframe.clone();cv::rectangle(annotated,cv::Point(50,50),cv::Point(250,250),cv::Scalar(0,255,0),3);cv::Scalar(0, 255, 0)是 BGR 顺序因此表示绿色。frame.clone()会产生一次 CPU 深拷贝本篇这样写是为了让示例简单后续零拷贝章节会再分析这类复制的代价。摄像头模式的输出文件是frame_cam_raw.jpg 读取到的原始 BGR 帧 output_cam_gray.jpg 灰度图 output_cam_blur.jpg 高斯模糊结果 output_cam_edge.jpg Canny 边缘结果 output_cam_annotated.jpg 标注结果可以用下面的命令把文件拉回电脑scpuser板子IP:/path/to/frame_cam_raw.jpg.scpuser板子IP:/path/to/output_cam_edge.jpg.请把板子IP和实际文件路径替换成自己的值。实测参考USB 摄像头--camera /dev/video21[ WARN:0] ...cap_gstreamer.cpp ... GStreamer warning: unable to start pipeline [cam] 已打开 /dev/video21 [cam] 帧尺寸640 x 480 [save] output_cam_gray/blur/edge/annotated.jpg第一行 GStreamer WARN 是 OpenCV 尝试 GStreamer 后端失败后回退 V4L2 的正常现象不影响采集。程序实际经 V4L2 后端取到一帧 640×480并生成frame_cam_raw.jpg及 4 个处理结果。7. 需要桌面环境时再显示窗口./opencv_demo--camera/dev/videoN--show请把/dev/videoN替换成你实际找到的摄像头节点。--show会调用imshow然后用waitKey(0)等待按键关闭窗口。它不是连续视频预览而是显示当前采集结果并等待用户操作。通过 SSH 登录且没有图形桌面时窗口显示可能失败。示例已经用异常处理保护这条路径但最可靠的验证仍然是保存 JPEG 后用scp查看。8. 常见问题下面按现象整理排查入口。先确认设备、驱动和后端再检查图像格式与显示环境。现象检查方向opencv2/opencv.hpp不存在安装libopencv-dev检查pkg-config路径链接出现undefined reference确认 CMake 链接了${OpenCV_LIBS}/dev/video0不存在查看实际设备节点不要假定一定是video0VideoCapture打不开检查设备权限、驱动和 OpenCV 视频后端读到的帧为空检查设备格式、分辨率和采集是否成功图像颜色异常核对 BGR/RGB 和实际摄像头输出格式SSH 下窗口失败不使用--show改为保存文件输出图像错位或花屏本篇只通过 OpenCV 读取进入 V4L2 章节后再核对 stride 和像素格式有 video 节点但打不开No such device/Operation not permitted该节点无摄像头硬件接入MIPI sensor 未注册、USB 未插。用v4l2-ctl --list-devices和lsusb确认真正的摄像头节点出现GStreamer warning: unable to start pipelineOpenCV 先尝试 GStreamer 后端失败后回退 V4L2不影响采集结果可忽略或安装 gstreamer 插件消除警告--camera 0打不开但--camera /dev/videoX可以索引0对应的是设备枚举不一定是你想用的摄像头改用v4l2-ctl --list-devices确认节点号USB 摄像头往往是靠后的编号如/dev/video21实测补充RK3588 上 USB 摄像头uvcvideo与板载 MIPI 摄像头rkisp/rkcif都可能在/dev/video*里列出大量节点。区分方法是看v4l2-ctl的Driver name/Card type而不是凭编号猜测。板载 MIPI 摄像头若 DTS 未配置 sensor 节点VIDIOC_STREAMON会返回Operation not permitted内核日志出现check rkisp_mainpath link or isp input此时应优先改用 USB 摄像头或先修复 DTS 的 sensor 配置。9. 下一篇本篇使用 OpenCV 的VideoCapture作为入口。下一篇进入 YOLO 模型转 RKNN梳理模型从 PC 到 RK3588 的转换链路并对比量化前后的精度。V4L2、MMAP 与 DMA-BUF 会在后续采集章节展开。