LoginSignup
2
0

More than 5 years have passed since last update.

C++でカメラ画像取得をマルチスレッドやってみる:Semaphore版

Posted at

概要

OpenCVを用いて、USBカメラから取得した画像を出力するプログラムを2つのスレッドで実行してみました。USBカメラは1つとして、1つのカメラから取得される画像をセマフォのように割り当て、画像出力もセマフォのように出力しています。

実行環境

次に実行環境を示します。

Soft and Hard バージョン
Visual Studio 2017
OpneCV 4.0.0

実装したプログラムついて

スレッド間の排他制御はセマフォのように、カウンタを使って実装しました。カウンタが0の時はスレッド1を実行、カウンタが1の時はスレッド2を実行のようにしています。次に、イメージ図を示します。

  • イメージ図 6.png

マーカ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();

}

実装プログラム実行

上記のプログラムを実行した場合の結果を示します。

  • 全体画像 5.png

mutexを使うより格段に速くなりました。どうして、mutexが遅いのについては、調査してみたいと思います。

まとめ

1つのUSBカメラから単純に画像を2つのスレッドで分ける場合には、セマフォのように実装したほうが、画像の更新速度が速いことがわかりました。また、間違っているところや、追加したほうがいい、こういう書き方の方がいいよ!という箇所がありましたら、お教え頂けるととても嬉しいです。

2
0
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0