Programming/Qt

[도서 실습] Qt 5 and OpenCV 4 Computer Vision – The Gazer Application 1편 - 화면 생성(완성된 소스 확인)

변화의 물결1 2024. 3. 30. 00:04

 

 

안녕하세요.

 

  Gazer Application을 만들어 보기 전에 기능과 화면 구성에 대해서 이전 내용에서 확인해 보았습니다. 이제는 실제 Qt로 개발하는 것을 진행해 보겠습니다. 우선 이전 내용에서 말한 것처럼 기존 소스가 잘 작동하는 것인지 확인하고 시작하겠습니다.


 

1. 원본 소스 프로그램 실행

 

  - 몇 가지 내용 수정하고 소스를 컴파일해서 실행 시면 문제없이 카메라 영상을 볼 수 있습니다. 그리고 모션 변화가 있을 때도 감지되는 것을 확인할 수 있습니다. 그래서 책 내용처럼 추가해서 만들어 보도록 하겠습니다. 그러나 원본 소스를 실행하려면 몇 가지 수정 후 실행해야 합니다.

 

1) 수정해야 할 부분

 

 - 첫 번째로 Gazer.pro 파일에 OpenCV 경로를 지정해 주고 필요한 라이브러리도 함께 입력해주어야 합니다. 이전 내용처럼 OpenCV 경로만 추가했다면 아래와 같이 에러가 발생할 수 있습니다.

opencv error: undefined reference to `cv::VideoCapture::VideoCapture()' 에러가 발생합니다.

 

 

win32 {

    INCLUDEPATH += D:/opencv/release/install/include
    LIBS += -Ld:/opencv/release/install/x64/mingw/bin \
     -lopencv_core453 \
     -lopencv_imgproc453 \
     -lopencv_imgcodecs453 \
     -lopencv_video453 \
     -lopencv_videoio453
}

 

 

 - 두 번째로 소스상에 카메라 아이디가 2로 되어 있어서 사용자가 사용하는 카메라가 나타나지 않을 수 있습니다. 컴퓨터에 부착된 카메라마다 인덱스(ID)가 부여되기 때문에 기본적인 웹캠이나 USB 카메라이면 ‘0’으로 camID 번호를 변경하면 됩니다.

 

 

void MainWindow::openCamera()
{
    if(capturer != nullptr) {
        // if a thread is already running, stop it
        capturer->setRunning(false);
        disconnect(capturer, &CaptureThread::frameCaptured, this, &MainWindow::updateFrame);
        disconnect(capturer, &CaptureThread::fpsChanged, this, &MainWindow::updateFPS);
        disconnect(capturer, &CaptureThread::videoSaved, this, &MainWindow::appendSavedVideo);
        connect(capturer, &CaptureThread::finished, capturer, &CaptureThread::deleteLater);
    }
    // I am using my second camera whose Index is 2.  Usually, the
    // Index of the first camera is 0.
    int camID = 0;

 

 

 

2) 실행결과

 

 - “File->Open Camera”를 선택하면 이상 없이 카메라 영상이 나오는 것을 확인할 수 있습니다.

 

 

 

 

2. GazerW UI 설계

 

 - Project 이름은 GazerW로 해서 새로운 프로젝트를 생성합니다. 기본 클래스는 MainWindow로 설정하고, Generate form 체크를 해제합니다. 이유는 동적으로 컴포넌트를 생성해 주기 위해서입니다.

 

 

 

 

 - 선언은 mainwindow.h파일에 하고 구현은 mainwindow.cpp에 하면 됩니다.

 

1) 변수 생성

 

 - mainwindow.h 파일에 메뉴 관련된 변수를 선언합니다.

   

 

      private:
         QMenu *fileMenu;

         QAction *cameraInfoAction;
         QAction *openCameraAction;
         QAction *exitAction;

 

 

- 영상(이미지 프레임)을 보여줄 영상 영역을 위한 변수를 만들어 줍니다.

 

 

        QGraphicsScene *imageScene;
        QGraphicsView *imageView;

 

 

 - 감지된 이미지와 상태 등 하단부 컴포넌트를 선언해 줍니다.

   

 

         QCheckBox *monitorCheckBox;
         QPushButton *recordButton;

         QListView *saved_list;

         QStatusBar *mainStatusBar;
         QLabel *mainStatusLabel;

 

 

 - private 영역에 UI를 초기화할 함수를 선언해 줍니다.

 

 

          private:
                   void initUI();
                   void createActions();

 

 

2) UI 화면 구현

 

 - 화면에 필요한 내용을 initUI() 함수에서 구현합니다. 예를 들면, 화면 크기를 조정 메뉴, 각 부분에 필요한 하위 widget 생성 및 추가되도록 합니다.

 

 

         this->resize(1000, 800);
         // setup menubar
         fileMenu = menuBar()->addMenu("&File");

          

 

- 영상 영역 컴포넌트 생성

           

        QGridLayout *main_layout = new QGridLayout();
       	imageScene = new QGraphicsScene(this);
        imageView = new QGraphicsView(imageScene);
        main_layout->addWidget(imageView, 0, 0, 12, 1);

          

 

- 녹화와 영상 감지 영역 컴포넌트 생성

           

         QGridLayout *tools_layout = new QGridLayout();
         main_layout->addLayout(tools_layout, 12, 0, 1, 1);

         monitorCheckBox = new QCheckBox(this);
         monitorCheckBox->setText("Monitor On/Off");
         tools_layout->addWidget(monitorCheckBox, 0, 0);

         recordButton = new QPushButton(this);
         recordButton->setText("Record");
         tools_layout->addWidget(recordButton, 0, 1, Qt::AlignHCenter);
         tools_layout->addWidget(new QLabel(this), 0, 2);

          

 

- 캡처된 이미지 리스트 표시 영역 생성

         

         // list of saved videos
         saved_list = new QListView(this);
         main_layout->addWidget(saved_list, 13, 0, 4, 1);

 

 

   - 생성된 컨테이너 컴포넌트인 main_layout을 화면에 배치하고 상태바 생성과 메뉴 생성하는 것으로 화면 구성을 마무리합니다.

         

         QWidget *widget = new QWidget();
         widget->setLayout(main_layout);
         setCentralWidget(widget);
         // setup status bar
         mainStatusBar = statusBar();
         mainStatusLabel = new QLabel(mainStatusBar);
         mainStatusBar->addPermanentWidget(mainStatusLabel);
         mainStatusLabel->setText("GazerW is Ready");

         createActions();

 

 

  - File 메뉴를 추가해 주기 위해서 createActions()를 구현해 줍니다. 단순한 내용이라서 책 내용에는 이전 내용 참고하라고 나와 있어서 소스 내용 추가해 보았습니다. 메뉴 추가와 메뉴와 함수가 연동될 수 있도록 signals와 slots를 connect 함수도 추가되어야 하지만 현재 화면 확인만 할 것이라 fps 부분과 같이 추가하지 않았습니다.

     

    // create actions, add them to menus
    cameraInfoAction = new QAction("Camera &Information", this);
    fileMenu->addAction(cameraInfoAction);
    openCameraAction = new QAction("&Open Camera", this);
    fileMenu->addAction(openCameraAction);
    exitAction = new QAction("E&xit", this);
    fileMenu->addAction(exitAction);

 

 

3) 추가사항

 

 - 컴파일시키려고 하면 이런저런 에러가 코드가 발생합니다. 이유는 사용하는 라이브러리가 추가되지 않아서입니다. 그래서 앞으로 필요한 라이브러리를 Mainwindow.h에 포함시켜 줍니다.

 

 

#include <QMainWindow>
#include <QMenuBar>
#include <QAction>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QStatusBar>
#include <QLabel>
#include <QListView>
#include <QCheckBox>
#include <QPushButton>
#include <QGraphicsPixmapItem>
#include <QMutex>
#include <QStandardItemModel>

 

 

- Mainwindow.cpp 파일에는 QGridLayout를 사용하고 있어서 QGridLayout 라이브러리를 추가해 줍니다.

  

#include <QGridLayout>

 

 

- 메인 메뉴 생성자 함수에 설계한 UI 함수를 추가해 줍니다.

 

 

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
    , fileMenu(nullptr)
{
    initUI();
}

 

 

4) 참고 함수

 

 - addWidget(), addLayout() 함수를 많이 사용하고 있는데 인수를 보면 아래와 같습니다.  

 

void addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment = Qt::Alignment())
void addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment = Qt::Alignment())
void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = Qt::Alignment())

 

 

3. 실행 결과

 

 - 위의 소스코드를 잘 입력해서 실행해 보면 기능은 동작하지 않지만 화면은 UI를 설계한 것 같이 나타날 것입니다. 화면은 필요에 따라 추가나 수정해서 사용할 수 있습니다. 참고로, 위와 같이 컴포넌트들을 동적으로 생성하는 것이 아니라, 정적으로 UI를 만들어서 (.ui) 파일을 만들어서 사용해도 됩니다.

 

 

 

 

 

감사합니다.

 

 

<참고사이트>

1. opencv error: undefined reference to `cv::VideoCapture::VideoCapture()'

https://forum.qt.io/topic/92848/opencv-error-undefined-reference-to-cv-videocapture-videocapture

2. [BOOK] Qt-5-and-OpenCV-4-Computer-Vision-Projects

3. Qt-5-and-OpenCV-4-Computer-Vision-Projects

https://github.com/PacktPublishing/Qt-5-and-OpenCV-4-Computer-Vision-Projects/tree/master/Chapter-03/Gazer

4. QGridLayout Class

https://doc.qt.io/qt-5/qgridlayout.html  

 

GazerW_day1.zip
0.00MB

 

반응형