2015-01-20 2 views
13

일부 이미지 처리 기능이있는 Qt5.4 기반 프로그램이 있습니다. 나는 QCameravideoSurface (QAbstractVideoSurface에서 파생 됨)을 사용하여 VideoFrames를 얻습니다. 그것은 Windows에서 잘 작동합니다.Qt QML 카메라 - C++ QImage (안드로이드)

하지만 지금 내 앱의 Android 버전이 필요합니다. QCamera이 Android에서 작동하지 않는다는 것을 알았습니다. 하지만 QML 카메라 예제는 문제없이 Android에서 실행됩니다.

그래서 QML로 응용 프로그램을 다시 작성하기로 결정했습니다. 주요 문제 : C++에서 QML 카메라 표면에 액세스 할 수 없습니다.

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(); 
} 

이 코드는 속성에 대한 액세스 권한을 부여합니다. 하지만 videoSurface에이 방법으로 액세스 할 수 없습니다 (QCamera 사용). 어떻게 QML 카메라가 작동하는지 궁금하네요? 그것은 QCamera을 기반으로합니까?

  1. 는 C++에서 가공 후의 이미지 QML 카메라를 사용할 수있다 : 나는

    그래서 나는이 개 질문이 ... QDeclarativeCamera에서 QCamera *m_camera 참조? 실용 예제는 매우 가치있을 것입니다.
  2. Qt에서 Android 카메라로 비디오를 캡처하는 다른 방법을 알고 계십니까?

답변

9

1) 가능합니다. 나는 그것을하기위한 두 가지 방법이있다.

QVideoFilterRunnable 클래스 (QT 5.5 만 해당)와 함께 QAbstractVideoFilter를 사용하면 매우 좋습니다. 이 시나리오를 위해 특별히 개발되었으며 사용하기가 쉽습니다.

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 말했다 것처럼, 안드로이드 디바이스들 QVideoFrame의 포인터 즉,된다

그것을 사용하여 웹에 대한 몇 가지 좋은 사례가있다 doesnt는 원시 픽셀 데이터를 가지고 있습니다. 대신 OpenGL Texture를 읽어야합니다. (두 번째 예제는 이것을 해결하는 해결 방법이 있습니다.) 따라서이 접근법은 실시간으로 IMHO에 유용하지 않습니다.

이 문제를 해결하기 위해 내가 무엇을 사용했는지는 QVideoProbe 클래스입니다.

먼저 당신이 당신의 QML 카메라의 인스턴스 이름을 가지고

Camera { 
    id: camera 

    objectName: "qrCameraQML" 
} 

이 그럼 당신은 C++ 측면에서이 인스턴스를 얻기를, 무언가 같이 :

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

QML 카메라의 인스턴스는 실제로 QVariant있다 QCamera로 캐스팅 할 수있는 C++를 통해서만 액세스 할 수있는 요소 * :

내 예를 들어 camera_에

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

probe_.setSource(camera_); 

및 probe_는 단순히 : 게요 당신이해야 할 것은 실제로 QCamera * previouslly 캐스트로 프로브의 소스를 설정 한 후 QVideoFrames을 처리 할 것 슬롯에 프로브를 연결하는 것입니다 :

QCamera *camera_; 

QVideoProbe probe_; 

내 경험에 이러한 접근 방식은 Qt는 비디오 필터 클래스를 사용하는 것보다 훨씬 빨리 (안드로이드 플랫폼)을했지만, 그것은 당신이 기본적으로 만 QML에서 비디오 출력을 읽을 단점을 가지고 있으며, AFAIK 당신이 늘 수 qml로 후 처리 된 비디오 프레임을 보낼 수 있습니다.

처리 된 이미지를 qml로 다시 보내야하는 경우 첫 번째 방법을 시도하고 어떤 결과가 발생하는지 확인하는 것이 좋습니다.

2) Qt AFAIK에는 없거나 OpenCv 또는 기타 lib가있을 수 있습니다.

+0

에 최소한의 작업 예제를 만들었습니다. GLTextureHandle을 처리하는 OpenGL 코드를 강조하고 싶습니다. 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에서 사용할 수 있도록 항목을 칠하기 만하므로 다른 모든 처리가 백엔드에서 계속되므로 카메라에서 사용하는 매트 이미지를 처리에 사용할 수 있습니다.

5

@ waldez-junior의 첫 번째 대답을 강조하고 싶습니다. QML에서는 QAbstractVideoFilter 구성 요소를 VideoOutput에 추가합니다. C++에서

Camera { 
    id: camera 
} 

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

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

, 당신은 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; 
    } 
}; 

```

Qt는 소스 코드의 QAbstractVideoFilter 예있다 : http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl.

더 쉽게하려면 Qt 내부 기능 qt_imageFromVideoFrame을 사용하여 QVideoFrameQImage으로 변환하는 것이 좋습니다. 이 코드는 NoHandle 케이스에서 작동하며 대부분의 플랫폼에서 작동합니다. 안타깝게도 QVideoFrame::map()false을 반환하기 때문에 많은 Android 기기에서 작동하지 않습니다.

extern QImage qt_imageFromVideoFrame(const QVideoFrame& f); 

안드로이드를 들어, 당신은 당신이 QImage을 채울 수는 OpenGL을 사용하는 GLTextureHandle 경우를 처리 할 필요가있다.

일부 장치에서는 이미지 내부 비트 버퍼가 뒤집혀 나타납니다.

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

일부 장치에서는 이미지가 회전 할 수도 있습니다. 회전을 처리하는 가장 좋은 방법은 VideoOutput 구성 요소에 autoOrientation: true으로 설정하는 것입니다. 그런 다음 구성 요소에 videoOutput.orientation 사본을 가져갈 수 있습니다.

이미지가 뒤집어지고 회전되는 방법을 알고 있으면 비디오 인식 응용 (예 : 얼굴 인식)에 도움이됩니다.

는 또한 훌륭한 작품을 QVideoFilterRunnable` 클래스`와`QAbstractVideoFilter`를 사용 https://github.com/stephenquan/MyVideoFilterApp