C
Qt Quick Ultralite 相机示例
演示了如何将平台特定的图像数据与 QML UI 集成。
概述
此示例演示了如何处理平台特定的图像数据。它具有一个简单的用户界面来控制相机并使用 Qul::SharedImage 访问其帧。示例使用支持板上摄像头硬件,以及为其他板的模拟实现。
目标平台
项目结构
示例由一个简单的 UI(camera.qml)、摄像头界面定义(camerainterface.h)、NXP平台上摄像头界面的实现以及摄像头界面的模拟实现(在 platform
目录中)组成。此外,还有一个背景图像资产(bg_qt.png)。
CMake 项目文件
除 Qt Quick Ultralite 应用程序的 CMake 设置外,还包括包含 NXP 和模拟摄像头界面实现的 platform 子目录。
add_subdirectory(platform)
在 QmlProject 文件中,它还注册了摄像头界面,以便 Qt Quick Ultralite 能够找到它。
InterfaceFiles { files: [ "camerainterface.h" ] }
在 platform 目录中的 CMakeLists.txt 文件在选择实现之前会检查平台。
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 引脚复用配置和摄像头 I2C 功能。此外,摄像头支持代码和驱动程序是使用 MCUXpresso SDK 编译的。
应用程序 UI
用户界面是在 camera.qml 中实现的。
应用程序通过显示背景图像和“启动相机”按钮开始。点击该按钮后,将启动摄像头图像流并启用“拍摄”和“停止”按钮。点击“拍摄”按钮停止摄像头流到可见的帧,并启用“最小化”和“关闭”按钮。点击“最小化”按钮将当前可见的帧最小化到右上角,点击“关闭”按钮将启用先前状态。点击“停止”按钮停止摄像头流并切换回开始状态。
用户界面代码中有趣的部分是 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::Singleton 接口,包含 Qul::EventQueue。事件队列用于将相机帧异步地从平台传递到 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 &); };
首先,相机接口引入了类型为 image 的 Qul::SharedImage 属性。此属性包含来自平台相机流的帧数据。在此之后,声明了用于控制相机的函数。有 initCamera() 函数以初始化平台相机,以及 startCamera() 和 stopCamera() 以开始和停止相机流。覆盖了 Qul::EventQueue 的 onEvent() 函数以处理图像更新。最后,阻止了外部构造和复制。
相机接口实现
相机接口的实现位于 platform 目录中。该 dummy 子目录包含一个演示实现,该实现实现了接口的存根函数。这可以作为将示例移植到另一个平台的起点。
#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});
在 onEvent()
中处理 FrameEvent
,在此处构建了具有自定义清理函数的 Qul::Image,并将其封装在 Qul::SharedImage 中,然后将它设置为 image
属性的值。
image.setValue(Qul::SharedImage(newFrame));
当 Qt Quick Ultralite 引擎销毁 Qul::SharedImage 引用时,将调用 cleanup
函数。函数的 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。
在特定 Qt 许可证下提供。
了解更多信息。