概要
OpenCVを用いて、USBカメラから取得した画像を出力するプログラムを2つのスレッドで実行してみました。USBカメラは1つとして、1つのカメラから取得される画像をセマフォのように割り当て、画像出力もセマフォのように出力しています。
実行環境
次に実行環境を示します。
Soft and Hard | バージョン |
---|---|
Visual Studio | 2017 |
OpneCV | 4.0.0 |
実装したプログラムついて
スレッド間の排他制御はセマフォのように、カウンタを使って実装しました。カウンタが0の時はスレッド1を実行、カウンタが1の時はスレッド2を実行のようにしています。次に、イメージ図を示します。
マーカID取得プログラム
次に作成したマーカID取得プログラムを示します。カメラはUSBカメラを使いました。
multi_thread_with_semaphore.cpp
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include<thread>
#include<time.h>
#include<mutex>
// Global Varidation
cv::VideoCapture cap(1);
cv::Mat frame_thread_first;
cv::Mat frame_thread_second;
int semaphonre_counter = 0;
void GetFrameFromCameraFunction1() {
while (true) {
if (semaphonre_counter == 0) {
cap.read(frame_thread_first);
semaphonre_counter++;
}
}
}
void GetFrameFromCameraFunction2() {
while (true) {
if (semaphonre_counter == 2) {
cap.read(frame_thread_second);
semaphonre_counter++;
}
}
}
void ShowFrameFromCameraFunction1() {
while (true) {
if (semaphonre_counter == 1) {
cv::imshow("WIndow1", frame_thread_first);
const int key = cv::waitKey(1);
if (key == 27) {
exit(EXIT_SUCCESS);
}
else if (key == 50) {
cv::imwrite("th2.png", frame_thread_first);
}
semaphonre_counter++;
}
}
}
void ShowFrameFromCameraFunction2() {
while (true) {
if (semaphonre_counter == 3) {
cv::imshow("WIndow2", frame_thread_second);
const int key = cv::waitKey(1);
if (key == 27) {
exit(EXIT_SUCCESS);
}
else if (key == 52) {
cv::imwrite("th4.png", frame_thread_second);
}
semaphonre_counter = 0;
}
}
}
void StartThread() {
std::thread GetFrameThread1(GetFrameFromCameraFunction1);
std::thread ShowFrameThread1(ShowFrameFromCameraFunction1);
std::thread GetFrameThread2(GetFrameFromCameraFunction2);
std::thread ShowFrameThread2(ShowFrameFromCameraFunction2);
ShowFrameThread1.join();
GetFrameThread1.join();
ShowFrameThread2.join();
GetFrameThread2.join();
}
int main(int argh, char* argv[])
{
StartThread();
}
実装プログラム実行
上記のプログラムを実行した場合の結果を示します。
mutexを使うより格段に速くなりました。どうして、mutexが遅いのについては、調査してみたいと思います。
まとめ
1つのUSBカメラから単純に画像を2つのスレッドで分ける場合には、セマフォのように実装したほうが、画像の更新速度が速いことがわかりました。また、間違っているところや、追加したほうがいい、こういう書き方の方がいいよ!という箇所がありましたら、お教え頂けるととても嬉しいです。