1. 图像采集与格式转换

任务说明

本案例完成嵌入式GPU图像处理流水线的第一级:从摄像头采集原始图像帧,并将其转换为后续处理所需的RGB888格式。以V4L2作为摄像头采集接口,使用OpenCV完成格式转换,输出转换后的帧供下游模块使用。

环境依赖

  • Linux系统(含V4L2驱动),摄像头设备节点 /dev/video0
  • OpenCV(含imgproc、core模块),编译时链接 opencv_core opencv_imgproc
  • CMake ≥ 3.10,C++11及以上编译器

关键完整代码

// frame_capture.h
#pragma once
#include <opencv2/core.hpp>
#include <string>

class FrameCapture {
public:
    bool open(const std::string& device, int width, int height);
    bool read(cv::Mat& rgbFrame);
    void release();
private:
    cv::VideoCapture cap;
    int outWidth, outHeight;
};

// frame_capture.cpp
#include "frame_capture.h"
#include <opencv2/imgproc.hpp>

bool FrameCapture::open(const std::string& device, int width, int height) {
    outWidth = width;
    outHeight = height;
    cap.open(device, cv::CAP_V4L2);
    if (!cap.isOpened()) return false;
    cap.set(cv::CAP_PROP_FRAME_WIDTH, width);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);
    cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M','J','P','G'));
    return true;
}

bool FrameCapture::read(cv::Mat& rgbFrame) {
    cv::Mat rawFrame;
    if (!cap.read(rawFrame)) return false;
    // 摄像头输出为BGR(V4L2默认),转换为RGB供下游处理
    cv::cvtColor(rawFrame, rgbFrame, cv::COLOR_BGR2RGB);
    return true;
}

void FrameCapture::release() {
    if (cap.isOpened()) cap.release();
}

// main.cpp
#include "frame_capture.h"
#include <iostream>

int main() {
    FrameCapture fc;
    if (!fc.open("/dev/video0", 640, 480)) {
        std::cerr << "Failed to open camera" << std::endl;
        return -1;
    }
    cv::Mat rgbFrame;
    for (int i = 0; i < 30; ++i) {  // 采集30帧验证
        if (!fc.read(rgbFrame)) {
            std::cerr << "Frame read failed at index " << i << std::endl;
            fc.release();
            return -1;
        }
    }
    std::cout << "Captured 30 frames, size: "
              << rgbFrame.cols << "x" << rgbFrame.rows
              << ", channels: " << rgbFrame.channels() << std::endl;
    std::cout << "Pixel (10,10) RGB: "
              << (int)rgbFrame.at<cv::Vec3b>(10,10)[0] << ","
              << (int)rgbFrame.at<cv::Vec3b>(10,10)[1] << ","
              << (int)rgbFrame.at<cv::Vec3b>(10,10)[2] << std::endl;
    fc.release();
    return 0;
}

CMake配置

cmake_minimum_required(VERSION 3.10)
project(frame_capture)
find_package(OpenCV REQUIRED COMPONENTS core imgproc)
add_executable(capture main.cpp frame_capture.cpp)
target_link_libraries(capture ${OpenCV_LIBS})

编译与运行

mkdir build && cd build
cmake ..
make
./capture

验证方法

  • 采集成功标志:程序输出 Captured 30 frames, size: 640x480, channels: 3,且无错误信息。
  • 格式正确性:输出中 channels: 3 表明为三通道图像;打印的像素值范围应在0~255之间,且R、G、B三个分量数值合理(非全零或全255)。
  • 帧连续性:连续30帧读取无中断,说明采集链路稳定。

若摄像头输出格式非MJPEG(如YUYV),可删除 cap.set(cv::CAP_PROP_FOURCC, ...) 行,V4L2将使用默认格式,OpenCV会自动完成到BGR的转换,后续 cvtColor 仍保证输出为RGB。