C++ 多线程相机速度检测:实时图像显示和速度曲线绘制

本文介绍使用 C++ 多线程实现实时相机速度检测的方案,包括相机采图、实时图像显示、OpenCV 特征点匹配计算速度和 Qt 绘制速度曲线等功能。示例代码使用 OpenCV、Qt 和多线程技术,并提供详细的注释。

代码示例

#include <iostream>
#include <thread>
#include <mutex>
#include <opencv2/opencv.hpp>
#include "qcustomplot.h"

using namespace std;
using namespace cv;

const int WIDTH = 640;
const int HEIGHT = 480;

mutex mtx; // 互斥锁,用于保护全局变量
bool quit_flag = false; // 退出标志
double speed = 0; // 速度
vector<double> speed_history; // 速度历史记录
QCustomPlot* plot = nullptr; // 绘图对象

// 子线程1:相机采图
void capture_thread() {
    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cerr << "Failed to open camera!" << endl;
        mtx.lock();
        quit_flag = true;
        mtx.unlock();
        return;
    }

    cap.set(CAP_PROP_FRAME_WIDTH, WIDTH);
    cap.set(CAP_PROP_FRAME_HEIGHT, HEIGHT);

    while (true) {
        mtx.lock();
        if (quit_flag) {
            mtx.unlock();
            break;
        }
        mtx.unlock();

        Mat frame;
        cap.read(frame);
        if (frame.empty())
            break;

        mtx.lock();
        imshow("Camera", frame);
        mtx.unlock();
    }
}

// 子线程2:实时显示图像
void display_thread() {
    while (true) {
        mtx.lock();
        if (quit_flag) {
            mtx.unlock();
            break;
        }
        mtx.unlock();

        waitKey(10);
    }
}

// 子线程3:计算速度
void speed_thread() {
    Mat prev_frame, curr_frame;
    vector<KeyPoint> prev_keypoints, curr_keypoints;
    Mat prev_descriptors, curr_descriptors;
    Ptr<ORB> orb = ORB::create();

    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cerr << "Failed to open camera!" << endl;
        mtx.lock();
        quit_flag = true;
        mtx.unlock();
        return;
    }

    cap.set(CAP_PROP_FRAME_WIDTH, WIDTH);
    cap.set(CAP_PROP_FRAME_HEIGHT, HEIGHT);

    cap.read(prev_frame);
    orb->detectAndCompute(prev_frame, noArray(), prev_keypoints, prev_descriptors);

    while (true) {
        mtx.lock();
        if (quit_flag) {
            mtx.unlock();
            break;
        }
        mtx.unlock();

        cap.read(curr_frame);
        if (curr_frame.empty())
            break;

        orb->detectAndCompute(curr_frame, noArray(), curr_keypoints, curr_descriptors);

        vector<DMatch> matches;
        BFMatcher matcher(NORM_HAMMING);
        matcher.match(prev_descriptors, curr_descriptors, matches);

        double sum_distance = 0;
        for (const auto& match : matches) {
            sum_distance += match.distance;
        }
        double avg_distance = sum_distance / matches.size();
        speed = 30.0 / avg_distance;

        prev_frame = curr_frame.clone();
        prev_keypoints = curr_keypoints;
        prev_descriptors = curr_descriptors;

        mtx.lock();
        speed_history.push_back(speed);
        if (plot != nullptr)
            plot->graph(0)->setData(QVector<double>::fromStdVector(speed_history));
        mtx.unlock();
    }
}

// 主线程
int main(int argc, char** argv) {
    namedWindow("Camera");

    // 创建绘图对象
    QCoreApplication app(argc, argv);
    plot = new QCustomPlot();
    plot->addGraph();
    plot->xAxis->setLabel("Time");
    plot->yAxis->setLabel("Speed");
    plot->xAxis->setRange(0, 50);
    plot->yAxis->setRange(0, 100);
    plot->show();

    // 启动子线程
    thread t1(capture_thread);
    thread t2(display_thread);
    thread t3(speed_thread);

    // 主线程循环
    while (true) {
        mtx.lock();
        if (quit_flag) {
            mtx.unlock();
            break;
        }
        mtx.unlock();

        cout << "Speed: " << speed << endl;
        waitKey(100);
    }

    // 等待子线程结束
    t1.join();
    t2.join();
    t3.join();

    // 销毁窗口和绘图对象
    destroyWindow("Camera");
    delete plot;

    return 0;
}

功能说明

  1. 相机采图: capture_thread() 线程使用 OpenCV 的 VideoCapture 类获取相机采集的图像,并使用 imshow 函数实时显示图像。
  2. 实时显示图像: display_thread() 线程负责在 imshow 窗口中实时显示图像。
  3. 计算速度: speed_thread() 线程使用 OpenCV 的特征点检测函数和匹配函数来计算速度,并使用 speed_history 数组记录速度历史数据。
  4. 绘制速度曲线: 主线程使用 Qt 的 QCustomPlot 库将 speed_history 中的速度数据绘制成实时速度曲线。

代码说明

  1. 互斥锁: mtx 互斥锁用于保护全局变量,确保多个线程安全访问和修改共享数据。
  2. 退出标志: quit_flag 退出标志用于控制线程的退出,当需要停止程序时,将 quit_flag 设置为 true,所有线程都将结束。
  3. 速度历史记录: speed_history 数组记录速度历史数据,用于绘制速度曲线。
  4. 绘图对象: plot 对象是 QCustomPlot 实例,用于绘制速度曲线。

运行步骤

  1. 安装 OpenCV 和 Qt 库。
  2. 将代码保存为 .cpp 文件。
  3. 使用 C++ 编译器编译代码。
  4. 运行编译后的可执行文件。

注意事项

  1. 需要将代码中的相机索引(VideoCapture(0))更改为你的实际相机索引。
  2. 可以根据需要调整程序中的速度计算方法和参数。
  3. 可以通过修改 waitKey 函数的参数来调整图像显示的刷新频率。

其他

除了使用 OpenCV 和 Qt,还可以使用其他库来实现类似的功能。例如,可以使用其他图形库来绘制速度曲线,或者使用其他多线程库来管理线程。

希望本文能够帮助你理解如何使用 C++ 多线程实现实时相机速度检测。

参考文献

联系方式

如果您有任何问题或建议,请随时联系我。

版权声明

本文由作者原创,版权所有,转载请注明出处。

C++ 多线程相机速度检测:实时图像显示和速度曲线绘制

原文地址: https://www.cveoy.top/t/topic/mU56 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录