警告

本节包含从C++自动翻译到Python的代码片段,可能包含错误。

相机概览

相机取景器、静态图像捕捉和视频录制。

Qt Multimedia API 提供了许多与相机相关的类,因此您可以访问来自移动设备相机或网络相机的图像和视频。对于常见任务,有C++和QML API。

相机功能

为了使用相机类,需要快速了解相机的工作原理。如果你已经熟悉这一点,可以跳过直接查看相机实现细节。有关相机工作原理的更详细解释,请观看以下YouTube视频。

镜头组件

在相机组件的一端是镜头组件(一个或多个镜头,排列成将光线聚焦到传感器上)。镜头本身有时可以移动以调整焦点和变焦等。它们也可能固定在一个排列中,以在保持焦点和成本之间取得良好的平衡。

../_images/how-focus-works.gif ../_images/Zoom.gif

一些镜头组件可以自动调整,以便将距离相机不同距离的物体保持在焦点上。这通常通过测量画面中特定区域的清晰度,然后调整镜头组件以找到最佳清晰度来实现。在某些情况下,相机将始终使用画面的中心进行此操作。在其他情况下,相机可能还允许指定此目标对焦区域。此功能的一些示例包括:

  • 面部缩放:使用计算机视觉检测并使用一个或多个面部作为目标。

  • 触摸缩放:允许用户通过预览屏幕手动选择一个区域。

传感器

一旦光线到达传感器,它就会被转换成数字像素。这个过程可能取决于许多因素,但最终归结为两件事:

  • 允许进行时间转换的长度。也称为曝光时间。

  • 光的亮度如何。

转换时间越长,生成的图像质量越好。使用闪光灯可以帮助更多的光线照射到传感器上,使其更快地转换像素,从而在相同的时间内获得更好的质量。相反,允许更长的转换时间可以让你在更暗的环境中拍摄照片,只要相机保持稳定。如果相机在传感器记录时移动,生成的图像会模糊。

图像处理

图像被传感器捕捉后,相机固件会对其执行各种图像处理任务,以补偿各种传感器特性、当前光照和所需的图像属性。更快的传感器像素转换时间可能会引入数字噪声,因此可以根据相机传感器设置进行一定量的图像处理来消除这种噪声。

在这个阶段,还可以调整图像的颜色以补偿不同的光源 - 荧光灯和阳光会使同一物体呈现出非常不同的外观,因此可以根据图片的白平衡(由于光源的不同色温)来调整图像。

../_images/image_processing.png

在这个阶段也可以执行一些“特殊效果”。可以生成黑白、棕褐色或“负片”风格的图像。

为后代记录

最后,一旦创建了一个完美聚焦、曝光和处理过的图像,它就可以派上用场了。相机图像可以通过应用程序代码进一步处理(例如,检测条形码或拼接全景图像),或者保存为JPEG等常见格式,或者用于创建电影。许多这些任务都有类来辅助完成。

相机实现细节

检测和选择相机

在使用相机API之前,您应该在运行时检查是否有可用的相机。如果没有可用的相机,您可以在应用程序中禁用与相机相关的功能。要在C++中执行此检查,请使用videoInputs()函数,如下例所示:

def checkCameraAvailability():

    if QMediaDevices.videoInputs().count() > 0:
        return True
else:
        return False

使用C++中的QCamera类或QML中的Camera类型访问相机。

当有多个摄像头可用时,您可以指定使用哪一个。

在C++中:

cameras = QMediaDevices.videoInputs()
for cameraDevice in cameras:
    if cameraDevice.description() == "mycamera":
        camera = QCamera(cameraDevice)

在QML中,您可以通过设置Camera::cameraDevice属性来选择相机。您还可以根据相机在系统上的物理位置而不是相机信息来选择相机。这在移动设备上非常有用,因为移动设备通常有一个前置摄像头和一个后置摄像头。

在C++中:

camera = QCamera(QCameraDevice.FrontFace)

在QML中,您可以设置CameracameraDevice属性。可用的摄像头可以通过MediaDevices.videoInputs获取。

在QML中:

如果未指定QCameraDevice和位置,则将使用默认相机。在桌面平台上,默认相机由用户在系统设置中设置。在移动设备上,后置相机通常是默认相机。您可以使用defaultVideoInput()MediaDevices .defaultVideoInput在QML中获取默认相机。

预览

虽然并非绝对必要,但能够看到相机指向的内容通常很有用。这被称为预览。

根据您使用的是QML还是C++,您可以通过多种方式实现这一点。在QML中,您可以一起使用Camera和videoOutput来监控captureSession。

在C++中,你的选择取决于你使用的是widgets还是QGraphicsView。QVideoWidget类用于widgets的情况,而QGraphicsVideoItem对于QGraphicsView非常有用。

captureSession = QMediaCaptureSession()
camera = QCamera()
captureSession.setCamera(camera)
viewfinder = QVideoWidget()
captureSession.setVideoOutput(viewfinder)
viewfinder.show()
camera.start() # to start the camera

对于高级用法(例如处理预览帧以检测对象或模式),您也可以使用自己的QVideoSink并将其设置为QMediaCaptureSession的videoOutput。在这种情况下,您需要通过处理从videoFrameChanged()信号接收到的数据来自己渲染预览图像。

captureSession = QMediaCaptureSession()
camera = QCamera()
captureSession.setCamera(camera)
mySink = QVideoSink()
captureSession.setVideoOutput(mySink)
camera.start()
# MyVideoSink::setVideoFrame(..) will be called with video frames

在移动设备上,预览图像默认与设备的方向一致。因此,当用户旋转设备时,预览图像将在纵向和横向模式之间切换。一旦开始录制,方向将被锁定。为了避免不良的用户体验,您还应在录制时锁定应用程序用户界面的方向。这可以通过使用QWindow的contentOrientation属性来实现。

静态图像

在设置好取景器并找到适合拍摄的景物后,为了捕捉图像,我们需要初始化一个新的QImageCapture对象。然后只需要启动相机并捕捉图像。

captureSession = QMediaCaptureSession()
camera = QCamera()
captureSession.setCamera(camera)
imageCapture = QImageCapture()
captureSession.setImageCapture(imageCapture)
camera.start() # Viewfinder frames start flowing
#on shutter button pressed
imageCapture.capture()

电影

之前我们看到了允许捕获静态图像的代码。录制视频需要使用一个QMediaRecorder对象。

为了录制视频,我们需要像之前一样创建一个相机对象,但这次除了创建取景器外,我们还将初始化一个媒体录制器对象。

captureSession = QMediaCaptureSession()
camera = QCamera()
captureSession.setCamera(camera)
recorder = QMediaRecorder(camera)
captureSession.setRecorder(recorder)
camera.start()
# setup output format for the recorder
format = QMediaFormat(QMediaFormat.MPEG4)
format.setVideoCodec(QMediaRecorder.VideoCodec.H264)
format.setAudioCodec(QMediaRecorder.AudioCodec.MP3)
recorder.setMediaFormat(settings)
#on shutter button pressed
recorder.record()
# sometime later, or on another press
recorder.stop()

来自QMediaRecorder的信号可以连接到槽,以响应编码过程状态的变化或错误事件。当调用record()时,录制开始。这会导致信号recorderStateChanged()被发出。录制由QMediaRecorder的record()、stop()和pause()槽控制。

控制成像管道

现在我们已经介绍了捕获图像和视频的基础知识,接下来有多种方法可以控制成像管道以实现一些有趣的技术。如前所述,多个物理和电子元素共同决定了最终的图像,您可以使用不同的类来控制它们。

聚焦和缩放

QCamera 允许您通过 FocusMode 的枚举来设置通用的对焦策略。FocusMode 处理诸如 FocusModeAutoFocusModeInfinity 等设置。

对于支持它的相机硬件,FocusModeAutoNear 允许对靠近传感器的物体进行成像。这在条形码识别或名片扫描等应用中非常有用。

除了对焦,QCamera 还允许您使用 setZoomFactor()zoomTo() 控制任何可用的缩放功能。可用的缩放范围可能受到限制或完全固定为1:1。允许的范围可以通过 minimumZoomFactor()maximumZoomFactor() 进行检查。

曝光、快门速度和闪光灯

有许多设置会影响到达相机传感器的光量,从而影响最终图像的质量。

自动拍摄图像的主要设置是exposure modeflash mode。其他一些设置(例如:ISO设置和曝光时间)通常由系统自动管理,但也可以根据需要手动覆盖。

最后,您可以使用此类控制闪光硬件(如果存在)。在某些情况下,硬件也可能兼作手电筒。

图像处理

QCamera 类允许你调整图像处理部分的流程。这些设置包括:

  • white balance(也称为色温)

大多数相机都支持所有这些自动设置,因此除非用户想要特定的设置,否则您不需要调整它们。

取消异步操作

各种操作,如图像捕捉和自动对焦,是异步发生的。只要相机支持,这些操作通常可以通过开始一个新操作来取消。

示例

有C++和QML示例可供使用。

C++ 示例

Camera-Example

展示如何捕捉静态图像或录制视频。

QML 示例

QML-Camera-Application

这个基于Qt Quick的应用程序展示了如何使用API来捕捉静态图像或视频。

QML-Video-Recorder

使用Qt Quick录制音频和视频。

参考文档

C++ 类

PySide6.QtMultimedia.QCamera

QCamera类提供了系统摄像头设备的接口。

PySide6.QtMultimedia.QCameraFormat

QCameraFormat 类描述了相机设备支持的视频格式。

PySide6.QtMultimedia.QCameraDevice

QCameraDevice 类提供了关于相机设备的一般信息。

PySide6.QtMultimedia.QImageCapture

QImageCapture 类用于录制媒体内容。

QML 类型

qml-qtmultimedia-camera.html

一个用于与对焦和缩放相关的相机设置的界面。

qml-qtmultimedia-imagecapture.html

用于捕捉相机图像的接口。