C++ 多线程相机速度检测:实时图像显示和速度曲线绘制
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;
}
功能说明
- 相机采图:
capture_thread()线程使用 OpenCV 的VideoCapture类获取相机采集的图像,并使用imshow函数实时显示图像。 - 实时显示图像:
display_thread()线程负责在imshow窗口中实时显示图像。 - 计算速度:
speed_thread()线程使用 OpenCV 的特征点检测函数和匹配函数来计算速度,并使用speed_history数组记录速度历史数据。 - 绘制速度曲线: 主线程使用 Qt 的
QCustomPlot库将speed_history中的速度数据绘制成实时速度曲线。
代码说明
- 互斥锁:
mtx互斥锁用于保护全局变量,确保多个线程安全访问和修改共享数据。 - 退出标志:
quit_flag退出标志用于控制线程的退出,当需要停止程序时,将quit_flag设置为true,所有线程都将结束。 - 速度历史记录:
speed_history数组记录速度历史数据,用于绘制速度曲线。 - 绘图对象:
plot对象是QCustomPlot实例,用于绘制速度曲线。
运行步骤
- 安装 OpenCV 和 Qt 库。
- 将代码保存为
.cpp文件。 - 使用 C++ 编译器编译代码。
- 运行编译后的可执行文件。
注意事项
- 需要将代码中的相机索引(
VideoCapture(0))更改为你的实际相机索引。 - 可以根据需要调整程序中的速度计算方法和参数。
- 可以通过修改
waitKey函数的参数来调整图像显示的刷新频率。
其他
除了使用 OpenCV 和 Qt,还可以使用其他库来实现类似的功能。例如,可以使用其他图形库来绘制速度曲线,或者使用其他多线程库来管理线程。
希望本文能够帮助你理解如何使用 C++ 多线程实现实时相机速度检测。
参考文献
联系方式
如果您有任何问题或建议,请随时联系我。
版权声明
本文由作者原创,版权所有,转载请注明出处。
原文地址: https://www.cveoy.top/t/topic/mU56 著作权归作者所有。请勿转载和采集!