Qt + OpenCV。 CvCaptureのランタイムとウィジェット(ビデオキャプチャデバイス)

はじめに



以前の投稿( OpenCVサービスのQt DesignerおよびRuntime Qtライブラリ... )のコメントを分析して、OpenCVライブラリのビデオキャプチャデバイスと、ランタイムライブラリとウィジェットを分離する方法について詳しく説明する必要がありました。

Qt Designerでの作業は便利です(私は残念です)。そのため、CvCaptureのインターフェイスデザインコンポーネントが登場しました。 作業の開始後、「科学的」な説明が作成されました。たとえば、ビデオキャプチャデバイスを使用してアプリケーションのプロパティまたはパラメーターのインターフェイスを設計するとき、同様の何かを使用すると便利です。

プロジェクトアーカイブのダウンロード中に読み進めてください。



謝辞。



前の投稿にコメントを残してくれた皆さんに感謝します。



ランタイムライブラリ。



そのため、OpenCVライブラリがインストールされ、コードサンプルがレビューされます。 ビデオキャプチャデバイスをQtに「固定」するときです。 はい、それだけではなく、デバイスを動的に変更して画像を受信するために。 はい、画像、ビデオへのすべての方法を覚えています。 はい、カメラ番号を切り替えます。 はい、そうです...投稿は短くなります。

ライブラリ。


簡単なことは何ですか! QObjectから新しいライブラリクラスを継承し、QScopedPointerコレクションの要素としてプライベートクラスの開発者に不要なフィールドとメソッドを非表示にし、警告信号とプロセッサスロットをマウントします。



ヘッダーファイルcqtopencvcaptureobject.hを取得します
#ifndef CQTOPENCVCAPTUREOBJECT_H #define CQTOPENCVCAPTUREOBJECT_H #include "../../../include/qtopencv_global.h" #include <opencv2/opencv.hpp> #include <QObject> #include <QScopedPointer> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /*----------------------------------------------------------------------------*/ /** \internal \class CQtOpenCVCaptureObjectPrivate \brief                CvCapture  OpenCV. */ class CQtOpenCVCaptureObjectPrivate; /*----------------------------------------------------------------------------*/ /** \class CQtOpenCVCaptureObject \brief       CvCapture  OpenCV. */ class #if defined(QTOPENCV_LIB_EXPORT) QTOPENCV_DECLARE_EXPORT #else Q_DECL_EXPORT #endif CQtOpenCVCaptureObject : public QObject { Q_OBJECT Q_CLASSINFO("brief", "OpenCV Capture class.") Q_CLASSINFO("author", "Vladimir N. Litvinenko") Q_CLASSINFO("URL", "http://www.codepaint.ru") Q_CLASSINFO("email", "litvinenko.vladimir@gmail.com") Q_CLASSINFO("created", "21-JUN-2012") Q_CLASSINFO("edited", "06-JUL-2012") public: explicit CQtOpenCVCaptureObject ( QObject *parent = 0 ); virtual ~CQtOpenCVCaptureObject (); CvCapture* getCapture () const; QString getPath () const; int getNumber () const; int getTimeoutInterval () const; IplImage* getImage () const; int getFrameCount () const; bool isInternal () const; bool isExternal () const; bool isActive () const; bool isRecap () const; signals: /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_Errno ( int errno, const QString& errmsg ); \brief      . \param errno -   \param errmsg -   */ void signal_Errno ( int, const QString& ); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_CaptureChanged () \brief       */ void signal_CaptureChanged (); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_CaptureChanged ( const CvCapture* value ) \brief       \param value -       CvCapture  OpenCV */ void signal_CaptureChanged ( const CvCapture* ); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_ImageChanged ( const IplImage* value ) \brief         IplImage  OpenCV. \param value -      IplImage  OpenCV. */ void signal_ImageChanged ( const IplImage* ); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_TimeoutChanged () \brief        */ void signal_TimeoutChanged (); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_TimeoutChanged ( int value ) \brief        \param value -      */ void signal_TimeoutChanged ( int ); /** \fn [SIGNAL] void CQtOpenCVCaptureObject::signal_ActiveChanged ( bool value ) \brief            -. \param value -     .  true   ,  false -      -. */ void signal_ActiveChanged ( bool ); public slots: void slot_SetNumber ( int ); void slot_SetPath ( const QString& ); void slot_SetAsInternal ( bool ); void slot_SetTimeout ( int ); void slot_captureOn ( bool ); void slot_Activate (bool); void slot_SetRecap (bool); protected: virtual void timerEvent(QTimerEvent *event); private: Q_DISABLE_COPY(CQtOpenCVCaptureObject) Q_DECLARE_PRIVATE(CQtOpenCVCaptureObject) QScopedPointer<CQtOpenCVCaptureObjectPrivate> d_ptr; }; /*----------------------------------------------------------------------------*/ QT_END_NAMESPACE QT_END_HEADER #endif // CQTOPENCVCAPTUREOBJECT_H
      
      









スロット:



.pro



ファイルを配置します
 DEFINES += QDESIGNER_EXPORT_WIDGETS
      
      





OpenCVライブラリを接続する必要はなくなりました。ランタイムライブラリに応じて接続されます。

そして、ここで、彼女、最愛の人、そして締める:

 unix: LIBS += -L/usr/lib -lQtOpenCVCapture INCLUDEPATH += $$PWD/../../runtime/capture/QtOpenCVCapture DEPENDPATH += /usr/lib
      
      







注意してください! パスは/usr/lib



指します。 これは便利です。 将来、このディレクトリにライブラリへのシンボリックリンクを作成するだけで、リンクに問題はありません!



デザイナーのウィジェットプロパティを宣言します。
 ... Q_PROPERTY( bool visible READ isVisible WRITE slot_setVisible ) Q_PROPERTY( bool internal READ isInternal WRITE slot_SetAsInternal ) Q_PROPERTY( QString path READ getPath WRITE slot_SetPath ) Q_PROPERTY( int number READ getNumber WRITE slot_SetNumber ) Q_PROPERTY( int numberMax READ getNumberMax WRITE slot_SetNumberMax ) Q_PROPERTY( int timeout READ getTimeoutInterval WRITE slot_SetTimeout ) Q_PROPERTY( int timeoutMax READ getTimeoutMax WRITE slot_SetTimeoutMax ) Q_PROPERTY( int timeoutStep READ getTimeoutStep WRITE slot_SetTimeoutStep ) Q_PROPERTY( bool recapture READ isRecap WRITE slot_SetRecap ) Q_PROPERTY( QString FrameTitle READ getFrameTitle WRITE slot_setFrameTitle ) Q_PROPERTY( QString GroupBoxTitle READ getGroupBoxTitle WRITE slot_setGroupBoxTitle ) Q_PROPERTY( QString RadioNumberTitle READ getRadioNumberTitle WRITE slot_setRadioNumberTitle ) Q_PROPERTY( QString RadioPathTitle READ getRadioPathTitle WRITE slot_setRadioPathTitle ) Q_PROPERTY( QString PathTitle READ getPathTitle WRITE slot_setPathTitle ) Q_PROPERTY( QString NumberTitle READ getNumberTitle WRITE slot_setNumberTitle ) Q_PROPERTY( QString TimeOutTitle READ getTimeOutTitle WRITE slot_setTimeOutTitle ) Q_PROPERTY( QString TimeOutExtTitle READ getTimeOutExtTitle WRITE slot_setTimeOutExtTitle ) Q_PROPERTY( QString RecaptureTitle READ getRecaptureTitle WRITE slot_setRecaptureTitle ) ...
      
      









プロパティをサポートするためのスロットとメソッドのセットを拡張します。

 ... //   bool isVisible () const; QString getFrameTitle () const; QString getGroupBoxTitle () const; QString getRadioNumberTitle () const; QString getRadioPathTitle () const; QString getPathTitle () const; QString getNumberTitle () const; QString getTimeOutTitle () const; QString getTimeOutExtTitle () const; QString getRecaptureTitle () const; ... //  void slot_setVisible( bool ); void slot_setFrameTitle( const QString& ); void slot_setGroupBoxTitle( const QString& ); void slot_setRadioNumberTitle( const QString& ); void slot_setRadioPathTitle( const QString& ); void slot_setPathTitle( const QString& ); void slot_setNumberTitle( const QString& ); void slot_setTimeOutTitle( const QString& ); void slot_setTimeOutExtTitle( const QString& ); void slot_setRecaptureTitle( const QString& ); void slot_SetNumberMax ( int ); void slot_SetTimeoutMax ( int ); void slot_SetTimeoutStep ( int ); ...
      
      







ランタイムライブラリのテスト例からウィンドウ設定をコピーします。
 /*----------------------------------------------------------------------------*/ void CQtOpenCVCaptureWidgetPrivate::setupUi ( QWidget* parent ) { p_Frame = new QFrame(parent); Q_ASSERT(p_Frame); p_Frame->setObjectName(QString::fromUtf8("p_Frame")); p_Frame->resize(550, 195); p_Frame->setMinimumSize(QSize(550, 195)); // p_Frame->setMaximumSize(QSize(550, 195)); p_Frame->setFrameShape(QFrame::StyledPanel); p_Frame->setFrameShadow(QFrame::Raised); p_gridLayout_Frame = new QGridLayout(p_Frame); Q_ASSERT(p_gridLayout_Frame); p_gridLayout_Frame->setObjectName(QString::fromUtf8("p_gridLayout_Frame")); p_groupBox_Capture = new QGroupBox(p_Frame); Q_ASSERT(p_groupBox_Capture); p_groupBox_Capture->setObjectName(QString::fromUtf8("p_groupBox_Capture")); QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(p_groupBox_Capture->sizePolicy().hasHeightForWidth()); p_groupBox_Capture->setSizePolicy(sizePolicy); // p_groupBox_Capture->setMinimumSize(QSize(540, 190)); // p_groupBox_Capture->setMaximumSize(QSize(540, 185)); p_groupBox_Capture->setFlat(true); p_gridLayout_GBox = new QGridLayout(p_groupBox_Capture); Q_ASSERT(p_gridLayout_GBox); p_gridLayout_GBox->setSpacing(1); p_gridLayout_GBox->setContentsMargins(3, 3, 3, 3); p_gridLayout_GBox->setObjectName(QString::fromUtf8("p_gridLayout_GBox")); p_horLayout_Radio = new QHBoxLayout(); Q_ASSERT(p_horLayout_Radio); p_horLayout_Radio->setSpacing(1); p_horLayout_Radio->setObjectName(QString::fromUtf8("p_horLayout_Radio")); p_radioButton_URL = new QRadioButton(p_groupBox_Capture); Q_ASSERT(p_radioButton_URL); p_radioButton_URL->setObjectName(QString::fromUtf8("p_radioButton_URL")); p_horLayout_Radio->addWidget(p_radioButton_URL); p_radioButton_Number = new QRadioButton(p_groupBox_Capture); Q_ASSERT(p_radioButton_Number); p_radioButton_Number->setObjectName(QString::fromUtf8("p_radioButton_Number")); p_radioButton_Number->setChecked(true); p_horLayout_Radio->addWidget(p_radioButton_Number); p_gridLayout_GBox->addLayout(p_horLayout_Radio, 0, 0, 1, 1); p_horLayout_PathNum = new QHBoxLayout(); Q_ASSERT(p_horLayout_PathNum); p_horLayout_PathNum->setSpacing(3); p_horLayout_PathNum->setObjectName(QString::fromUtf8("p_horLayout_PathNum")); p_label_PathNum = new QLabel(p_groupBox_Capture); Q_ASSERT(p_label_PathNum); p_label_PathNum->setObjectName(QString::fromUtf8("p_label_PathNum")); QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Preferred); sizePolicy1.setHorizontalStretch(0); sizePolicy1.setVerticalStretch(0); sizePolicy1.setHeightForWidth(p_label_PathNum->sizePolicy().hasHeightForWidth()); p_label_PathNum->setSizePolicy(sizePolicy1); p_label_PathNum->setMinimumSize(QSize(150, 0)); p_label_PathNum->setLayoutDirection(Qt::LeftToRight); p_label_PathNum->setFrameShape(QFrame::NoFrame); p_label_PathNum->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); p_horLayout_PathNum->addWidget(p_label_PathNum); p_spinBox_Number = new QSpinBox(p_groupBox_Capture); Q_ASSERT(p_spinBox_Number); p_spinBox_Number->setObjectName(QString::fromUtf8("p_spinBox_Number")); sizePolicy.setHeightForWidth(p_spinBox_Number->sizePolicy().hasHeightForWidth()); p_spinBox_Number->setSizePolicy(sizePolicy); p_spinBox_Number->setMinimum(0); p_spinBox_Number->setMaximum(999999); p_horLayout_PathNum->addWidget(p_spinBox_Number); p_lineEdit = new QLineEdit(p_groupBox_Capture); Q_ASSERT(p_lineEdit); p_lineEdit->setObjectName(QString::fromUtf8("p_lineEdit")); p_lineEdit->setEnabled(true); p_horLayout_PathNum->addWidget(p_lineEdit); p_gridLayout_GBox->addLayout(p_horLayout_PathNum, 1, 0, 1, 1); p_horLayout_TOut = new QHBoxLayout(); Q_ASSERT(p_horLayout_TOut); p_horLayout_TOut->setSpacing(3); p_horLayout_TOut->setObjectName(QString::fromUtf8("p_horLayout_TOut")); p_label_TOut = new QLabel(p_groupBox_Capture); Q_ASSERT(p_label_TOut); p_label_TOut->setObjectName(QString::fromUtf8("p_label_TOut")); sizePolicy1.setHeightForWidth(p_label_TOut->sizePolicy().hasHeightForWidth()); p_label_TOut->setSizePolicy(sizePolicy1); p_label_TOut->setMinimumSize(QSize(150, 0)); p_horLayout_TOut->addWidget(p_label_TOut); p_spinBox_TOut = new QSpinBox(p_groupBox_Capture); Q_ASSERT(p_spinBox_TOut); p_spinBox_TOut->setObjectName(QString::fromUtf8("p_spinBox_TOut")); sizePolicy.setHeightForWidth(p_spinBox_TOut->sizePolicy().hasHeightForWidth()); p_spinBox_TOut->setSizePolicy(sizePolicy); p_spinBox_TOut->setMinimum(0); p_spinBox_TOut->setMaximum(999999); p_horLayout_TOut->addWidget(p_spinBox_TOut); p_label_ms = new QLabel(p_groupBox_Capture); Q_ASSERT(p_label_ms); p_label_ms->setObjectName(QString::fromUtf8("p_label_ms")); sizePolicy1.setHeightForWidth(p_label_ms->sizePolicy().hasHeightForWidth()); p_label_ms->setSizePolicy(sizePolicy1); p_horLayout_TOut->addWidget(p_label_ms); p_horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Preferred, QSizePolicy::Minimum); Q_ASSERT(p_horizontalSpacer); p_horLayout_TOut->addItem(p_horizontalSpacer); p_gridLayout_GBox->addLayout(p_horLayout_TOut, 2, 0, 1, 1); p_horLayout_Buttons = new QHBoxLayout(); Q_ASSERT(p_horLayout_Buttons); p_horLayout_Buttons->setSpacing(3); p_horLayout_Buttons->setObjectName(QString::fromUtf8("p_horLayout_Buttons")); p_checkBox_Recap = new QCheckBox(p_groupBox_Capture); Q_ASSERT(p_checkBox_Recap); p_checkBox_Recap->setObjectName(QString::fromUtf8("p_checkBox_Recap")); sizePolicy.setHeightForWidth(p_checkBox_Recap->sizePolicy().hasHeightForWidth()); p_checkBox_Recap->setSizePolicy(sizePolicy); p_horLayout_Buttons->addWidget(p_checkBox_Recap); p_pushButton_Test = new QPushButton(p_groupBox_Capture); Q_ASSERT(p_pushButton_Test); p_pushButton_Test->setObjectName(QString::fromUtf8("p_pushButton_Test")); p_pushButton_Test->setCheckable(true); p_pushButton_Test->setChecked(false); p_horLayout_Buttons->addWidget(p_pushButton_Test); p_gridLayout_GBox->addLayout(p_horLayout_Buttons, 3, 0, 1, 1); p_gridLayout_Frame->addWidget(p_groupBox_Capture, 0, 0, 1, 1); #ifndef QT_NO_SHORTCUT p_label_PathNum->setBuddy(p_lineEdit); #endif // QT_NO_SHORTCUT retranslateUi(); QMetaObject::connectSlotsByName(p_Frame); }
      
      









信号とスロットを接続します。

 /*----------------------------------------------------------------------------*/ void CQtOpenCVCaptureWidgetPrivate::setupConnections () { //   runtime-    q_obj->connect (q_obj, SIGNAL(signal_Errno(int,QString)), q_ptr, SIGNAL(signal_Errno(int,QString))); q_obj->connect (q_obj, SIGNAL(signal_CaptureChanged()), q_ptr, SIGNAL(signal_CaptureChanged())); q_obj->connect (q_obj, SIGNAL(signal_CaptureChanged(const CvCapture*)), q_ptr, SIGNAL(signal_CaptureChanged(const CvCapture*))); q_obj->connect (q_obj, SIGNAL(signal_ImageChanged(const IplImage*)), q_ptr, SIGNAL(signal_ImageChanged(const IplImage*))); q_obj->connect (q_obj, SIGNAL(signal_TimeoutChanged()), q_ptr, SIGNAL(signal_TimeoutChanged())); q_obj->connect (q_obj, SIGNAL(signal_TimeoutChanged(int)), q_ptr, SIGNAL(signal_TimeoutChanged(int))); q_obj->connect (q_obj, SIGNAL(signal_ActiveChanged(bool)), q_ptr, SIGNAL(signal_ActiveChanged(bool))); //       q_ptr->connect (p_radioButton_Number,SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetAsInternal(bool))); q_ptr->connect (p_radioButton_URL, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetAsExternal(bool))); //         q_ptr->connect (p_lineEdit, SIGNAL(textChanged(QString)), q_ptr, SLOT(slot_SetPath(QString))); q_ptr->connect (p_lineEdit, SIGNAL(returnPressed()), q_ptr, SLOT(slot_PathComplete())); //       q_ptr->connect (p_spinBox_Number, SIGNAL(valueChanged(int)), q_ptr, SLOT(slot_SetNumber(int))); //    -   q_ptr->connect (p_spinBox_TOut, SIGNAL(valueChanged(int)), q_ptr, SLOT(slot_SetTimeout(int))); //          - q_ptr->connect (p_checkBox_Recap, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_SetRecap(bool))); //      q_ptr->connect (p_pushButton_Test, SIGNAL(toggled(bool)), q_ptr, SLOT(slot_Test(bool))); // q_ptr->connect (q_ptr, SIGNAL(signal_ImageChanged(const IplImage*)), q_ptr, SLOT(slot_ShowImage(const IplImage*))); } /*----------------------------------------------------------------------------*/
      
      





ウィジェットに基づいてライブラリを収集します。

デザイナへのプラグイン。


QWidgetライブラリをQt Designerに接続します。

コレクションプロジェクトを作成しましょう。

 CONFIG += designer plugin debug_and_release TARGET = $$qtLibraryTarget(CQtOpenCVCollection) TEMPLATE = lib DEFINES += QDESIGNER_EXPORT_WIDGETS HEADERS = cqtopencvcapturewidgetplugin.h cqtopencvcollection.h SOURCES = cqtopencvcapturewidgetplugin.cpp cqtopencvcollection.cpp RESOURCES = icons.qrc //target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target #include(cqtopencvimagewidget.pri) include(cqtopencvcapturewidget.pri) #include(cqtopencvcannywidget.pri) unix: LIBS += -L/usr/lib/ -lQtOpenCVCaptureWidget INCLUDEPATH += $$PWD/ DEPENDPATH += $$PWD/
      
      







プラグインクラスを宣言します。
 #ifndef CQTOPENCVCAPTUREWIDGETPLUGIN_H #define CQTOPENCVCAPTUREWIDGETPLUGIN_H #include <QDesignerCustomWidgetInterface> #include <QtDesigner/QDesignerExportWidget> class #if defined(QDESIGNER_EXPORT_WIDGETS) QDESIGNER_WIDGET_EXPORT #else Q_DECL_EXPORT #endif CQtOpenCVCaptureWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) public: CQtOpenCVCaptureWidgetPlugin(QObject *parent = 0); bool isContainer() const; bool isInitialized() const; QIcon icon() const; QString domXml() const; QString group() const; QString includeFile() const; QString name() const; QString toolTip() const; QString whatsThis() const; QWidget *createWidget(QWidget *parent); void initialize(QDesignerFormEditorInterface *core); private: bool m_initialized; };
      
      









コレクションクラスを宣言します。

 #ifndef CQTOPENCVCOLLECTION_H #define CQTOPENCVCOLLECTION_H #include <QtDesigner/QtDesigner> #include <QtCore/qplugin.h> class CQtOpenCVCollection : public QObject, public QDesignerCustomWidgetCollectionInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) public: explicit CQtOpenCVCollection(QObject *parent = 0); virtual QList<QDesignerCustomWidgetInterface*> customWidgets() const; private: QList<QDesignerCustomWidgetInterface*> m_widgets; }; #endif
      
      





実装:

 #include "cqtopencvcapturewidgetplugin.h" //#include "cqtopencvimagewidgetplugin.h" //#include "cqtopencvcannywidgetplugin.h" #include "cqtopencvcollection.h" CQtOpenCVCollection::CQtOpenCVCollection(QObject *parent) : QObject(parent) { m_widgets.append(new CQtOpenCVCaptureWidgetPlugin(this)); // m_widgets.append(new CQtOpenCVImageWidgetPlugin(this)); // m_widgets.append(new CQtOpenCVCannyWidgetPlugin(this)); } QList<QDesignerCustomWidgetInterface*> CQtOpenCVCollection::customWidgets() const { return m_widgets; } Q_EXPORT_PLUGIN2(CQtOpenCVCollection, CQtOpenCVCollection)
      
      







に注意してください

 // m_widgets.append(new CQtOpenCVImageWidgetPlugin(this)); // m_widgets.append(new CQtOpenCVCannyWidgetPlugin(this));
      
      







CQtOpenCVImageWidgetPlugin



およびCQtOpenCVCannyWidgetPlugin



実装した後CQtOpenCVCannyWidgetPlugin



コメントを削除できます。 また、Qt DesignerコンポーネントのOpenCVグループには、新しい要素が表示されます。



プロジェクトのアーカイブ。



テストケース。


すべてのライブラリをアセンブルし、リンクを正しく割り当て、Qt Designerのプラグインカタログにコレクションリンクをインストールした後、テストケースを作成できます。



デザイナでMainWindowを作成し、ウィジェットを配置して組み立てます。



おわりに







ご清聴ありがとうございました。




All Articles