更改QCamera的输入分辨率

时间:2013-10-25 07:02:57

标签: qt qt5 qt5.1

我使用QCamera和QAbstractVideoSurface实现了相机捕捉。 我将QAbstractVideoSurface扩展为派生类,以将捕获编组到缓冲区中以供将来处理。一切正常,但我在改变输入捕获的捕获分辨率时遇到了问题。

使用setNativeResolution()似乎不起作用。

以下是代码的简要说明。

#ifndef _CAPTURE_BUFFER_H_
#define _CAPTURE_BUFFER_H_

#include <QMutex>
#include <QWidget>
#include <QImage>
#include <QVideoFrame>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <control/qcircularbuffer.h>

class CaptureBuffer: public QAbstractVideoSurface
{
    Q_OBJECT

public:
    CaptureBuffer(int size = 30);
    QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
    bool start(const QVideoSurfaceFormat& format);
    void stop();
    bool present(const QVideoFrame& frame);
    bool isEmpty() const;
    void pushBack(const QVideoFrame& new_frame);    
    void popFront();
    bool top(QVideoFrame& frame);
    bool back(QVideoFrame& frame);

    const QImage::Format& image_format() const {return m_image_format;}
    const QSize& image_size() const {return m_image_size;}

protected:
    void setNativeResolution(const QSize & resolution);

private:
    QSize                        m_image_size;
    QImage::Format               m_image_format;
    QCircularBuffer<QVideoFrame> m_buffer;
    QMutex                       m_buffer_mutex;
};

#endif



   CaptureBuffer::CaptureBuffer(int size) :
    m_buffer(QCircularBuffer<QVideoFrame>(size))
{
}

QList<QVideoFrame::PixelFormat> CaptureBuffer::supportedPixelFormats(
        QAbstractVideoBuffer::HandleType handleType) const
{
    if (handleType == QAbstractVideoBuffer::NoHandle) {
        return QList<QVideoFrame::PixelFormat>()
                << QVideoFrame::Format_RGB24
                << QVideoFrame::Format_RGB32
                << QVideoFrame::Format_ARGB32
                << QVideoFrame::Format_ARGB32_Premultiplied
                << QVideoFrame::Format_RGB565
                << QVideoFrame::Format_RGB555;
    } else {
        return QList<QVideoFrame::PixelFormat>();
    }
}

bool CaptureBuffer::start(const QVideoSurfaceFormat& format)
{
    const QImage::Format image_format = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
    const QSize size = format.frameSize();

    if (image_format != QImage::Format_Invalid && !size.isEmpty()) {
        m_image_format = image_format;
        m_image_size = size;

        QAbstractVideoSurface::start(format);

        return true;
    } else {
        return false;
    }
}

void CaptureBuffer::stop()
{
    QAbstractVideoSurface::stop();
}

bool CaptureBuffer::present(const QVideoFrame& frame)
{   
    pushBack(frame);
    return true;
}

bool CaptureBuffer::isEmpty() const
{
    return m_buffer.empty();
}

void CaptureBuffer::pushBack(const QVideoFrame& frame)
{
    m_buffer_mutex.lock();
    m_buffer.push_back(frame);
    m_buffer_mutex.unlock();
}

void CaptureBuffer::popFront()
{
    m_buffer_mutex.lock();
    m_buffer.pop_front();
    m_buffer_mutex.unlock();
}

bool CaptureBuffer::top(QVideoFrame& frame)
{
    if(m_buffer.empty()) 
        return false;

    m_buffer_mutex.lock();
    frame = m_buffer.front();
    m_buffer_mutex.unlock();
    return true;
}

bool CaptureBuffer::back(QVideoFrame& frame)
{
    if(m_buffer.empty())
        return false;

    m_buffer_mutex.lock();
    frame = m_buffer.back();
    m_buffer_mutex.unlock();
    return true;
}

void CaptureBuffer::setNativeResolution( const QSize & resolution )
{
    QAbstractVideoSurface::setNativeResolution(resolution);
}

以下是如何使用QCamera并将其附加到捕获缓冲区:

m_camera = camera;
m_camera->setCaptureMode(QCamera::CaptureVideo);
m_camera->setViewfinder(m_capture_buffer);
m_camera->start(); 

如果网络摄像机支持此分辨率,我如何将输入捕捉分辨率调整为640 x 480到1280 x 720等。

1 个答案:

答案 0 :(得分:2)

从Qt5.2.1开始(来自git)看起来Digia并没有完全针对Windows完成QCamera。但是,如何克服分辨率设置问题还有更多选择。

如果必须携带:

你可以试试gstreamer。正如我所看到的那样,gstreamer插件的必要部分已经实现。

我在Windows上工作,gstreamer在Windows上使用DirectShow,所以我决定直接使用DirectShow插件。

Qt5.2.1有一个功能强大的DirectShow核心插件,但它没有完全连接到Qt框架本身,因为DSImageEncoderControl(将从QImageEncoderControl派生)在DirectShow插件中不存在。

QAndroidImageEncoderControl和其他一些移动性实现存在。似乎Digia决定首先推动Qt Mobility业务。

无论如何,他们在Qt文件中说:

QImageEncoderSettings imageSettings;
imageSettings.setCodec("image/jpeg");
imageSettings.setResolution(1600, 1200);
imageCapture->setEncodingSettings(imageSettings);

然而,当您调用QCameraImageCapture :: setEncodingSettings时,Qt尝试通过DSImageEncoderControl设置分辨率,但由于缺少该代码,因此该部分代码将无法运行。 大多数控件尚未在DirectShow插件中实现。

对我来说,另一个问题是拍摄静止图像也需要设置表面,但我只想使用图像数据进行OpenCV的进一步处理。

可能的解决方案:

如果你不需要跨平台的东西,你可以使用我从Qt的DirectShow插件中借来的代码,你也可以设置分辨率和像素格式。 在我的例子中,我试图遵循Qt的命名约定。

另一个问题是目前QImage只知道RGB格式,但有些相机设备以YUYV格式输出捕获的数据。因此需要进行转换。 我还在我的代码中添加了一个简单的YUYV到RGB24转换器(感谢FourCC.org)来测试我的笔记本电脑的相机,但主要是我使用Logitech C920 Pro高清摄像头输出RGB24以及无需转换的地方。

Download the code from here