当前位置: 首页 > article >正文

OpenCV多线程编程:从单线程到多线程的视频处理

一、最简单的摄像头显示程序让我们从最基础的版本开始一个单线程程序直接从摄像头读取并显示画面。基础版本代码#include iostream #include opencv2/opencv.hpp using namespace std; int main() { // 打开摄像头默认摄像头编号0 cv::VideoCapture cap(0); if (!cap.isOpened()) { cerr Error: Could not open camera! endl; return -1; } cv::Mat frame; while (true) { cap frame; // 读取一帧 if (frame.empty()) { cerr Error: Empty frame! endl; break; } cv::imshow(Camera, frame); // 显示画面 char key cv::waitKey(1); if (key q || key Q) { break; // 按q键退出 } } cap.release(); cv::destroyAllWindows(); return 0; }基础版本的特点优点简单直接易于理解缺点所有操作都在一个线程中执行如果添加复杂的图像处理会导致画面卡顿二、尝试使用线程初学者可能会尝试将摄像头读取放入单独的线程#include iostream #include opencv2/opencv.hpp #include thread using namespace std; void captureThread() { cv::VideoCapture cap(0); if (!cap.isOpened()) { std::cerr Error: Could not open camera! std::endl; return; } cv::Mat frame; while (true) { cap frame; if (frame.empty()) break; cv::imshow(Camera, frame); // 错误在子线程中显示 char key cv::waitKey(1); if (key q || key Q) break; } cap.release(); cv::destroyAllWindows(); } int main() { thread captureVideo(captureThread); captureVideo.join(); return 0; }三、再进一步使用双线程实现#include iostream #include opencv2/opencv.hpp #include thread #include mutex #include atomic using namespace std; // 共享数据 cv::Mat sharedFrame; mutex mtx; atomicbool running(true); // 线程1负责捕获视频帧 void captureThread() { cv::VideoCapture cap(0); if (!cap.isOpened()) { cerr Error: Could not open camera! endl; running false; return; } cv::Mat frame; while (running) { cap frame; if (frame.empty()) { cerr Error: Empty frame! endl; break; } // 使用互斥锁保护共享数据 lock_guardmutex lock(mtx); frame.copyTo(sharedFrame); } cap.release(); } // 线程2负责处理和显示 void displayAndProcessThread() { cv::namedWindow(Camera, cv::WINDOW_AUTOSIZE); while (running) { cv::Mat frame; // 获取最新的帧 { lock_guardmutex lock(mtx); if (!sharedFrame.empty()) { sharedFrame.copyTo(frame); } } if (!frame.empty()) { // 在这里添加你的图像处理代码 // 示例1添加文字 string text Hello OpenCV!; cv::putText(frame, text, cv::Point(50, 50), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 255, 0), 2); // 示例2添加时间戳信息 cv::putText(frame, Press q to quit, cv::Point(10, frame.rows - 10), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); // 显示处理后的画面 cv::imshow(Camera, frame); } // 检查退出条件 char key cv::waitKey(30); if (key q || key Q) { running false; break; } } cv::destroyAllWindows(); } int main() { cout Program started. Press q to quit. endl; // 创建两个线程 thread capture(captureThread); thread display(displayAndProcessThread); // 等待线程结束 display.join(); capture.join(); cout Program terminated. endl; return 0; }四、代码解析1. 线程同步机制mutex mtx; // 互斥锁防止数据竞争 atomicbool running; // 原子变量控制线程结束互斥锁确保同一时刻只有一个线程访问共享数据原子变量安全地在多线程间传递状态信息2. 线程分工线程职责说明captureThread捕获视频帧持续从摄像头读取存入共享变量displayAndProcessThread处理和显示获取帧添加特效显示画面3. 关键代码说明// 保护共享数据的访问 { lock_guardmutex lock(mtx); // 自动加锁解锁 frame.copyTo(sharedFrame); // 安全的拷贝 }五、进阶添加更多图像处理效果你可以在显示线程中添加各种OpenCV特效// 在显示线程的处理部分添加 // 1. 转为灰度图 cv::Mat gray; cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); // 2. 边缘检测 cv::Mat edges; cv::Canny(gray, edges, 50, 150); // 3. 人脸检测需要haar cascade文件 // cv::CascadeClassifier faceCascade; // faceCascade.load(haarcascade_frontalface_default.xml); // vectorcv::Rect faces; // faceCascade.detectMultiScale(gray, faces); // 4. 添加帧率显示 static int frameCount 0; static auto startTime chrono::steady_clock::now(); frameCount; auto currentTime chrono::steady_clock::now(); auto elapsed chrono::duration_castchrono::seconds(currentTime - startTime).count(); if (elapsed 1) { double fps frameCount / elapsed; cout FPS: fps endl; frameCount 0; startTime currentTime; }六、总结单线程 vs 双线程对比特性单线程双线程实现复杂度简单中等响应性好极好处理复杂任务会卡顿流畅CPU利用率一般更好代码可维护性简单良好多线程编程要点正确使用互斥锁保护共享数据避免死锁注意加锁顺序使用原子变量控制线程状态确保主线程等待子线程结束OpenCV的显示操作必须在主线程改进点有朋友说我这个会导致使用的那个线程空转然后上面那个如果挂了底下一直阻塞。的确是有这个问题我的出发点是最简单的实现既然这么说了那就优化一下#include iostream #include opencv2/opencv.hpp #include thread using namespace std; cv::Mat shareFrame; atomicbool running(true); mutex mtx; condition_variable condin_v; bool frameReady false; void captureThread() { cv::VideoCapture cap(0); if (!cap.isOpened()) { std::cerr Error: Could not open camera! std::endl; running false; condin_v.notify_all(); return; } cv::Mat frame; cap.set(cv::CAP_PROP_FPS, 30); while (running) { cap frame; if (frame.empty()) { std::cerr Error: Empty frame! std::endl; break; } { lock_guardmutex lock(mtx); frame.copyTo(shareFrame); frameReady true; } condin_v.notify_one(); this_thread::sleep_for(chrono::microseconds(33)); } cap.release(); condin_v.notify_all(); } void displayAndProcessThread() { cv::namedWindow(Camera, cv::WINDOW_AUTOSIZE); cv::Mat frame; while (running) { { unique_lockmutex lock(mtx); condin_v.wait(lock, [] {return frameReady || !running; }); if (!running) break; if (!shareFrame.empty()) { shareFrame.copyTo(frame); frameReady false; } } if (!frame.empty()) { string text Hello Opencv!; cv::putText(frame, text, cv::Point(50, 50), cv::FONT_HERSHEY_DUPLEX, 1.0, cv::Scalar(0, 255, 0), 2); cv::imshow(Camera, frame); } char key cv::waitKey(30); if (key Q || key q) { running false; condin_v.notify_all(); break; } } cv::destroyAllWindows(); } int main() { thread captureVideo(captureThread); thread display(displayAndProcessThread); captureVideo.join(); display.join(); return 0; }时间 → 生产者线程 | 消费者线程 --------------------|-------------------- 获取锁 | 生产帧 | (可能正在等待) frameReady true | 释放锁 | notify_one() ------→ 被唤醒 | 尝试获取锁 | 获取锁成功 | 检查 frameReady true | 消费帧 | frameReady false | 释放锁 | 处理并显示帧

相关文章:

OpenCV多线程编程:从单线程到多线程的视频处理

一、最简单的摄像头显示程序让我们从最基础的版本开始&#xff1a;一个单线程程序&#xff0c;直接从摄像头读取并显示画面。基础版本代码#include <iostream> #include <opencv2/opencv.hpp> using namespace std;int main() {// 打开摄像头&#xff08;默认摄像头…...

Jetson Orin Nano 上跑 DeepSeek 模型实测:1.5B 和 7B 哪个更香?附完整部署流程

Jetson Orin Nano 深度评测&#xff1a;1.5B vs 7B 模型实战指南 当边缘计算遇上大语言模型&#xff0c;如何在资源受限的硬件上实现最优性能&#xff1f;作为英伟达边缘计算产品线的明星设备&#xff0c;Jetson Orin Nano凭借其紧凑体积和强大算力&#xff0c;成为众多开发者在…...

蒙特卡洛模拟的颠覆性突破:OpenMC如何通过多源采样与方差缩减技术解决计算效率瓶颈

蒙特卡洛模拟的颠覆性突破&#xff1a;OpenMC如何通过多源采样与方差缩减技术解决计算效率瓶颈 【免费下载链接】openmc OpenMC Monte Carlo Code 项目地址: https://gitcode.com/gh_mirrors/op/openmc 在核工程、粒子物理和辐射屏蔽等领域&#xff0c;蒙特卡洛模拟一直…...

Xournal++终极指南:免费手写笔记与PDF批注完整教程

Xournal终极指南&#xff1a;免费手写笔记与PDF批注完整教程 【免费下载链接】xournalpp Xournal is a handwriting notetaking software with PDF annotation support. Written in C with GTK3, supporting Linux (e.g. Ubuntu, Debian, Arch, SUSE), macOS and Windows 10. S…...

Open-AutoGLM自动化测试:用自然语言编写移动应用测试用例

Open-AutoGLM自动化测试&#xff1a;用自然语言编写移动应用测试用例 1. 项目概述 Open-AutoGLM是由智谱AI开源的一款革命性手机端智能助理框架&#xff0c;专为自动化手机操作而设计。该项目基于AutoGLM架构构建&#xff0c;采用Apache-2.0开源协议&#xff0c;完全免费且支…...

Arduino非阻塞编程:Pin与WaitDo轻量级嵌入式工具库

1. 项目概述HDW-Utils 是一个面向 Arduino 平台的轻量级嵌入式工具库&#xff0c;其核心设计目标并非提供底层硬件驱动&#xff0c;而是解决嵌入式开发中高频出现的代码重复性、结构松散性与阻塞式延时滥用三大工程痛点。该库以“硬件开发者的实用主义”为出发点&#xff0c;通…...

鸽姆智库真理纪元白皮书(学术修订版)真理纪元:贾子科学定理与人类逻辑主权的学术纲要

鸽姆智库真理纪元白皮书&#xff08;学术修订版&#xff09;真理纪元&#xff1a;贾子科学定理与人类逻辑主权的学术纲要摘要《真理纪元》以贾子科学定理为理论基石&#xff0c;旨在修正波普尔证伪主义百余年间对科学认知范式的垄断影响。本文以112作为科学体系的基础公理与确定…...

真理纪元:贾子科学定理与人类逻辑主权的学术白皮书

真理纪元&#xff1a;贾子科学定理与人类逻辑主权的学术白皮书作者单位&#xff1a;鸽姆智库&#xff08;GG3M Think Tank&#xff09;作者简介&#xff1a;贾子&#xff08;Kucius&#xff09;&#xff0c;研究员&#xff0c;鸽姆智库&#xff08;GG3M Think Tank&#xff09;…...

Java全栈开发面试实战:从基础到项目落地的完整技术旅程

Java全栈开发面试实战&#xff1a;从基础到项目落地的完整技术旅程 面试场景描述 在一家知名互联网大厂&#xff0c;一位名叫李晨阳的28岁程序员正在接受一场紧张而富有挑战性的面试。他拥有计算机科学与技术硕士学位&#xff0c;有5年全栈开发经验&#xff0c;曾参与多个大型项…...

猫抓扩展完整配置指南:从零开始掌握浏览器资源嗅探

猫抓扩展完整配置指南&#xff1a;从零开始掌握浏览器资源嗅探 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为网页上的视频无法下载而烦恼吗…...

基于Matlab/Simulink的直流电机双闭环调速系统参数优化与动态响应分析

1. 直流电机双闭环调速系统基础认知 第一次接触直流电机双闭环调速系统时&#xff0c;我被那一堆专业术语绕得头晕——什么ASR、ACR、转速环电流环&#xff0c;感觉像在听天书。后来在实际项目中摸爬滚打才发现&#xff0c;这套系统本质上就是个"双保险"设计。想象一…...

Phi-4-mini-reasoning效果展示:数学符号识别+语义理解+推理三重能力

Phi-4-mini-reasoning效果展示&#xff1a;数学符号识别语义理解推理三重能力 1. 模型概览 Phi-4-mini-reasoning是一款3.8B参数的轻量级开源模型&#xff0c;专为数学推理、逻辑推导和多步解题等强逻辑任务设计。这款由Azure AI Foundry推出的模型主打"小参数、强推理、…...

实战应用开发:基于快马平台构建带监控和定时任务的c盘管理大师

今天想和大家分享一个非常实用的项目开发经验——如何用Python快速打造一个功能完备的C盘管理工具。作为一个经常被C盘爆满困扰的程序员&#xff0c;我决定把这个痛点转化为一个完整的桌面应用解决方案。 项目需求分析 首先明确核心需求&#xff1a;我们需要一个能实时监控C盘空…...

赛马娘DMM版汉化优化终极指南:三分钟打造完美中文体验

赛马娘DMM版汉化优化终极指南&#xff1a;三分钟打造完美中文体验 【免费下载链接】umamusume-localify Localify "ウマ娘: Pretty Derby" DMM client 项目地址: https://gitcode.com/gh_mirrors/um/umamusume-localify 还在为赛马娘DMM版的日文界面而头疼吗&…...

告别死记硬背:用GitHub笔记和实战思维重新理解电路与电子学

告别死记硬背&#xff1a;用GitHub笔记和实战思维重新理解电路与电子学 电路与电子学这门课&#xff0c;常常让计算机专业的学生又爱又恨。爱的是它揭示了计算机硬件底层的奥秘&#xff0c;恨的是那些繁琐的公式和抽象的概念。但问题真的出在课程本身吗&#xff1f;或许我们需…...

Realtek 8922AE WiFi 7网卡驱动固件版本不匹配实战指南:从问题诊断到长效维护

Realtek 8922AE WiFi 7网卡驱动固件版本不匹配实战指南&#xff1a;从问题诊断到长效维护 【免费下载链接】rtw89 Driver for Realtek 8852AE, an 802.11ax device 项目地址: https://gitcode.com/gh_mirrors/rt/rtw89 在Linux系统中&#xff0c;网卡驱动是连接网络的核…...

提升游戏资源管理效率:Steam清单获取的自动化解决方案

提升游戏资源管理效率&#xff1a;Steam清单获取的自动化解决方案 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 你是否曾遇到想要备份Steam游戏却不知从何下手&#xff1f;或者尝试解析游戏文…...

SEO_详解SEO优化中站内与站外优化的区别

SEO优化中站内与站外优化的区别详解 在当今的网络世界&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;是每一个网站主人都必须掌握的技能。SEO优化主要分为站内优化和站外优化&#xff0c;两者在策略和目标上有着显著的区别。本文将详细解析这两者的区别&#xff0c;并为…...

基于springboot+vue高校课堂管理系统hx0546FEZB

文章目录详细视频演示技术介绍功能介绍核心代码系统效果图源码获取详细视频演示 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 技术介绍 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomca…...

Nature论文ELLMER拆解:具身智能为什么需要RAG技术?从知识库设计到工业落地

具身智能与RAG技术&#xff1a;从知识库设计到工业落地的深度实践 当机器人需要理解"请帮我拿一杯水"这样简单的指令时&#xff0c;背后隐藏着怎样的认知挑战&#xff1f;传统工业机器人依靠精确编程完成重复动作&#xff0c;但在面对动态环境时往往束手无策。具身智…...

基于springboot+vue房屋拆迁管理系统hx0514Z1A1

文章目录详细视频演示技术介绍功能介绍核心代码系统效果图源码获取详细视频演示 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 技术介绍 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomca…...

如何用TPFanCtrl2解决ThinkPad散热难题:5个智能控制进阶技巧与实战案例

如何用TPFanCtrl2解决ThinkPad散热难题&#xff1a;5个智能控制进阶技巧与实战案例 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 一、重新定义散热控制&#xff1a;T…...

从FLOPS到TOPS:深入解析算力单位及其在AI芯片中的应用

1. 算力单位&#xff1a;从FLOPS到TOPS的进化史 第一次接触FLOPS这个术语时&#xff0c;我正试图比较两款显卡的性能。当时完全被各种"FLOP"搞晕了头&#xff0c;直到后来在实际项目中调试AI模型时&#xff0c;才真正理解了这些算力单位背后的意义。FLOPS&#xff0…...

告别无效开荒:Path of Building PoE2如何让你的角色构建效率提升300%

告别无效开荒&#xff1a;Path of Building PoE2如何让你的角色构建效率提升300% 【免费下载链接】PathOfBuilding-PoE2 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding-PoE2 当你第10次洗点天赋树却依然打不过剧情BOSS&#xff0c;当你花费数小时研…...

硬件电路进阶指南(一)——深度解析MOS管的关键参数与选型策略

1. 为什么MOS管选型是硬件工程师的必修课 第一次设计电源电路时&#xff0c;我犯了个低级错误——随手选了个标称电流20A的MOS管&#xff0c;结果样机批量烧毁。拆解发现MOS管内部焊线熔断&#xff0c;而实际电路电流才15A。这个惨痛教训让我明白&#xff1a;参数表上的数字都…...

DDrawCompat终极指南:让经典老游戏在Windows 10/11完美运行的免费方案

DDrawCompat终极指南&#xff1a;让经典老游戏在Windows 10/11完美运行的免费方案 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mi…...

Qwen3-ForcedAligner-0.6B语音强制对齐实战:基于LLM的时间戳预测

Qwen3-ForcedAligner-0.6B语音强制对齐实战&#xff1a;基于LLM的时间戳预测 1. 引言 你有没有遇到过这样的情况&#xff1a;手里有一段音频和对应的文字稿&#xff0c;想要知道每个词在音频中的具体位置&#xff1f;比如给视频加字幕时&#xff0c;需要精确到每个字的出现时…...

Kook Zimage真实幻想Turbo常见问题解决:生成全黑图?显存不足?看这篇就够了

Kook Zimage真实幻想Turbo常见问题解决&#xff1a;生成全黑图&#xff1f;显存不足&#xff1f;看这篇就够了 你是不是已经迫不及待地部署好了Kook Zimage真实幻想Turbo&#xff0c;准备大展身手创作奇幻大片&#xff0c;结果一运行&#xff0c;要么生成一张全黑的图片&#…...

新手入门transformer不再难:用快马生成可运行、带详解的注意力机制代码

最近在学习深度学习中的transformer模型&#xff0c;发现很多教程要么太理论化&#xff0c;要么代码注释不够详细。作为新手&#xff0c;我特别希望能有一份带详细中文注释、可以实际运行的代码来帮助理解。经过一番摸索&#xff0c;发现用InsCode(快马)平台可以很好地解决这个…...

小说下载与数字图书馆构建:开源工具novel-downloader完全指南

小说下载与数字图书馆构建&#xff1a;开源工具novel-downloader完全指南 【免费下载链接】novel-downloader 一个可扩展的通用型小说下载器。 项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader 在数字阅读时代&#xff0c;读者常面临三大困境&#xff1a…...