捕获图像而不保存

Posted

技术标签:

【中文标题】捕获图像而不保存【英文标题】:Capture image without saving 【发布时间】:2016-07-05 12:37:57 【问题描述】:

基于thread,有没有办法在 QML 中处理来自相机的图像而不保存它?

从doc 的示例开始,capture() 函数将图像保存到图片位置。 我想要实现的是每秒使用 onImageCaptured 处理相机图像,但我不想将其保存到驱动器中。

我尝试使用 onImageSaved 信号实现清理操作,但它也影响了 onImageCaptured。

【问题讨论】:

这真的取决于你想做什么。如果您只想处理帧(例如搜索标签/二维码),您可以连接mediaObject,仅此而已。如果要进行实时过滤和叠加,则需要做更多的工作。有关第二种情况的更多详细信息,请参阅this answer 开头的链接。 我想实现的是扫描二维码。由于this 无法使用grabWindow(),我想每秒捕获相机输出并处理图像。 所以根据您对使用 mediaObject 的建议,一旦我获得对 QCamera 对象的引用,我需要做什么? 我添加了一个答案。我无法发布完整的代码,但我希望我已经为您提供了正确的工具来构建完整的解决方案。 【参考方案1】:

正如this answer 中所述,您可以通过mediaObject 桥接C++ 和QML。这可以通过objectName(如链接的答案)或使用专用的Q_PROPERTY(稍后详细介绍)来完成。无论哪种情况,您都应该得到这样的代码:

QObject * source  // QML camera pointer obtained as described above
QObject * cameraRef = qvariant_cast<QMediaObject*>(source->property("mediaObject"));  

一旦你得到了相机的钩子,就将它用作QVideoProbe对象的来源,即

QVideoProbe *probe = new QVideoProbe;
probe->setSource(cameraRef);

videoFrameProbed 信号连接到适当的插槽,即

connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));

就是这样:您现在可以在processFrame 函数中处理您的帧。这种函数的实现如下所示:

void YourClass::processFrame(QVideoFrame frame)

    QVideoFrame cFrame(frame);
    cFrame.map(QAbstractVideoBuffer::ReadOnly);
    int w cFrame.width();
    int h cFrame.height();
    QImage::Format f;
    if((f = QVideoFrame::imageFormatFromPixelFormat(cFrame.pixelFormat())) == QImage::Format_Invalid)
    
        QImage image(cFrame.size(), QImage::Format_ARGB32);
        // NV21toARGB32 convertion!!
        //
        // DECODING HAPPENS HERE on "image"
    
    else
    
        QImage image(cFrame.bits(), w, h, f);
        //
        // DECODING HAPPENS HERE on "image"
    
    cFrame.unmap();

这里有两个重要的实现细节:

    android 设备使用YUV format,目前QImage 不支持,需要手动转换。我在这里做了一个强有力的假设,即所有无效格式都是 YUV。在当前操作系统上,通过ifdef 的条件可以更好地管理。 解码成本很高,因此您可以跳过帧(只需在此方法中添加一个计数器)或将工作卸载到专用线程。这也取决于精心设计框架的速度。还减小它们的大小,例如只取QImage 的一部分可以大大提高性能。

就此而言,我将完全避免使用objectName 方法来获取mediaObject,而是使用register a new type,以便可以使用Q_PROPERTY 方法。我正在考虑这样的事情:

class FrameAnalyzer 

    Q_OBJECT
    Q_PROPERTY(QObject* source READ source WRITE setSource)
    QObject *m_source;  // added for the sake of READ function 
    QVideoProbe probe;
    // ...

public slots:
    void processFrame(QVideoFrame frame);

setSource 只是:

bool FrameAnalyzer::setSource(QObject *source)

    m_source = source; 
    return probe.setSource(qvariant_cast<QMediaObject*>(source->property("mediaObject")));

一旦像往常一样注册,即

qmlRegisterType<FrameAnalyzer>("FrameAnalyzer", 1, 0, "FrameAnalyzer");

您可以直接在QML中设置source属性如下:

// other imports
import FrameAnalyzer 1.0

Item 
    Camera 
        id: camera

        // camera stuff here

        Component.onCompleted: analyzer.source = camera
    

    FrameAnalyzer 
        id: analyzer
    

这种方法的一大优势是可读性以及Camera 代码和处理代码之间的更好耦合。这是以牺牲(稍微)更高的实施工作为代价的。

【讨论】:

以上是关于捕获图像而不保存的主要内容,如果未能解决你的问题,请参考以下文章

iOS:在相机预览期间捕获图像而不采取行动

捕获和裁剪图像并保存裁剪的图像

从相机捕获图像并保存

在 ResearchKit 中捕获皮疹的图像

保存图像后由于方向更改导致 Android 显示图像捕获错误

图像到浏览器而不保存