c++多线程 三个子线程一个子线程调用相机采图一个子线程实时显示图像一个子线程利用opencv特征点匹配计算速度主线程实时显示速度并实时绘制速度曲线
以下是一个简单的示例代码,其中使用OpenCV的VideoCapture类来获取相机采集的图像,使用OpenCV的imshow函数实时显示图像,使用OpenCV的特征点检测函数和匹配函数来计算速度,使用Qt的QCustomPlot库来实时绘制速度曲线。
#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;
}
原文地址: http://www.cveoy.top/t/topic/brOP 著作权归作者所有。请勿转载和采集!