はじめに
前回はスレッドでUSBカメラから映像を取得して表示をしました。
スレッドの処理の章で、
メインスレッドではGUIの処理を、サブスレッドでUSBカメラの取得処理をと言う具合にします。
プログラムが起動している間は、サブスレッドでUSBカメラより映像を取得し続けます。
と記載しましたが、GUIの処理を付加しておりませんでしたので、「PushButton」をクリックして映像を反転させる処理を追加したいと思います。
今まで、前回や前々回と記載してややこしくなっていますので、今回から投稿したタイトルで表記します。
QtでOpenCV(Threadによる取得)
がベースとなっております。
こちらで作成したプロジェクトに機能を追加します。
仕様
上PushButton:回転しないで映像を表示
下PushButton:180度回転した映像を表示
左PushButton:270度回転した映像を表示
右PushButton:90度回転した映像を表示
とします。
UI
PushButtonの追加と名称やオブジェクト名修正
仕様の通り、4つの「PushButton」を追加します。mainwindow.uiを開きます。
「PushButton」を配置するのに、スペースが足りませんので、「Label」を左に移動します。
これで右側にスペースができましたので、「PushButton」を配置します。
QtでHello world!
を参考に、「PushButton」を4つ配置してください。
配置した「PushButton」のテキストがすべて「PushButton」の表記で、操作する人が分かりませんので変更します。
先ず、1番上の「PushButton」をクリックして、左下にある「Text」の「PushButton」を「rotateUp」にします。変更すると「PushButton」の表記か「rotateUp」に変わります。
「objectName」も変更します。
「pushButton」、「pushButton_2」、「pushButton_3」、「pushButton_4」となっておりますので、実装するときに分かり易い名称へ変更します。
「pushButton」を「pushButtonUp」へ変更します。
「pushButton_2」、「pushButton_3」、「pushButton_4」も同様に変更します。
全て修正すると、下記のようになると思います。
イベントを発生させる
「rotateUp」、「rotateDown」、「rotateLeft」、「rotateRight」にクリックのイベントを発生させるようにします。詳しくは、
QtでHello world!
の「イベントを発生させる」を参照してください。
今回の操作で、mainwindo.hとmainwindow.cppに下記が追加されます。
private slots:
void on_pushButtonUp_clicked();
void on_pushButtonDown_clicked();
void on_pushButtonLeft_clicked();
void on_pushButtonRight_clicked();
void MainWindow::on_pushButtonUp_clicked()
{
}
void MainWindow::on_pushButtonDown_clicked()
{
}
void MainWindow::on_pushButtonLeft_clicked()
{
}
void MainWindow::on_pushButtonRight_clicked()
{
}
Ctrl+sで保存し、mainwindow.uiを閉じます。
実装
追加は、「追加rotate」と記載しております。
修正は、「修正rotate」と記載しております。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMessageBox> // 追加
#include <QThread> // 追加
#include "getUsbCamera.h" // 追加
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
getUsbCamera *getUsbCamT; // 追加
private:
Ui::MainWindow *ui;
QImage qtImage; // 追加
unsigned char btnRotate; // 追加rotate
public slots:
void onValueChangedCam(void); // 追加
private slots:
void on_pushButtonUp_clicked();
void on_pushButtonDown_clicked();
void on_pushButtonLeft_clicked();
void on_pushButtonRight_clicked();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 追加(ここから)
getUsbCamT = new getUsbCamera(this);
if(getUsbCamT->initCam()){
btnRotate = POSITION_UP; // 追加rotate
connect(getUsbCamT, SIGNAL(valueChangedCam(void)), this, SLOT(onValueChangedCam(void)));
getUsbCamT->start();
} else {
QMessageBox msgBox(this);
msgBox.setText(tr("カメラがオープンできませんでした。"));
msgBox.setWindowTitle(tr("エラー"));
msgBox.setStandardButtons(QMessageBox::Yes);
msgBox.setDefaultButton(QMessageBox::Yes);
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
exit(0);
}
// 追加(ここまで)
}
MainWindow::~MainWindow()
{
getUsbCamT->Stop = true; // 追加
delete ui;
}
// 追加(ここから)
void MainWindow::onValueChangedCam(void)
{
cv::Mat dst;
// getUsbCamT->getImage(&dst);
getUsbCamT->getImage(&dst, btnRotate); // 修正rotate
qtImage = QImage((const unsigned char*)(dst.data), dst.cols, dst.rows, QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(qtImage));
}
// 追加(ここまで)
void MainWindow::on_pushButtonUp_clicked()
{
btnRotate = POSITION_UP; // 追加rotate
}
void MainWindow::on_pushButtonDown_clicked()
{
btnRotate = POSITION_DOWN; // 追加rotate
}
void MainWindow::on_pushButtonLeft_clicked()
{
btnRotate = POSITION_LEFT; // 追加rotate
}
void MainWindow::on_pushButtonRight_clicked()
{
btnRotate = POSITION_RIGHT; // 追加rotate
}
#ifndef GETUSBCAMERA_H
#define GETUSBCAMERA_H
#include <QThread>
#include <QObject>
// 追加(ここから)
#include <QMutex>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
// 追加(ここまで)
#define POSITION_UP 0 // 追加rotate
#define POSITION_DOWN 1 // 追加rotate
#define POSITION_LEFT 2 // 追加rotate
#define POSITION_RIGHT 3 // 追加rotate
class getUsbCamera : public QThread
{
Q_OBJECT
public:
// getUsbCamera(); 修正のため削除
// 追加(ここから)
getUsbCamera(QObject *parent = 0, bool b = false);
~getUsbCamera();
bool initCam(void);
void run(void);
// void getImage(cv::Mat*); 修正rotateのため削除
void getImage(cv::Mat*, unsigned char); // 修正rotate
bool Stop;
signals:
void valueChangedCam(void);
private:
cv::VideoCapture cap;
cv::Mat frame, dst;
// 追加(ここまで)
};
#endif // GETUSBCAMERA_H
#include "getUsbCamera.h"
// 修正のため削除
//getUsbCamera::getUsbCamera()
// 追加(ここから)
getUsbCamera::getUsbCamera(QObject *parent, bool b) : QThread(parent), Stop(b)
{
}
getUsbCamera::~getUsbCamera()
{
Stop = true;
}
bool getUsbCamera::initCam(void)
{
bool ret = true;
cap.open(0);
if(cap.isOpened()){
cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
} else {
ret = false;
}
return ret;
}
void getUsbCamera::run(void)
{
QMutex mutex;
while(1){
mutex.lock();
if(this->Stop) break;
mutex.unlock();
cap >> frame;
cv::cvtColor(frame, dst, cv::COLOR_BGR2RGB);
emit valueChangedCam();
this->msleep(20);
}
}
/* 修正rotateのため削除
void getUsbCamera::getImage(cv::Mat *image)
{
*image = dst.clone();
}
*/
void getUsbCamera::getImage(cv::Mat *image, unsigned char mode) // 修正rotate
{
// 追加rotate(ここから)
switch(mode){
case POSITION_UP:
*image = dst.clone();
break;
case POSITION_DOWN:
cv::rotate(dst, *image, cv::ROTATE_180);
break;
case POSITION_LEFT:
cv::rotate(dst, *image, cv::ROTATE_90_COUNTERCLOCKWISE);
break;
case POSITION_RIGHT:
cv::rotate(dst, *image, cv::ROTATE_90_CLOCKWISE);
break;
}
// 追加rotate(ここまで)
}
// 追加(ここまで)
build&run
実装が完了しましたら、▶をクリックして、build & run します。
USBカメラの映像(上)
USBカメラの映像(下)
USBカメラの映像(左)
USBカメラの映像(右)
あれっ?って気が付かれている方もおられると思います。
左右のPushButtonをクリックしたときに、Labelの背景が表示しています。
また、上下のときと比べて左右の映像が切れております。
更に映像が左に寄っています。
UIでLabelのgeometryは下記に設定しました。
640
480
映像を左右にすると、Labelの高さが映像の幅になりますので、映像が左右切れてしまいました。
修正してみましょう。
UI修正
windowの高さを下記のように変更
600 → 700
labelの高さを下記のように変更
480 → 640
labelのalignmentを下記のように変更
左揃え → 中央揃え(横方向)
Labelの位置も適切な位置にします。
Ctrl+sで保存し、mainwindow.uiを閉じます。
再度build&run
USBカメラの映像(上)
USBカメラの映像(下)
USBカメラの映像(左)
USBカメラの映像(右)
映像が切れることなく表示しました。
また映像もLabelの中央になっています。
まとめ
映像を回転させるときは、Labelの背景色は無い方が無難だと思います。