【问题标题】:Integrating OpenCV with larger programs将 OpenCV 与更大的程序集成
【发布时间】:2011-12-09 17:36:10
【问题描述】:

任何人都可以推荐一个操作指南或简要概述将 OpenCV 与更大的基于 GUI 的程序集成所涉及的内容吗?有哪些流行的方法?

特别是,使用 OpenCV 处理视频,同时使用 HighGUI 进行视频捕获/预览 似乎特别神秘。我希望有人可以揭开这个神秘面纱。

我的特定配置是使用 Juce 或 Qt,具体取决于可以做什么。跨平台的事情并不重要——如果在 Windows 中有一种很棒的方法,我可能会相信。社区支持的可用性很重要。

我听说 HighGUI 完全是为了测试,不适合实际应用。有人推荐了VideoInput 库,但它是实验性的。


答案要点:

  • 使用 Qt(因为 Qt 非常棒,并且拥有庞大的社区)。
  • 打开一个新线程以循环运行 cv::VideoCapture 并在帧捕获后发出emit 信号。使用 Qt 的 msleep 机制,而不是 OpenCV。 所以,我们仍在使用 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();

【问题讨论】:

  • 很棒的总结!我会说不一定需要使用VideoCapture(例如,您可以使用 CMU1394、供应商特定驱动程序等),但如果它支持您的开箱即用的相机,那将非常方便。
  • 感谢您的总结!

标签: qt user-interface opencv juce


【解决方案1】:

这是我使用 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

【讨论】:

  • 很好的答案——你也可以直接显示 QImage 而不是 OpenGL 只提供你自己的 QWidget::paintevent()。除了 OpenCV 之外,这还为您提供了所有 QImage 文件加载/保存功能。
  • 很高兴有不同的选择。考虑到没有进行缩放或图像变换,OpenGL 是否更快?
  • @MartinBeckett - 我不知道 QWidget::paintevent()。我得去看看。我也看过绘制到 QPixmap,它有效,但我读到如果你有一个视频卡(通常是一个安全的假设)OpenGL 小部件会更快。另外,如果你想做覆盖和类似的事情,OpenGL 给你带来了一些很好的灵活性。
  • @Matt - 取决于,glSubImage 在硬件不错的机器上可以更快。 glPixelBuffer 可以更快,因为它可以异步传输数据。但在具有糟糕 openGL(英特尔嵌入式芯片组)的机器上,QPainter 更快。
  • @Matt - 只是为了说明这一点。将 QImage(尤其是 ARGB_Prescaled 的)绘制到 QPainter 非常快。如果您将 Qt 设置为使用 Opengl2 绘图引擎,它可能会在幕后调用 glSubTex2D。绘制到 QPixmap 过去很慢。
【解决方案2】:

创建一个 openCV 图像来保存您捕获的图像。

对其进行处理,然后将数据复制到要显示的图像中(例如QImage)

您可以通过创建opencv cv::Mat 图像来优化事物以与

QImage 但由于 QImage 通常使用 ARGB,并且大多数图像处理任务最好以灰度或 RGB 形式完成,因此使用 opencv cvtColor() 函数复制图像并在它们之间进行转换可能会更好

然后简单地包含 opencv 标头,并链接到 opencv 库 - o​​pencv wiki 上有针对您特定环境的指南

【讨论】:

    猜你喜欢
    • 2016-04-19
    • 2017-03-04
    • 2015-08-23
    • 2013-01-26
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多