반응형

PyQt를 이용해 OpenCV 이미지를 출력해 보자.

 

디자이너에서 Dialog에 Label을 하나 배치하고 사이즈를 충분히 크게 한다. (test.ui)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import sys
import cv2
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import uic
 
myui = uic.loadUiType("test.ui")
 
class MyApp(QtWidgets.QWidget, myui[0]):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
 
        # 1) QtWidgets.QGraphicsView()에 이미지 출력하기
        # pixmap = QtGui.QPixmap()
        # pixmap.load("palvin.jpg")
        # scene = QtWidgets.QGraphicsScene()
        # scene.addPixmap(pixmap)
        # self.graphicsView.setScene(scene)
 
        # 2) QtWidgets.QGraphicsView()에 OpenCV 이미지 출력하기
        # img = cv2.imread("palvin.jpg")
        # img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # h, w, c = img.shape
        # qimg = QtGui.QImage(img.data, w, h, w*c, QtGui.QImage.Format_RGB888)
        # pixmap = QtGui.QPixmap.fromImage(qimg)
        # scene = QtWidgets.QGraphicsScene()
        # scene.addPixmap(pixmap)
        # self.graphicsView.setScene(scene)
 
        # QtWidgets.Label에 OpenCV 이미지 출력하기
        img = cv2.imread("palvin.jpg")
        img = cv2.resize(img, (self.label.size().width(), self.label.size().height()))
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        h, w, c = img.shape
        qimg = QtGui.QImage(img.data, w, h, w*c, QtGui.QImage.Format_RGB888)
        pixmap = QtGui.QPixmap.fromImage(qimg)
        self.label.setPixmap(pixmap)
 
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    myWindow = MyApp()
    myWindow.show()
   app.exec_()
 

 

소스를 입력하고 실행한다.

 

Label 사이즈에 맞게 이미지가 조절되었다.

 

이번엔 GraphicsView를 사용해 보자. 위 소스에서 1번이나 2번 주석을 해제한다.

1, 2번 주석부분의 소스는 이미지 크기를 조절하지 않는다.

 

Label은 삭제하고 Graphics View를 배치하고 크기를 조정한다.

 

이미지가 Graphics View보다 크지만 스크롤바가 표시된다.

 

Widget 없이 Dialog에 직접 이미지를 출력할 수 도 있다. Dialog만 남기고 모두 삭제한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import sys
import cv2
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import uic
 
myui = uic.loadUiType("test.ui")
 
class MyApp(QtWidgets.QWidget, myui[0]):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
 
        self.img = cv2.imread("palvin.jpg")        
        self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
        h, w, c = self.img.shape
        h, w = int(h/6), int(w/6)        
        self.img = cv2.resize(self.img, (w, h))
        self.qimg = QtGui.QImage(self.img.data, w, h, w*c, QtGui.QImage.Format_RGB888)
    
    def paintEvent(self, e):
        qp = QtGui.QPainter(self)
        self.drawCVImage(qp)
 
    def drawCVImage(self, qp):
        qp.drawImage(1010self.qimg)
        
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    myWindow = MyApp()
    myWindow.show()
   app.exec_()
 

 

소스를 입력하고 실행한다.

 

Dialog에 직접 이미지가 출력된다.

 

반응형

'OpenCV' 카테고리의 다른 글

Compiling and Running OpenPose from Source  (2) 2022.05.15
GDI+ and OpenCV - Bitmap to Mat & Mat to Bitmap Conversion  (0) 2022.01.02
OpenCV with C# and Camera  (0) 2021.12.29
OpenCvSharp for Network  (0) 2021.12.28
OpenCV with C#  (0) 2021.11.20
Posted by J-sean
:

Qt platform plugin error fix

C, C++ 2021. 9. 26. 15:14 |
반응형

Qt로 작성된 프로그램을 Qt Creator에서 실행하면 잘 되지만 실행 파일을 직접 실행하면 아래와 같은 에러가 발생한다.

 

 

This application failed to start because no Qt platform plugin could be initialized. 라는 메세지에서 알 수 있는 것 처럼 platform plugin이 없기 때문이다.

 

Qt 설치 폳더에서 platforms 폴더를 복사한다.

 

실행 파일이 있는 폴더에 붙여 넣는다.

Debug, Release 모두 동일하다.

그 외, 필요한 dll 파일도 모두 복사해 넣고 실행하면 문제없이 실행된다.

 

반응형
Posted by J-sean
:
반응형

Linux가 아닌 Windows에서는 Microsoft Visual C++을 사용하는 경우가 많다. 아래 링크와 같이 Qt를 설치한다.

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

 

Qt Widgets Application 프로젝트를 생성하고 프로젝트명.pro 파일을 확인한다.

 

프로젝트명.pro 파일을 위와 같이 수정한다. (opencv는 C:\opencv에 설치되어 있다)

CONFIG(debug, debug|release) {
    LIBS += -lopencv_world453d
}

CONFIG(release, debug|release) {
    LIBS += -lopencv_world453
}

opencv_world453은 C:\opencv\build\x64\vc15\bin 폴더의 opencv_worldXXX.dll, opencv_worldXXXd.dll 파일을 참고해 작성한다.

 

Projects - Build & Run - Run - Environment - Path 에 C:\opencv\build\x64\vc15\bin을 추가한다.

 

UI Design에서 Pushbutton을 하나 추가하고 우클릭 - Go to slot...을 클릭한다.

 

 

clicked()를 선택한다.

 

on_pushButton_clicked()를 위와 같이 수정한다. (상단에 opencv.hpp가 include 되어있다)

 

프로젝트를 빌드하고 XXX-Debug 폴더에 사진 파일을 복사한다.

 

실행하면 위와 같은 위도우가 나타난다. PushButton을 클릭하자.

 

 

Barbara palvin 사진이 출력된다.

 

반응형
Posted by J-sean
:
반응형

Qt6는 더 이상 오프라인 인스톨러를 제공하지 않는다. 오픈소스 온라인 인스톨러를 다운 받고 설치하자.

예전에는 Qt에 가입할 필요는 없었지만 지금은 아이디가 필요하다. 설치 전 미리 가입하자.

 

Latest releases - Qt - Qt 6.X.X - MSVC 2019 64-bit 만 선택하고 Developer and Designer Tools는 기본 상태 그대로 설치한다.

 

Qt 설치가 완료되면 Visual Studio - Extensions - Manage Extensions를 클릭한다.

 

Online - Visual Studio Marketplace에서 qt를 검색하고 Qt Visual Studio Tools를 설치한다. (Visual Studio 재시작이 필요하다)

 

Extensions - Qt VS Tools - Options를 클릭한다.

 

 

사용할 Qt를 추가해 주어야 한다. +아이콘을 클릭하고 Path를 클릭한다.

 

Qt가 설치된 디렉토리에서 qmake.exe 파일을 선택한다.

 

위 그림과 같이 설정 되었다면 OK를 클릭한다.

 

Qt Widgets Application 프로젝트를 만들자.

 

 

프로젝트 이름, 위치등을 지정하고 Create 버튼을 클릭한다.

 

Qt Widgets Application Wizard가 실행된다.

 

적당한 옵션을 선택한다.

 

적당한 옵션을 지정하고 Finish 버튼을 클릭한다.

 

 

소스파일이 표시된다.

 

Solution Explorer에서 UI 디자인 파일을 더블 클릭한다.

 

UI 디자인 화면이 표시된다.

 

Project Property Pages - Configuration Properties - C/C++ - Language를 클릭한다

 

 

Qt6는 C++ 17을 사용한다.

 

소스나 UI 수정없이 빌드하고 실행했을 때 위와 같은 위도우가 뜨면 성공이다. 

 

그런데 UI 디자인툴에서 PushButton - 우클릭을 해도 'Go to slot...'에 해당하는 명령어가 나오지 않는다.

그 뿐만 아니라 프로젝트 생성시 Qt Creator와 생성되는 파일도 다르고 코드를 작성해도 이해할 수 없는 방식으로 작동한다.

 

Qt Creator를 실행하고 Projects - New를 클릭한다.

 

 

Application (Qt) - Qt Widgets Application을 선택한다. 나머지 옵션은 적당히 선택한다.

 

Visual Studio와는 약간 다른 파일들이 생성되었다.

 

Forms - mainwindow.ui를 더블 클릭한다.

 

Label과 Pushbutton을 적당히 배치하고 Pushbutton에서 우클릭 - Go to slot...을 클릭한다.

 

 

clicked()를 선택하고 OK 버튼을 클릭한다.

 

mainwindow.cpp에 on_pushButton_clicked()가 생성되었다. (mainwindow.h 파일도 변경된다)

 

mainwindow.h 파일을 위와 같이 수정한다.

 

mainwindow.cpp 파일을 위와 같이 수정하고 빌드한다.

 

 

프로젝트를 실행하면 위와 같은 윈도우가 나타난다.

 

Pushbutton을 클릭하면 Label이 변경된다.

 

Pushbutton을 클릭할때마다 Label은 계속 변경된다.

다른 간단한 예제는 아래 링크를 참고한다.

2019.01.16 - [C, C++] - Qt 설치 및 간단한 사용 예

2019.02.21 - [C, C++] - Qt 스프라이트 애니매이션

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 OpenCV 이미지(cv::Mat)를 Qt로(QImage::QImage) 디스플레이 해 보자.

(cv::Mat ↔  QImage::QImage)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <opencv2/opencv.hpp>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
    ~Picture();
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass to receive paint events passed in event.
    void drawPicture(QPainter* qp);
    QImage Mat2QImage(cv::Mat const& src);
    cv::Mat QImage2Mat(QImage const& src);
 
private:
    int height;
    int width;
    QImage qtImage;
    cv::Mat cvImage;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    //image.load("Barbara Palvin.png");
    //cvimage = QImage2Mat(image);
 
    //Read images from OpenCV. Not from Qt.
    cvImage = cv::imread("Barbara Palvin.png", cv::IMREAD_COLOR);
    if (cvImage.empty())
    {
        std::cerr << "Image load failed." << std::endl;
 
        exit(EXIT_FAILURE);
    }
 
    cv::Mat tempCvImage;
    cv::cvtColor(cvImage, tempCvImage, cv::COLOR_RGB2GRAY);
 
    qtImage = Mat2QImage(tempCvImage);
    tempCvImage = QImage2Mat(qtImage);
 
    cv::resize(tempCvImage, tempCvImage, cv::Size(), 1.51.5);
    cv::imshow("OpenCV", tempCvImage);
 
    height = qtImage.height();
    width = qtImage.width();
 
    this->resize(width, height);
}
 
Picture::~Picture()
{
 
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the specified name is not used in the body
    // of a function. This can be used to suppress compiler warnings while allowing functions to be
    // defined with meaningful parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, qtImage);
}
 
QImage Picture::Mat2QImage(cv::Mat const& src)
{
    cv::Mat temp;
    cv::cvtColor(src, temp, cv::COLOR_BGR2RGB);
    QImage dest((const uchar*)temp.data, temp.cols, temp.rows, temp.step, QImage::Format_RGB888);
    dest.bits();
    // Enforce deep copy
    // See documentation of QImage::QImage (const uchar * data, int width, int height, Format format)
 
    return dest;
}
 
cv::Mat Picture::QImage2Mat(QImage const& src)
{
    cv::Mat temp(src.height(), src.width(), CV_8UC3, (uchar*)src.bits(), src.bytesPerLine());
    cv::Mat result; // Deep copy
    cv::cvtColor(temp, result, cv::COLOR_BGR2RGB);
 
    return result;
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Qt");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

 

소스를 입력한다. (qtcv.cpp)

 

컴파일(빌드)하고 실행하면 cv::imshow(), QPainter::drawImage() 모두 잘 표시된다. (OpenCV는 50% 확대)

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 이미지를 디스플레이 해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <QApplication>
#include <QWidget>
#include <QPainter>
 
class Picture : public QWidget
{
public:
    Picture(QWidget* parent = 0);
 
protected:
    void paintEvent(QPaintEvent* event);
    // This event handler can be reimplemented in a subclass
    // to receive paint events passed in event.
    void drawPicture(QPainter* qp);
 
private:
    int height;
    int width;
    QImage image;
};
 
Picture::Picture(QWidget* parent) : QWidget(parent)
{
    image.load("Barbara Palvin.png");
    height = image.height();
    width = image.width();
 
    this->resize(width, height);
}
 
void Picture::paintEvent(QPaintEvent* e)
{
    Q_UNUSED(e);
    // Q_UNUSED( name)
    // Indicates to the compiler that the parameter with the
    // specified name is not used in the body of a function.
    // This can be used to suppress compiler warnings while
    // allowing functions to be defined with meaningful
    // parameter names in their signatures.
 
    QPainter qp(this);
    drawPicture(&qp);
}
 
void Picture::drawPicture(QPainter* qp)
{
    qp->drawImage(00, image);
}
 
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
 
    Picture window;
    window.setWindowTitle("Picture Example");
    //window.resize(width, height);
 
    window.show();
 
    return app.exec();
}
 
 

소스를 입력한다. (qt.cpp)

 

컴파일(빌드)하고 실행하면 이미지가 디스플레이된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투)에서 Qt5를 이용해 GUI 프로그래밍을 해 보자.

 

Qt5를 설치한다.

 

단순한 window를 만드는 소스를 입력한다. (qt.cpp)

 

-fPIC 옵션과 함께 컴파일(빌드)하고 생성된 파일을 실행하면 Simple Example 윈도우가 나타난다.

 

이번엔 같은 소스를 qmake를 이용해 컴파일(빌드)해 보자. -project 옵션과 함께 실행하면 c.pro 파일이 생성된다. (디렉토리 이름.pro)

 

 

c.pro 파일의 내용을 보면 Qt Widgets 모듈이 포함되지 않았다.

 

파일의 끝에 Qt Widgets 모듈을 포함시킨다.

 

qmake, make 명령을 차례로 실행하면 컴파일(빌드)이 완료된다.

 

컴파일(빌드)된 파일을 실행하면 윈도우가 나타난다.

 

반응형
Posted by J-sean
:
반응형

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

 

Qt의 Pixmap을 이용해 간단한 스프라이트 애니매이션을 구현 할 수 있다.

 

아래와 같은 스프라이트 이미지를 준비 한다. 

horse.zip
다운로드

이 중 처음 11개의 달리는 이미지 프레임만 사용한다.

 

 

Qt Widgets Application으로 기본 설정들을 적용해서 프로젝트를 만든다. (D:\Horse)

 

 

프로젝트를 만든 후 바로 build 디렉토리가 만들어지지 않으므로 build를 한 번 진행 한다.

 

build 디렉토리에 준비한 스프라이트 이미지를 복사한다.

 

mainwindow.h 에 아래와 같이 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QTimer>
#include <QPainter>
#include <QDebug>
 
namespace Ui {
class MainWindow;
}
 
class Sprite
{
public:
    Sprite(QSize winsize);
    void Draw(QPainter* painter);   // 현재 프레임 그리기
    void NextFrame();   // 다음 프레임 지정
 
private:
    QPixmap* SpriteImage;   // 스프라이트
    int CurrentFrame;   // 현재 프레임
    int TotalFrame; // 전체 프레임 수(11)
    int Column; // 스프라이트내 프레임 열(4)
    int Row;    // 스프라이트내 프레임 행(3) (실제 사용되지는 않음)
    int FramesizeX; // 한 프레임의 X 길이(128)
    int FramesizeY; // 한 프레임의 Y 길이(128)
    QPoint FramePosition;   // 스프라이트내 현재 프레임의 픽셀 단위 위치
    QPoint DrawPosition;    // 윈도우에서 프레임이 그려질 위치
    QSize MainWindowSize;   // 윈도우 사이즈
};
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
    virtual void paintEvent(QPaintEvent* event);
 
private:
    Ui::MainWindow *ui;
 
    Sprite* sprite; // 스프라이트
    QTimer* timer;  // 타이머
};
 
#endif // MAINWINDOW_H
cs

 

 

mainwindow.cpp 에 아래와 같이 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    sprite = new Sprite(this->size());
    timer = new QTimer(this);
    timer->start(50);   // 20Hz 타이머 시작
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));    // timeout() 시그널이 발생하면 update() 실행
    // connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
    // Creates a connection of the given type from the signal in the sender object to the method in the receiver object.
    // Returns a handle to the connection that can be used to disconnect it later. You must use the SIGNAL() and SLOT() macros
    // when specifying the signal and the method.
}
 
MainWindow::~MainWindow()
{
    delete timer;
    delete sprite;
 
    delete ui;
}
 
void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter paint(this);   // The QPainter class performs low-level painting on widgets and other paint devices.
    sprite->Draw(&paint);
    sprite->NextFrame();
}
 
// 128X128 사이즈, 4X3배열의 11개 프레임
Sprite::Sprite(QSize winsize) : CurrentFrame(0), TotalFrame(11), Column(4), Row(3), FramesizeX(128), FramesizeY(128), FramePosition(00)
{
    MainWindowSize = winsize;   // 메인 윈도우 사이즈
    qDebug() << "Main Window Size: " << MainWindowSize << endl// Application Output 창에 메인 윈도우 사이즈(400X300) 출력
    SpriteImage = new QPixmap("horse.png"); //The QPixmap class is an off-screen image representation that can be used as a paint device.
    qDebug() << "Sprite Size: " << SpriteImage->size() << endl;    // Application Output 창에 스프라이트 사이즈(512X1024) 출력
 
    // 메인 윈도우 중앙에 프레임 출력
    DrawPosition.setX(MainWindowSize.width() / 2 - FramesizeX / 2);
    DrawPosition.setY(MainWindowSize.height() / 2 - FramesizeY / 2);
}
 
void Sprite::Draw(QPainter* painter)
{
    // Draws a pixmap at (x, y) by copying a part of the given pixmap into the paint device.
    painter->drawPixmap(DrawPosition.x(), DrawPosition.y(), *SpriteImage, FramePosition.x(), FramePosition.y(), FramesizeX, FramesizeY);
 
    // 'Running horse' 문자열 출력
    const QRect rect = QRect(00, MainWindowSize.width(), MainWindowSize.height() / 2);
    painter->setPen(Qt::blue);
    painter->setFont(QFont("Arial"30));
    painter->drawText(rect, Qt::AlignCenter, "Running horse");
}
 
void Sprite::NextFrame()
{
    if (CurrentFrame >= TotalFrame) // 11번 째 프레임을 넘어가면 0으로 초기화
        CurrentFrame = 0;
 
    // 출력할 프레임의 픽셀 단위 위치 지정
    FramePosition.setX((CurrentFrame % Column) * FramesizeX);
    FramePosition.setY((CurrentFrame / Column) * FramesizeY);
 
    CurrentFrame++;
}
cs

 

프로젝트를 build하고 실행하면 아래와 같은 애니매이션이 재생된다.

 

Application Output 창에는 Main Window와 Sprite 사이즈가 표시 된다.

 

iCCP 관련 warning은 무시하거나 이 링크를 참고해서 제거한다.

 

 

반응형
Posted by J-sean
: