app.zip



filecapture.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
#ifndef FILECAPTURE_H
#define FILECAPTURE_H
 
#include <QObject>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
 
using namespace cv;
 
class FileCapture : public QObject
{
    Q_OBJECT
 
    VideoCapture *videoCapture;
    QString url;
    bool stopVideo;
 
 
public:
    explicit FileCapture(QObject *parent = nullptr);
    void setUrl(QString &value);
 
signals:
    void newFrameCaptured(Mat frame);
 
public slots:
 
    bool openVideo();
 
 
};
 
#endif // FILECAPTURE_H
 
cs


frame.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
#ifndef FRAME_H
#define FRAME_H
 
#include <QObject>
#include <QQuickPaintedItem>
#include <QImage>
#include <QPainter>
#include <QDebug>
 
#include <opencv2/core.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
 
using namespace cv;
 
class Frame : public QQuickPaintedItem
{
    Q_OBJECT
 
    // passing frame as Qimage and writh with setFrame function and so on..
    Q_PROPERTY( QImage frame READ getFrame WRITE setFrame NOTIFY frameChanged )
 
    Mat rawFrame;
    QImage frame;
 
public:
    Frame(QQuickItem *parent = nullptr );
    void paint(QPainter *painter);
 
 
    Mat getRawFrame() const;
    QImage getFrame() const;
    void setFrame(const QImage &value);
 
    Q_INVOKABLE void setRawFrame(const Mat &value);
    Q_INVOKABLE void openImage(QString url);
 
 
signals:
    void frameChanged();
 
public slots:
    void convert2QImage();
 
};
 
#endif // FRAME_H
 
cs


threadmanager.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
#ifndef THREADMANAGER_H
#define THREADMANAGER_H
 
#include <QObject>
#include <QThread>
#include "filecapture.h"
 
class threadManager : public QObject
{
    Q_OBJECT
 
    QThread thread;
    FileCapture capture;
 
public:
    explicit threadManager(QObject *parent = nullptr);
    Q_INVOKABLE void runCapture(QString url);
 
 
signals:
 
    void updateView(Mat frame);
 
public slots:
    void receiveFrame(Mat frame);
 
 
};
 
#endif // THREADMANAGER_H
 
cs



filecapture.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
#include "filecapture.h"
 
void FileCapture::setUrl(QString &value)
{
    value.remove("file://");
    url = value;
}
 
bool FileCapture::openVideo()
{
    Mat rawFrame;
    videoCapture = new VideoCapture;
    videoCapture->open( url.toStdString() );
 
    if(!videoCapture->isOpened()){
        return false;
    }
 
    while(videoCapture->read(rawFrame) && !stopVideo){
        emit(newFrameCaptured(rawFrame));
    }
 
    return true;
 
}
 
FileCapture::FileCapture(QObject *parent) : QObject(parent)
{
    stopVideo = false;
}
 
cs


frame.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
71
72
73
74
75
#include "frame.h"
 
Mat Frame::getRawFrame() const
{
    qDebug() <<__func__;
    return rawFrame;
}
 
void Frame::setRawFrame(const Mat &value)
{
    qDebug() <<__func__;
    rawFrame = value;
    convert2QImage();
}
 
QImage Frame::getFrame() const
{
    qDebug() <<__func__;
    return frame;
}
 
void Frame::setFrame(const QImage &value)
{
    qDebug() <<__func__;
    frame = value;
    Frame::update();
    emit( frameChanged() );
}
 
void Frame::openImage(QString url)
{
    qDebug() <<__func__;
    url.remove("file://");
    rawFrame = imread(url.toStdString());
    convert2QImage();
}
 
 
void Frame::convert2QImage()
{
    qDebug() <<__func__;
    Mat tempMat;
 
//  this may be bgr to rgb
    cvtColor( rawFrame, tempMat, COLOR_RGB2BGR );
 
//  constructor with the buffer and width, height, byte per line, format
    QImage tempImage( (uchar*)tempMat.data, tempMat.cols, tempMat.rows, tempMat.step, QImage::Format_RGB888);
 
    frame = tempImage;
 
////  in my opinion this disconnect mamory sharing with tempImage so we can chaenge tempImage without effecting on frame
    frame.detach();
 
 
    Frame::update();
 
    emit(frameChanged());
 
}
 
Frame::Frame(QQuickItem *parent) : QQuickPaintedItem (parent)
{
    qDebug() <<__func__;
 
}
 
void Frame::paint(QPainter *painter)
{
    qDebug() <<__func__;
    frame.scaled(1280,720, Qt::IgnoreAspectRatio, Qt::FastTransformation);
    painter->drawImage(00, frame, 0-1-1, Qt::AutoColor );
 
}
 
cs



main.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
#include <QGuiApplication>
#include <QQmlApplicationEngine>
 
 
// include thease to expose my thread to qml
#include <QQmlContext>
#include <QQmlComponent>
 
//include frame because we want to render something from
// Frame object otherwise we just connect signal and slot to the object
#include <frame.h>
 
//I didn't registered video related objects
//Since I just wanna connect signal and slot from them
 
#include "threadmanager.h"
 
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
 
    threadManager videoThread;
    // register my class
    qmlRegisterType<Frame>("com.app.frame"10"Frame");
 
    //register object so Mat can be transfered throgh signal and slot
    qRegisterMetaType<cv::Mat>("Mat");
 
    // pass my context to qml as named videoThread( any class can be passed this way too )
    engine.rootContext()->setContextProperty("videoThread"&videoThread);
 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
 
    return app.exec();
}
 
cs


threadmanager.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
#include "threadmanager.h"
 
threadManager::threadManager(QObject *parent) : QObject(parent)
{
 
}
 
void threadManager::runCapture(QString url)
{
    capture.setUrl( url );
 
    connect( &thread , &QThread::started, &capture, &FileCapture::openVideo   );
    connect( &thread , &QThread::finished, &capture, &FileCapture::deleteLater);
    connect( &capture, &FileCapture::newFrameCaptured, this&threadManager::receiveFrame);
 
    capture.moveToThread(&thread);
    thread.start();
 
}
 
void threadManager::receiveFrame(Mat frame)
{
    emit(updateView(frame));
}
 
cs



home.qml


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
import QtQuick 2.0
import QtQuick.Controls 2.12
 
Page {
    anchors.fill:parent
    Rectangle{
        id: bar
        width: parent.width
        height: parent.height * 0.1
        color: 'orange'
 
        Label{
            text : "Welcome to the Qt OpenCV app"
            color : "white"
            anchors.centerIn: parent
        }
    }
 
    Button{
        id : imageButton
        text:'Show Image'
        anchors.top: bar.bottom
        anchors.topMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: loader.push("qrc:/showImage");
    }
 
    Button{
        text:'Show Video'
        anchors.top: imageButton.bottom
        anchors.topMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
        onClicked: loader.push("qrc:/showVideo");
    }
 
 
}
 
cs


main.qml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
 
Window {
    visible: true
    width: 1024
    height: 720
    title: qsTr("app")
 
 
    StackView{
 
        id: loader
        anchors.fill: parent
        initialItem: 'qrc:/home'
    }
 
 
 
}
 
cs


showImage.qml


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
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Dialogs 1.2
import com.app.frame 1.0
 
Page {
    anchors.fill:parent
    Rectangle{
 
        id: bar
        width: parent.width
        height: parent.height * 0.1
        color: 'orange'
 
        Label{
            text : "Show Image"
            color : "white"
            anchors.centerIn: parent
        }
    }
 
    ColumnLayout{
 
        id: imageContainer
        width: 640
        height: 480
        anchors.top:bar.bottom
        anchors.topMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
 
        Image{
 
            id : picture
            source: "qrc:/logo"
            Layout.preferredWidth : imageContainer.width
            Layout.preferredHeight: imageContainer.height
            fillMode: Image.PreserveAspectFit
        }
 
        Frame{
 
            id : selectedImage
            Layout.preferredWidth: imageContainer.width
            Layout.preferredHeight: imageContainer.height
            visible: false
        }
 
 
    }
 
    RowLayout{
 
        anchors.top: imageContainer.bottom
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
        width: parent.width * 0.6
        spacing: width * 0.2
 
        Button{
            text : 'Open Image'
            Layout.preferredWidth: parent.width * 0.4
            onClicked: imageDialog.open()
        }
 
        Button{
            text : 'Go Back'
            Layout.preferredWidth: parent.width * 0.4
            onClicked: loader.pop()
        }
 
    }
 
    FileDialog{
        id : imageDialog
        title  : 'Choose Image'
        folder : shortcuts.pictures
        onAccepted:{
            selectedImage.openImage(imageDialog.fileUrl);
            picture.visible = false;
            selectedImage.visible = true;
        }
    }
 
 
}
 
cs


showVideo.qml


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
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Dialogs 1.2
import com.app.frame 1.0
 
Page {
    anchors.fill:parent
 
    Connections{
 
        // name of class reference defined in main.cpp
        target: videoThread
        // updateView signal should be referred as onUpdateView such as a slot name
        // frame is a name of Mat object from updateView signal
        // name of parameter should be the same with it's definition
 
        onUpdateView : selectedImage.setRawFrame(frame)
    }
 
    Rectangle{
 
        id: bar
        width: parent.width
        height: parent.height * 0.1
        color: 'orange'
 
        Label{
            text : "Show Video"
            color : "white"
            anchors.centerIn: parent
        }
    }
 
    ColumnLayout{
 
        id: imageContainer
        width: 640
        height: 480
        anchors.top:bar.bottom
        anchors.topMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
 
        Image{
 
            id : picture
            source: "qrc:/logo"
            Layout.preferredWidth : imageContainer.width
            Layout.preferredHeight: imageContainer.height
            fillMode: Image.PreserveAspectFit
        }
 
        Frame{
 
            id : selectedImage
            Layout.preferredWidth: imageContainer.width
            Layout.preferredHeight: imageContainer.height
            visible: false
        }
 
 
    }
 
    RowLayout{
 
        anchors.top: imageContainer.bottom
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
        width: parent.width * 0.6
        spacing: width * 0.2
 
        Button{
            text : 'Open Video'
            Layout.preferredWidth: parent.width * 0.4
            onClicked: videoDialog.open()
        }
 
        Button{
            text : 'Go Back'
            Layout.preferredWidth: parent.width * 0.4
            onClicked: loader.pop()
        }
 
    }
 
    FileDialog{
        id : videoDialog
        title  : 'Choose Video'
        folder : shortcuts.movies
        onAccepted:{
 
            picture.visible = false;
            selectedImage.visible = true;
            videoThread.runCapture(videoDialog.fileUrl);
        }
    }
 
 
}
 
cs


app.pro


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
QT += quick
CONFIG += c++11
 
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
 
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
 
SOURCES += \
        filecapture.cpp \
        frame.cpp \
        main.cpp \
        threadmanager.cpp
 
RESOURCES += qml.qrc
 
INCLUDEPATH += /usr/local/include/opencv
LIBS += -L/usr/local/lib \
 -lopencv_core \
 -lopencv_imgproc \
 -lopencv_imgcodecs \
 -lopencv_videoio \
 -lopencv_flann \
 -lopencv_highgui \
 -lopencv_features2d \
 -lopencv_photo \
 -lopencv_video \
 -lopencv_calib3d \
 -lopencv_objdetect \
 -lopencv_stitching \
 -lopencv_dnn \
 -lopencv_ml
 
 
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
    filecapture.h \
    frame.h \
    threadmanager.h
cs


'QT' 카테고리의 다른 글

QT Mouse Event Label example  (0) 2019.06.21
QT invokeMethod 예제  (0) 2019.03.22
qt msvc-version.conf 설정  (0) 2019.03.18
커스텀 위젯 만들기 노트  (0) 2019.03.17
Qt 동적 라이브러리 만들기 및 사용하기  (0) 2019.03.16

+ Recent posts