このページでは

C

Qt Quick ウルトラライトカメラ 使用例

プラットフォーム固有の画像データをQML UIと統合する方法を示します。

概要

この例では、プラットフォーム固有の画像データの扱い方を示します。Qul::SharedImage を用いてカメラを制御し、フレームにアクセスするためのシンプルなユーザインタフェースを備 えています。この例では、サポートされているボードのカメラハードウェアと、その他のボードのダミー実装を使用します。

対象プラットフォーム

プロジェクト構成

サンプルは、シンプルなUI(camera.qml)、カメラインターフェース定義(camerainterface.h)、NXP プラットフォーム用のカメラインターフェースの実装、カメラインターフェースのダミー実装(platform ディレクトリ)で構成されています。さらに、背景画像アセット(bg_qt.png)があります。

CMakeプロジェクトファイル

Qt Quick UltraliteアプリケーションのCMakeセットアップに加え、NXP およびダミーのカメラインターフェース実装を含むプラットフォームサブディレクトリが含まれています。

add_subdirectory(platform)

QmlProjectファイルでは、Qt Quick Ultraliteがカメラインターフェースを見つけられるように登録します。

        InterfaceFiles {
                files: [
                        "camerainterface.h"
                ]
        }

platformディレクトリのCMakeLists.txtは実装を選択する前にプラットフォームをチェックします:

# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial
message(STATUS "Board manufacturer: ${BOARD_MANUFACTURER_NAME}")

string(REGEX MATCHALL "([^\-]+|[^\-]+$)" PLATFORM_COMPONENTS ${QUL_PLATFORM})
list(GET PLATFORM_COMPONENTS 0 BOARD_NAME)
string(TOLOWER ${BOARD_NAME} BOARD_NAME)

if(NOT ${BOARD_NAME} STREQUAL "mimxrt1170" AND ${BOARD_MANUFACTURER_NAME} STREQUAL "nxp")
    add_subdirectory(nxp)
else()
    add_subdirectory(dummy)
endif()

このサンプルはMCUXpresso SDKが提供するコードに依存しています。そのコードをQt Quick Ultraliteプラットフォーム・ライブラリに追加する代わりに、サンプルに追加します。このコードは主にCSIピンmux設定とカメラI2C機能を扱います。また、カメラサポートコードとドライバはMCUXpresso SDKからコンパイルされます。

アプリケーションUI

ユーザーインターフェースはcamera.qmlに実装されています。

アプリケーションは背景画像とカメラ開始ボタンを表示して起動します。ボタンをクリックすると、カメラ画像ストリームが開始され、撮影ボタンと停止ボタンが有効になります。Shootボタンをクリックすると、表示されていたフレームまでカメラ・ストリームが停止し、MinimizeボタンとCloseボタンが有効になります。最小化ボタンは現在表示されているフレームを右上に最小化し、閉じるボタンは前の状態を有効にします。Stopボタンをクリックすると、カメラ・ストリームが停止し、開始状態に戻ります。

ユーザー・インターフェース・コードの興味深い部分は、cameraView Image タイプです:

    Text {
        id: message
        color: "red"
        font.pixelSize: 14
    }

    Image {
        id: cameraView
        anchors.right: parent.right
        anchors.top: parent.top
        source: CameraInterface.image
        width: 0
        height: 0

        Behavior on width { NumberAnimation { duration: 500; easing.type: Easing.OutCubic } }
        Behavior on height { NumberAnimation { duration: 500; easing.type: Easing.OutCubic } }

        Component.onCompleted: {
            if (!CameraInterface.initCamera()) {
                console.log("Camera initialization failed");
                message.text =
                    "Camera initialization failed.\nConnect a camera and/or check the serial console output.";
            }
        }

        SequentialAnimation on opacity {
            id: shootAnimation
            PropertyAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200}
            PropertyAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200}
        }
    }

これは、カメラ・インターフェースのimage プロパティをsource プロパティにバインドします。また、イベント・ハンドラからinitCamera() を呼び出してカメラを初期化します。

カメラ・インターフェース

カメラ・インターフェースは、Qul::EventQueue を持つ単純なQul::Singleton インターフェースです。イベント・キューは、プラットフォームからQt Quick Ultralite アプリケーションにカメラ・フレームを非同期に配信するために使用されます。

まず、カメラ・フレーム・データへのポインタを保持する単純な構造体が定義されます:

struct FrameEvent
{
    uint8_t *newFrame;
};

この構造体はQul::EventQueue のイベント・データ型として使用されます。

以下はカメラ・インターフェースの定義です:

struct CameraInterface : public Qul::Singleton<CameraInterface>, public Qul::EventQueue<FrameEvent>
{
    Qul::Property<Qul::SharedImage> image;

    bool initCamera();
    void startCamera();
    void stopCamera();

private:
    void onEvent(const FrameEvent &frame) QUL_DECL_OVERRIDE;

    friend struct Qul::Singleton<CameraInterface>;
    CameraInterface() {}
    CameraInterface(const CameraInterface &);
    CameraInterface &operator=(const CameraInterface &);
};

まず、カメラ・インターフェースは、Qul::SharedImage タイプのイメージ・プロパティを導入します。このプロパティには、プラットフォーム・カメラ・ストリームのフレーム・データが含まれます。この後、カメラを制御する関数が宣言されます。initCamera()関数はプラットフォーム・カメラを初期化し、startCamera()関数とstopCamera()関数はカメラ・ストリームを開始および停止します。Qul::EventQueueonEvent()関数は、画像の更新を処理するためにオーバーライドされます。最後に、外部からの構築とコピーが防止されます。

カメラ・インターフェースの実装

カメラ・インターフェースの実装はプラットフォーム・ディレクトリにあります。ダミーのサブディレクトリにはダミーの実装があり、インターフェースのスタブ関数を実装しています。これはサンプルを他のプラットフォームに移植する際の出発点として使用できます:

#include "camerainterface.h"

/* Initialize your platform's camera hardware in this function. */
bool CameraInterface::initCamera()
{
    return false;
}

/* Start camera stream. */
void CameraInterface::startCamera() {}

/* Stop camera stream. */
void CameraInterface::stopCamera() {}

/* When the camera frame is ready, the image property can be updated in this event handler. */
void CameraInterface::onEvent(const FrameEvent &frameEvent)

nxpサブディレクトリにはNXP ボード用の実装があります。この実装では、NXP のカメラ・レシーバー API を使用します。initCamera() でカメラ・レシーバーを初期化し、新しいフレームを受信するためのコールバック関数と、this のポインタをユーザー・データとして設定し、Qul::EventQueue を通じてイベントを投稿できるようにします。

    err = CAMERA_RECEIVER_Init(&cameraReceiver, &cameraConfig, newCameraFrame, this);

また、空のカメラ・フレーム・バッファもカメラ・レシーバに送信されます。

    for (uint32_t i = 0; i < CAMERA_BUFFER_COUNT; i++) {
        err = CAMERA_RECEIVER_SubmitEmptyBuffer(&cameraReceiver, (uint32_t) (s_cameraBuffers[i]));
        RETURN_FALSE_IF(err != kStatus_Success, "Failed to submit camera buffer!");
    }

カメラレシーバはnewCameraFrame コールバックを介して新しいフレームを通知します。コールバックは新しいカメラフレームへのポインタを含むFrameEvent

    me->postEventFromInterrupt(FrameEvent{(uint8_t *) cameraFrameAddr});

FrameEventonEvent() で処理され、カスタムクリーンアップ関数を持つQul::Image が構築され、Qul::SharedImage でラップされ、image プロパティの値として設定されます。

    image.setValue(Qul::SharedImage(newFrame));

cleanup 関数は、Qt Quick Ultralite エンジンがQul::SharedImage 参照を破棄するときに呼び出されます。関数のmemory 引数は、image プロパティを使用してQt Quick Ultralite エンジンに渡されたバッファを指します。空のバッファは、新しいカメラフレームが利用可能になるたびにアクセスするために再利用されます。

    status_t err = CAMERA_RECEIVER_SubmitEmptyBuffer(&cameraReceiver, (uint32_t) (memory));

ファイル

画像:

Qul::SharedImage,Qul::Image,Qul::EventQueue, およびQul::Singletonも参照してください


詳細はこちら。