12

OpenCV を大規模な GUI ベースのプログラムと統合することに関するハウツー ガイドを推奨したり、簡単な概要を提供したりできる人はいますか? それを行うための一般的な方法は何ですか?

特に、 HighGUI を使用せずにビデオ キャプチャ/プレビューを実行しながら OpenCV でビデオを処理することは、特に難解に思えます。誰かがこれをわかりやすく説明してくれることを願っています。

私の特定の構成は、何ができるかに応じて、Juce または Qt を使用しています。クロス プラットフォームのことは重要ではありません。Windows でこれを行う素晴らしい方法があれば、私は納得するかもしれません。コミュニティ サポートの利用可能性は重要です。

HighGUI は完全にテスト用であり、実際のアプリケーションには適していないと聞いています。誰かがVideoInputライブラリを推奨しましたが、これは実験的なものです。


回答の要点:

  • Qt を使用します (Qt は優れており、大きなコミュニティがあるため)。
  • 新しいスレッドを開いて cv::VideoCapture をループで実行し、emitフレーム キャプチャ後にシグナルを送ります。OpenCV ではなく、 Qt のmsleepメカニズムを使用します。そのため、キャプチャには引き続き OpenCV highgui を使用しています。
  • cv::Mat を QtImage に変換します。

    QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);

    qtFrame = qtFrame.rgbSwapped();

  • オプション: GLWidget でレンダリングします。Qt組み込みメソッドを使用してQtImageをGLFormatに変換します。

    m_GLFrame = QGLWidget::convertToGLFormat(frame);

    this->updateGL();

4

2 に答える 2

10

これが私がQtでそれをしている方法です。あなたはあなたに役立つかもしれないものなら何でも使うことを歓迎します:)

/// OpenCV_GLWidget.h
#ifndef OPENCV_GLWIDGET_H_
#define OPENCV_GLWIDGET_H_

#include <qgl.h>
#include <QImage>

class OpenCV_GLWidget: public QGLWidget {
public:
    OpenCV_GLWidget(QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0);
    virtual ~OpenCV_GLWidget();

    void renderImage(const QImage& frame);
protected:
    virtual void paintGL();
    virtual void resizeGL(int width, int height);

private:
    QImage m_GLFrame;
};

#endif /* OPENCV_GLWIDGET_H_ */

/// OpenCV_GLWidget.cpp
#include "OpenCV_GLWidget.h"

OpenCV_GLWidget::OpenCV_GLWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) :
QGLWidget(parent, shareWidget, f)
{
    // TODO Auto-generated constructor stub

}

OpenCV_GLWidget::~OpenCV_GLWidget() {
    // TODO Auto-generated destructor stub
}

void OpenCV_GLWidget::renderImage(const QImage& frame)
{
    m_GLFrame = QGLWidget::convertToGLFormat(frame);
    this->updateGL();
}

void OpenCV_GLWidget::resizeGL(int width, int height)
{
    // Setup our viewport to be the entire size of the window
    glViewport(0, 0, width, height);

    // Change to the projection matrix and set orthogonal projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, width, height, 0, 0, 1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void OpenCV_GLWidget::paintGL() {
    glClear (GL_COLOR_BUFFER_BIT);
    glClearColor (0.0, 0.0, 0.0, 1.0);
    if (!m_GLFrame.isNull()) {
        m_GLFrame = m_GLFrame.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

        glEnable(GL_TEXTURE_2D);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_GLFrame.width(), m_GLFrame.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_GLFrame.bits() );
        glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex2f(0, m_GLFrame.height());
        glTexCoord2f(0, 1); glVertex2f(0, 0);
        glTexCoord2f(1, 1); glVertex2f(m_GLFrame.width(), 0);
        glTexCoord2f(1, 0); glVertex2f(m_GLFrame.width(), m_GLFrame.height());
        glEnd();
        glDisable(GL_TEXTURE_2D);

        glFlush();
    }
}

このクラスは、プロモートされたQWidgetへの画像のレンダリングを処理します。次に、ウィジェットにフィードするスレッドを作成しました。(ここでは、Qtシグナルスロットアーキテクチャを使用するのは簡単だったので、だましました...本の中で最高のパフォーマンスを発揮する人ではないかもしれませんが、始める必要があります)。

void VideoThread::run()
{
    cv::VideoCapture video(0);

    while(!m_AbortCapture)
    {
        cv::Mat cvFrame;
        video >> cvFrame;

        cv::Mat gray(cvFrame.size(), CV_8UC1);
        cv::GaussianBlur(cvFrame, cvFrame, cv::Size(5, 5), 9.0, 3.0, cv::BORDER_REPLICATE);
        cv::cvtColor(cvFrame, gray, CV_RGB2GRAY);

        m_ThresholdLock.lock();
        double localThreshold = m_Threshold;
        m_ThresholdLock.unlock();

        if(localThreshold > 0.0)
        {
            qDebug() << "Threshold = " << localThreshold;
            cv::threshold(gray, gray, localThreshold, 255.0,  cv::THRESH_BINARY);
        }

        cv::cvtColor(gray, cvFrame, CV_GRAY2BGR);

        // convert the Mat to a QImage
        QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
        qtFrame = qtFrame.rgbSwapped();

        // queue the image to the gui
        emit sendImage(qtFrame);
        msleep(20);
    }
}

それを理解するのに少し時間がかかったので、うまくいけば、あなたや他の人が時間を節約するのに役立つでしょう:D

于 2011-10-18T02:09:53.417 に答える
2

キャプチャしたイメージを保持するための openCV イメージを作成します。

それを処理してから、データを表示したい画像にコピーします(例:QImage)

opencv cv::Mat イメージを作成してメモリを共有することで、物事を最適化できます

QImage ですが、QImage は一般的に ARGB を使用し、ほとんどの画像処理タスクはグレースケールまたは RGB として実行する方がよいため、opencv cvtColor() 関数を使用して画像をコピーし、それらの間で変換することをお勧めします。

次に、opencv ヘッダーをインクルードし、opencv ライブラリにリンクするだけです。特定の環境の opencv wiki にガイドがあります。

于 2011-10-18T01:41:21.443 に答える