C++中的類加多線程代碼修煉之二

背景:在上一篇文章中 寫到了我第一次使用C++使用多個類多個線程進行編程,由于是第一接手“這么大一個工程”,所以還是要有個參照物的,由于我呢之前好幾年一直在看的一個C++代碼工程就是ORB-SLAM了,這個工程使用C++語言,工程內有三個線程,多個類,代碼風格很好,通俗易懂,有很多值得我借鑒和學習的地方,所以我就按照ORB-SLAM工程的思路來組織我的代碼。

前情回顧:

我首先創建了四個類:

(1). Capturing類主要專注于相機相關的操作,比如相機的初始化,圖像獲取,開始,暫停等。

(2). Tracking類主要專注于目標跟蹤相關操作。

(3). System類相當于是一個管理者,就像ORB-SLAM中的System類,完成一些系統初始化的任務,其中我主要讓他完成,兩個線程的創建以及線程之間指針變量的設置(這一點很重要,我剛開始沒做相關設置,導致兩個線程之間數據傳輸時出了問題,下面會講到,嘻嘻)

(4). Frame類,這個類是我后來添加的,目前暫時封裝了“圖像本身”以及圖像的“時間戳”屬性。

兩個線程:我把主線程先保留了出來,又單獨創建了兩個線程

(1). 將Capturing中Run函數(用來實現連續從相機去圖像的工作)作為CaptureThread線程的線程入口。

(2). 將Tracking中Run函數(用來實現目標跟蹤的工作)作為TrackThread線程的線程入口。

我在上一篇文章中https://blog.csdn.net/weixin_38636815/article/details/112848772中講到了我完成了類的創建和線程的創建,并且測試兩個線程可以正常的同步工作,在這片文章中我主要解決的是我在兩個線程之間的數據傳輸過程中遇到的問題。

首先,我要明確我想要的什么,我需要將CaptureThread線程中從相機獲取的圖像傳給TrackingThread線程中去,繼續目標跟蹤處理,兩個線程,CaptureThread線程只負責獲取圖像數據,TrackingThread線程只負責目標跟蹤。但是最重點的是我要把CaptureThread線程中獲取的圖像傳給TrackingThread線程。

我學著ORB-SLAM的樣子,在Tracking類中創建了一個list變量,在Capturing中將獲取的圖像都插入到list中來,這樣在TrackingThread中就可以處理這些圖像了。

System.h

#ifndef SYSTEM_H
#define SYSTEM_H
#include <thread>
#include "../include/Tracking.h"
#include "../include/Capturing.h"namespace FDSST
{
class Tracking;
class CaptureThread;
class System {
public:System();~System();
private:Tracking* mpTracker;Capturing* mpCapturer;bool mbCameraInited;//定義兩個線程std::thread* mptTrackThread;std::thread* mptCaptureThread;
};
}
#endif

System.cpp

#include <thread>
#include "../include/System.h"
namespace FDSST {System::System(){mbCameraInited = false;//創建相機獲取圖像線程mpCapturer = new Capturing();mptCaptureThread = new std::thread(&FDSST::Capturing::Run, mpCapturer);std::cout << "Capture thread has been created" << std::endl;//創建目標跟蹤線程mpTracker = new Tracking();mptTrackThread = new std::thread(&FDSST::Tracking::Run, mpTracker);std::cout << "Tracking thread has been created" << std::endl;}System::~System(){}
}

Capturing.h

#ifndef Capturing_H
#define Capturing_H
#include <iostream>#include <opencv2/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>#include <list>
#include "../include/Tracking.h"
#include "../include/Frame.h"using namespace std;
using namespace cv;namespace FDSST {
class System;
class Tracking;
class Frame;
class Capturing {
public:Capturing();~Capturing();void Run();void Stream();void Pause();void Stop();bool quit;public:Frame mCurrentFrame;
protected:Tracking* mpTracker;
};
}

Capturing.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>#include "../include/Capturing.h"namespace FDSST
{
Capturing::Capturing(){}
Capturing::~Capturing(){}void Capturing::Run()
{//從本地讀入視頻來模擬從相機獲取圖像,要換成自己的視頻路徑呦std::string videoPath = "F:\\Programme\\object_detection\\fdsst\\data\\012.avi";cv::VideoCapture cap(videoPath);if (!cap.isOpened()){std::cout << "視頻打開失敗" << std::endl;return;}while (1){cv::Mat currentImg;double timestamp = (double)cv::getTickCount();cap >> currentImg;if (currentImg.rows <= 0 || currentImg.cols <= 0){break;}//將獲取的圖像實例化為Frame類的對象。Frame* pFrame = new Frame(currentImg, timestamp);//將Frame的指針對象插到在Tracking線程中創建的mlNewFrame的list中mpTracker->InsertFrames(pFrame);cv::imshow("test1", currentImg);cv::waitKey(1);}return;
}
void Capturing::Stream()
{pause_status = false;
}void Capturing::Pause()
{pause_status = true;
}void Capturing::Stop()
{pause_status = true;quit = true;
}

Tracking.h

#ifndef TRACKING_H
#define TRACKING_H
#include <mutex>#include "../include/Frame.h"
#include "../include/Capturing.h"namespace FDSST
{
class Capturing;
class Tracking {
public:Tracking();~Tracking();void Run();void InsertImages(Frame* frame);int FramesInQueue() {std::unique_lock<std::mutex> lock(mMutexNewFrame);return mlNewFrames.size();}void SetCapturer(Capturing* pCapturer);protected://定義互斥鎖變量,確保在TrackThread線程中,在list中取圖像數據時,CaptureThread停止插入操作std::mutex mMutexNewFrame;//定義list變量,存儲從CaptureThread中傳遞的圖像數據。std::list<Frame*> mlNewFrames;Frame* mCurrentFrame;Capturing* mpCapturer;void ProcessNewFrames();bool CheckNewFrames();};
}
#endif

Tracking.cpp

#include <iostream>
#include <windows.h>
#include <mutex>
#include "../include/Capturing.h"
#include "../include/Tracking.h"
namespace FDSST
{Tracking::Tracking(){}Tracking::~Tracking(){}void Tracking::Run(){while (1){if (CheckNewFrames()){ProcessNewFrames();}}}void Tracking::InsertFrames(Frame* frame){std::unique_lock<std::mutex> lock(mMutexNewFrame);mlNewFrames.push_back(frame);}void Tracking::ProcessNewFrames(){std::unique_lock<std::mutex> lock(mMutexNewFrame);mCurrentFrame = mlNewFrames.front();cv::Mat img = mCurrentFrame->mImage;mlNewFrames.pop_front();cv::imshow("test", img);cv::waitKey(1);	}bool Tracking::CheckNewFrames(){std::unique_lock<std::mutex> lock(mMutexNewFrame);return (!mlNewFrames.empty());}
}

Frame.h

#ifndef FRAME_H
#define FRAME_H
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core.hpp>
namespace FDSST
{class Frame{public:Frame();Frame(const cv::Mat& image, const double &timeStamp);private:cv::Mat mImage;double mTimeStamp;};
}
#endif

我寫完上面的代碼進行測試,發現我的mpTracker為空,無法操作。

?于是我就在Capturing類的構造函數new了一個Tracking指針對象。mpTracker = new Tracking;

然后繼續編譯,發現代碼可以通過了,但是我從Tracking類中查看mlNewFrames變量長度,發現一只是0,也就是圖像沒有被插進來,我就很納悶,然后我就又回來研究ORB-SLAM 代碼,對比一下,我哪個地方沒有做好,找來找去,終于發現了,原來是忘了下面這里的設置。

于是我在Captureing類中添加了下面函數

void Capturing::SetTracker(Tracking* pTracker)
{mpTracker = pTracker;
}

在Tracking類中添加下面函數

void Tracking::SetCapturer(Capturing* pCapturer)
{mpCapturer = pCapturer;
}

在System的構造函數中添加下面語句

System::System()
{//創建相機獲取圖像線程mpCapturer = new Capturing();mptCaptureThread = new std::thread(&FDSST::Capturing::Run, mpCapturer);std::cout << "Capture thread has been created" << std::endl;//創建目標跟蹤線程mpTracker = new Tracking();mptTrackThread = new std::thread(&FDSST::Tracking::Run, mpTracker);std::cout << "Tracking thread has been created" << std::endl;//Set pointers between threadsmpTracker->SetCapturer(mpCapturer);mpCapturer->SetTracker(mpTracker);}

經過以上改進CpatureThread中的Frame可以傳送到TrackThread中來了。

感覺好像是他們在互相交換信息。但是我還是不太清楚這樣操作的目的,經過Set函數之后,將mpTracker就不是空了,而是將mpTracker賦值給他,而mpTracker = new Tracking(),這不很像我剛才的補救措施mpTracker = new Tracking;嘛,我的操作不夠專業。

現在終于把這個實現兩個線程之間數據傳輸的代碼實現了,雖然簡單,但對我來說是一次進步,我不需要跟別人比較,只要我今天跟昨天相比有進步,我就感覺這一天過的有意義,我很開心。

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252295.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Primer c++ 第5版pdf

下載地址&#xff1a;網盤下載 內容簡介 這本久負盛名的 C經典教程&#xff0c;時隔八年之久&#xff0c;終迎來史無前例的重大升級。除令全球無數程序員從中受益&#xff0c;甚至為之迷醉的——C 大師 Stanley B. Lippman 的豐富實踐經驗&#xff0c;C標準委員會原負責…

eclispe修改project Explorer字體大小

切換到Eclipse目錄下: D:\JAVA\spring-tool-suite\sts-4.0.2.RELEASE\plugins\org.eclipse.ui.themes_1.2.200.v20180828-1350 找到下面的這個css文件 打開找到下面的位置在下面添加代碼:CTabFolder Tree{font-size: 15px;} 復制代碼重啟Eclipse,就可以看到效果 修改前 修改后…

3-4 第三天 Generator生成器

Generator是ES6里面的新增規范&#xff0c;ES6其實就是ES2015。ES5、ES6、ES7這些術語大家上網一查就都明白了。JavaScript是一個范程&#xff0c;就是我們說的JS。ES就是ECMA Script&#xff0c;是JavaScript標準的書面說法。ES4、5、6、7其實是JS這門語言發展中的不同的版本。…

神奇的事情--長見識了

背景&#xff1a;我的這個工程里有多個命名空間&#xff0c;之所以是這樣是因為&#xff0c;有一個跟蹤算法他本身有幾個namespace,然后我在他的基礎上進行整合代碼&#xff0c;將其作為一個功能接口&#xff0c;供其他函數調用&#xff0c;我在整合代碼時&#xff0c;將我新加…

箭頭函數的使用用法(一)

1 //箭頭函數的一個好處是簡化回調函數2 //箭頭函數沒有參數&#xff0c;就使用圓刮號代表參數部分&#xff1b;3 var f () >5;4 console.log(f());5 //兩個參數的情況&#xff0c;代碼塊只有一條語句&#xff0c;可以省略{}6 var f (a,b)> console.log(ab);7 f(1,3);8…

LinkedList中查詢(contains)和刪除(remove)源碼分析

一、contains源碼分析 本文分析雙向鏈表LinkedList的查詢操作源碼實現。jdk中源程序中&#xff0c;LinkedList的查詢操作&#xff0c;通過contains(Object o)函數實現。具體見下面兩部分程序&#xff1a;① public boolean contains(Object o) {return indexOf(o) ! -1; } ② p…

分塊入門

我貌似和所有的數據結構都有些誤會。。。。。。 在處理一些修改查詢問題的時候&#xff0c;我們可以利用分治的思想&#xff0c;比如說把一個線性的數據不斷分成一棵二叉樹&#xff0c;也就是我們所說的線段樹&#xff0c;這樣我們就可以在logn的時限里做到修改和查詢。同理我們…

開始使用gitlab

不得不說&#xff0c;我真不是一個合格的程序猿&#xff0c;工作馬上兩年了&#xff0c;github和gitlab用的一點也不熟練&#xff0c;每次興致來了就搞幾下&#xff0c;可是每次都淺嘗輒止&#xff0c;不求甚解&#xff0c;時間一長&#xff0c;上一次練習的步驟就都記不起來了…

Spark 2.2.0 文檔中文版 Collaborative Filtering 協同過濾 JAVA推薦系統

協同過濾常用于推薦系統&#xff0c;這項技術旨在填補 丟失的user-item關聯矩陣 的條目&#xff0c;spark.ml目前支持基于模型的協同過濾&#xff08;用一些丟失條目的潛在因素在描述用戶和產品&#xff09;。spark.ml使用ALS&#xff08;交替最小二乘法&#xff09;去學習這些…

淘寶top平臺調用接口響應時間優化

我的專欄地址&#xff1a;我的segmentfault,歡迎瀏覽 一、背景 調用top接口的響應時間長&#xff08;160ms左右&#xff09;&#xff0c;超時和連接異常頻繁發生。導致消息組件消費工程的tps遇到瓶頸&#xff08;單實例單消息隊列250tps&#xff09;&#xff0c;只能通過增加實…

樹上倍增一些理解和寫法

樹上倍增可以比較容易求得i節點的第k個父親&#xff0c;我們定義一個二維數組fa[i][j]代表節點i的第2^j個父親&#xff0c;關于有什么用我們等會再說&#xff0c;現在先學會怎么去求這個fa數組 我們可以通過從根節點開始一遍dfs求得所有fa數組&#xff0c;首先我們發現fa數組有…

圖像去畸變和添加畸變

背景&#xff1a;最近的項目中用到的圖像去畸變的知識&#xff0c;剛開始是直接調用opencv中提供的函數cv::initUndistortRectifyMap()和cv::remap()函數&#xff0c;實現圖像的全局去畸變&#xff0c;但是由于圖像的分辨率很高&#xff0c;再加上&#xff0c;實際過程中我們只…

win10上編譯libharu庫

背景&#xff1a; 最近的項目需要自動的生成pdf文件&#xff0c;我在網上查看相關的資料&#xff0c;發現目前比較流行的生成pdf文件的庫有兩個&#xff0c;一個是libpdf&#xff0c;另一個是libharu。libpdf個人使用時免費的但是商業使用就需要收費了&#xff0c;否則得到的p…

爬蟲——正則表達式re模塊

為什么要學習正則表達式 實際上爬蟲一共就四個主要步驟&#xff1a; 明確目標&#xff1a;需清楚目標網站爬&#xff1a;將所有的目標網站的內容全部爬下來取&#xff1a;在爬下來的網站內容中去掉對我們沒有用處的數據&#xff0c;只留取我們需要的數據處理數據&#xff1a;按…

深入Spring Boot:快速集成Dubbo + Hystrix

2019獨角獸企業重金招聘Python工程師標準>>> 背景 Hystrix 旨在通過控制那些訪問遠程系統、服務和第三方庫的節點&#xff0c;從而對延遲和故障提供更強大的容錯能力。Hystrix具備擁有回退機制和斷路器功能的線程和信號隔離&#xff0c;請求緩存和請求打包&#xff…

BZOJ2333 [SCOI2011]棘手的操作 【離線 + 線段樹】

題目 有N個節點&#xff0c;標號從1到N&#xff0c;這N個節點一開始相互不連通。第i個節點的初始權值為a[i]&#xff0c;接下來有如下一些操作&#xff1a; U x y: 加一條邊&#xff0c;連接第x個節點和第y個節點 A1 x v: 將第x個節點的權值增加v A2 x v: 將第x個節點所在的連通…

opencv圖像仿射變換和普通旋轉

背景&#xff1a;今天需要對程序生成的圖像進行旋轉90度和下采樣操作&#xff0c;當然還有改變圖像類型的操作&#xff0c;就是把原來.png的圖像轉換為.jpg的圖像&#xff0c;主要是我目前使用libharu庫&#xff0c;無法成功從本地加載png圖像到pdf中去&#xff0c;不得不使用j…

討厭麻煩的ora 01722無效數字

webservice開發過程中&#xff0c;數據庫由原來的oracle改為現在的sql server。然后重新調試&#xff0c;結果報出ora 01722無效數字的錯誤。 由于連接oracle數據庫的時候并沒有問題&#xff0c;所以一開始我以為是數據庫不同&#xff0c;導致部分數據類型差異&#xff0c;&…

CSS樣式:覆蓋規則

規則一&#xff1a;由于繼承而發生樣式沖突時&#xff0c;最近祖先獲勝。 CSS的繼承機制使得元素可以從包含它的祖先元素中繼承樣式&#xff0c;考慮下面這種情況: <html><head><title>rule 1</title><style>body {color:black;}p {color:blue;}…

try{}里有一個 return 語句,那么緊跟在這個 try 后的 finally {}里的 code 會 不會被執行,什么時候被執行,在 return 前還是后?...

這是一道面試題&#xff0c;首先finally{}里面的code肯定是會執行的&#xff0c;至于在return前還是后&#xff0c; 看答案說的是在return后執行&#xff0c;我覺得不對&#xff0c;百度了一下&#xff0c;有說return前的&#xff0c;有說return后的&#xff0c;還有return中間…