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::EventQueue のonEvent()関数は、画像の更新を処理するためにオーバーライドされます。最後に、外部からの構築とコピーが防止されます。
カメラ・インターフェースの実装
カメラ・インターフェースの実装はプラットフォーム・ディレクトリにあります。ダミーのサブディレクトリにはダミーの実装があり、インターフェースのスタブ関数を実装しています。これはサンプルを他のプラットフォームに移植する際の出発点として使用できます:
#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});FrameEvent はonEvent() で処理され、カスタムクリーンアップ関数を持つ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));ファイル
- camera/CMakeLists.txt
- camera/camera.qml
- camera/camerainterface.h
- camera/mcu_camera.qmlproject
- camera/platform/CMakeLists.txt
- camera/platform/dummy/CMakeLists.txt
- camera/platform/dummy/camerainterface.cpp
- camera/platform/nxp/CMakeLists.txt
- camera/platform/nxp/camerainterface.cpp
- camera/platform/nxp/pin_mux_csi.c
- camera/platform/nxp/pin_mux_csi.h
画像:
Qul::SharedImage 、Qul::Image 、Qul::EventQueue 、Qul::Singletonも参照してください 。