2015-01-20 2 views
13

У меня есть программа на основе Qt5.4 с некоторой обработкой изображений. Я использую QCamera с моим videoSurface (производным от QAbstractVideoSurface), чтобы получить VideoFrames. Это хорошо работает в Windows.Qt QML Camera to C++ QImage на Android

Но теперь мне нужна версия Android для Android. Я узнал, что QCamera не работают на Android. Но я вижу, что пример камеры QML работает на Android без проблем.

Итак, я решил переписать свое приложение в QML. Основная проблема: я не могу получить доступ к поверхности QML-камеры на C++.

void myVideoOutput::setSource(QObject *source) 
{ 
    qDebug() << Q_FUNC_INFO << source; 

    if (source == m_source.data()) 
     return; 
    m_source = source; 
    if (m_source) { 
     const QMetaObject *metaObject = m_source.data()->metaObject(); 

     QStringList properties; 
     for(int i = metaObject->propertyOffset(); i <metaObject>propertyCount(); ++i) 
      properties << QString::fromLatin1(metaObject->property(i).name()); 
     qDebug() << properties; 

    } 
    ..... 
    emit sourceChanged(); 
} 

Этот код предоставляет доступ к объектам недвижимости. Но я не могу получить доступ к видеоповерхности таким образом (с помощью QCamera я мог бы это сделать). Интересно, как работает камера QML? Он основан на QCamera? Я вижу в QDeclarativeCameraQCamera *m_camera ...

Так что у меня 2 вопроса:

  1. Можно ли использовать QML камеры для постобработки изображений в C++? Рабочий пример был бы очень ценным.
  2. Знаете ли вы другие способы захвата видео с камеры Android в Qt?

ответ

9

1) Да, это возможно. У меня есть два способа сделать это.

Использование QAbstractVideoFilter наряду с классами QVideoFilterRunnable (только QT 5.5!), Которые являются простыми. Они были разработаны специально для этого сценария и довольно просты в использовании.

Есть несколько хороших примеров в Интернете, используя его:

https://blog.qt.io/blog/2015/03/20/introducing-video-filters-in-qt-multimedia/

http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl

Недостатком этого подхода, как было сказано here, является то, что на Android устройствах указатель QVideoFrame не имеет сырых данных пикселя, вместо этого у него есть текстура OpenGL, которая должна быть прочитана (второй пример, который я опубликовал, имеет обходное решение, разрешающее это), тем самым делая этот подход не очень хорошим для целей реального времени IMHO.

Что я использовал для решения этой проблемы, был класс QVideoProbe.

Сначала вы должны назвать экземпляр вашей QML камеры:

Camera { 
    id: camera 

    objectName: "qrCameraQML" 
} 

Тогда вы получите этот экземпляр со стороны C++, что-то вроде:

QObject *qmlCamera = engine.rootObjects().at(0).findChild<QObject*>("qrCameraQML"); 

Экземпляр камеры QML на самом деле имеет QVariant доступный только через C++, который может быть отлит в QCamera *:

Затем a LL вы должны сделать, это подключить датчик к слоту, который будет на самом деле справиться с QVideoFrames, а затем установить источник зонда как QCamera * previouslly отбрасываемой:

connect(&probe_,SIGNAL(videoFrameProbed(QVideoFrame)),this,SLOT(handleFrame(QVideoFrame))); 

probe_.setSource(camera_); 

На моем примере camera_ и probe_ просто:

QCamera *camera_; 

QVideoProbe probe_; 

Этот подход на моем опыте был намного быстрее (для андроид платформ), чем при использовании Qt классов видео фильтров, но имеет тот недостаток, что вы в основном только для чтения видео выхода из QML, и AFAIK вы не будете возможность отправлять постобрабованные видеофрагменты обратно в qml.

Если вам действительно нужно отправить обработанные изображения обратно в qml, я бы посоветовал вам попробовать первый подход и посмотреть, что произойдет.

2) Не с Qt AFAIK, может быть, с OpenCv или какой-либо другой lib.

+0

Использование '' QAbstractVideoFilter' с классами QVideoFilterRunnable' отлично работает. Я хотел бы выделить OpenGL-код для обработки GLTextureHandle, показанный на http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl/rgbframehelper.h –

+0

@WaldezJunior Первое решение не работайте над Qt5.9.1, setSource всегда возвращает false – StereoMatching

3
  1. Я думаю, что ответ выше достаточно объяснил обработку с камеры QML
  2. Да, есть и другие возможности, которые я нашел этот проект мне очень помог: https://github.com/rferrazz/CvCamView зарегистрировать плагин для QML, и он может быть использован как это:
import QtQuick 2.3 
import QtQuick.Window 2.2 
import CVComponents 1.0 

Window { 
    visible: true 
    CVCAM{ 
     id: camera 
     width: 640 
     height: 480 
     deviceId: "0" 
     imageHeight: 640 
     imageWidth: 480 
    } 

} 

Обработка изображения как очень просто. Класс только рисует элемент, поэтому его можно использовать в QML, вся другая обработка продолжается в задней части, поэтому изображение Mat, используемое камерой, может использоваться для обработки.

5

Мне нравится выделить @ waldez-junior первый ответ. В QML вы добавляете свой компонент QAbstractVideoFilter к VideoOutput.

Camera { 
    id: camera 
} 

VideoOutput { 
    id: videoOutput 
    source: camera 
    filters: [ videoFilter ] 
    autoOrientation: true 
} 

MyVideoFilter { 
    id: videoFilter 
    // orientation: videoOutput.orientation 
} 

В C++, вы реализуете QAbstractVideoFilter компонент, вот минимальный пример:

class MyVideoFilter : public QAbstractVideoFilter 
{ 
    Q_OBJECT 

public: 
    QVideoFilterRunnable *createFilterRunnable() Q_DECL_OVERRIDE 
    { 
     return new CustomFilterRunnable(this); 
    } 
}; 

class MyVideoFilterRunnable : public QVideoFilterRunnable 
{ 
public: 
    QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& surfaceFormat, RunFlags flags) 
    { 
     if (!input->isValid()) 
     { 
      return *input; 
     } 

     // do stuff with input 
     return *input; 
    } 
}; 

`` `

Там пример QAbstractVideoFilter в исходном коде Qt: http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl.

Чтобы упростить задачу, рассмотрите возможность использования внутренней функции Qt qt_imageFromVideoFrame для преобразования QVideoFrame в QImage. Этот код работает для корпуса NoHandle и работает на большинстве платформ. К сожалению, он не работает на многих устройствах Android, потому что QVideoFrame::map() вернет false.

extern QImage qt_imageFromVideoFrame(const QVideoFrame& f); 

для Android, вам нужно обрабатывать GLTextureHandle случай, когда вы используете OpenGL для заполнения QImage.

На некоторых устройствах внутренние битовые буферы изображения будут отображаться с переворачиванием.

#ifdef Q_OS_ANDROID 
    bool flip = true; 
#else 
    bool flip = surfaceFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop; 
#endif 

На некоторых устройствах изображение также может быть повернуто. Наилучшим способом обработки вращения является autoOrientation: true в компоненте VideoOutput. Затем ваш компонент может просто взять копию videoOutput.orientation.

Знание того, как изображение перевернуто и повернуто, поможет в распознавании видеосигнала (например, распознавании лиц).

Я также создал минимальный рабочий образец на https://github.com/stephenquan/MyVideoFilterApp