Kivy 的又一个相机
项目描述
Camera4Kivy
Kivy 的又一个相机
本文档包含以下部分:概述、安装、示例、预览小部件、图像分析、相机行为、相机提供程序和已知行为。
仅在 Android 上:
概述
可在所有常用平台上使用。
from camera4kivy import Preview
Camera4Kivy 包含一个Preview带有 api 的小部件,用于连接到物理相机单元。Preview 小部件布局使用 Kivy 属性配置,相机单元和图像分析行为使用 api 配置。例如:
在.kv
Preview:
id: preview
aspect_ratio: '16:9'
在 Python 中
self.preview = Preview(aspect_ratio = '16:9')
要将相机单元连接到预览,请在 on_start() 之后connect_camera()调用预览的方法。例如在启用图像分析 api 的情况下连接相机:
self.preview.connect_camera(enable_analyze_pixels = True)
当相机不再使用时,表现良好的应用程序会断开相机。举止得体很重要。
self.preview.disconnect_camera()
拍照:
self.preview.capture_photo()
可以指定捕获的文件位置,也可以在回调中报告。数据分析 api 允许每帧分析和预览注释或预览图像替换。
在 Android 上,捏/张开手势控制缩放,轻按会覆盖任何自动对焦和测光(如果可用)。一些connect_camera()选项是特定于平台的。
请注意,预览操作取决于图形硬件的性能。一般来说,预览使用最高的可用分辨率。在具有低性能图形硬件的设备上,如低端笔记本电脑或 Raspberry,您可能必须明确设置较低的图像分辨率以提高帧速率。
安装
可能需要相机提供商。在 destop 上,摄像机提供程序安装一次。在 Android 上,相机提供程序被添加到每个项目中。
在桌面上安装 Camera4Kivy
pip3 install camera4kivy
在 Android 上安装 Camera4Kivy
Camera4Kivy 依赖于 Buildozer 1.3.0 或更高版本
pip3 install buildozer
buildozer.spec:
android.api = 30 (或更高,最少 29)
requirements = python3, kivy, camera4kivy, gestures4kivy
设置p4a.hook为启用应用程序对相机提供程序的使用。这将设置所需的 p4a 选项。
p4a.hook = camerax_provider/gradle_options.py
camerax gradle 依赖项的实现是特定于架构的,为 armeabi-v7a 构建的应用程序将在 arm64-v8a 设备上崩溃。
运行时权限
必须在应用程序中请求以下运行时权限。像往常一样在 build() 或 on_start() 之后请求这些。请参阅示例。
始终需要:CAMERA
需要录制带音频的视频:RECORD_AUDIO
捕获照片、屏幕截图或视频并保存到共享存储时需要,并且仅在运行 api_version < 29 的设备上:WRITE_EXTERNAL_STORAGE
在 iOS 上安装 Camera4Kivy
安装 'master'(2022/04/22 或更高版本)的 kivy-ios。
pip3 install git+https://kivy/kivy-ios.git
toolchain build python3 kivy
toolchain pip3 install camera4kivy
运行时权限
iOS需要使用相机和保存图像的权限。启用权限编辑<project>-ios/<project-Info.plist。添加部分或全部这些:
要启用相机添加:
<key>NSCameraUsageDescription</key>
<string> </string>
要启用将图像捕获保存到照片应用程序(默认行为),请添加:
<key>NSPhotoLibraryAddUsageDescription</key>
<string> </string>
要使用文件管理器查看保存到应用程序本地存储的图像:
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
例子
先决条件是安装了工作相机。在继续之前使用平台的相机应用程序对此进行测试。所有示例都使用特定于平台的相机提供程序,并假定典型的默认 camera_id 为“0”。如果您发现该示例未连接到摄像头,请查看可用的摄像头 ID 和您的摄像头提供商选择。
测试示例和平台
照片示例说明了基本的相机用法,请先尝试一下。其余示例说明了使用各种包的图像分析。
在 Android 和 iOS 上,应用程序可以在设备旋转时旋转,在桌面上,您可以更改窗口大小以模拟方向,从而旋转移动设备。
| 例子 | 视窗 | 苹果系统 | Linux | 安卓 | iOS | 珊瑚 |
|---|---|---|---|---|---|---|
| 照片 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | |
| 二维码 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | ||
| 开放式CV | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | ||
| 机器学习套件 | :heavy_check_mark: | |||||
| TFLite | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
- Windows:Windows 11、i7-10 @ 1.1GHz、Python 3.8.2 Kivy==2.1.0.dev0
- Windows:Windows 10,i3-7 @ 2.4GHz,Python 3.9.7 Kivy==2.0.0
- Macos:大苏尔,i5-10 @ @ 1.1GHz,Python 3.9.9 Kivy==2.0.0
- Linux:Raspberry Buster,Cortex-A72 @ 1.5GHz Python3.7.3 Kivy==2.0.0
- Android:构建:arm64-v8a 设备:Android 12,Pixel 5
- Android : build : armeabi-v7a device: Android 6, Nexus 5 启动有点慢。
- iOS:iPhone SE(第二代)
- Coral :加速器在 Windows 11 上进行了测试,提供了大约一个数量级的加速。
C4K-照片示例
使用屏幕说明基本布局。基本的相机功能,包括照片捕获、屏幕截图以及在 Android 上捕获带音频的视频。在 Raspberry PI 上必须使用鼠标,触摸板无法正常工作。
C4K-QR-示例
阅读餐厅菜单所需的一切。长按或双击突出显示的 QR 码以打开 Web 浏览器。说明基本分析、屏幕注释和用户交互。
C4K-OpenCV-示例。
边缘检测视频流。说明使用 OpenCV 分析并用转换后的图像替换原始预览。
C4K-MLKit-示例
人脸检测,MLKit 仅适用于 Android。使用 ImageProxy api 进行说明。
C4K-TFLite-示例
对象分类。使用大型 Tensorflow Lite 模型进行说明,并将文本写入预览图像。
预览小部件
一个应用程序可以有多Preview个小部件,但一次只能将一个小部件连接到物理相机单元。实现此功能的一种自然方法是将预览小部件添加到屏幕内容中,然后连接到相机单元on_enter并断开连接on_pre_leave。C4K-Photo-Example 说明了这一点,其他示例只是在之后连接相机on_start()并断开连接on_stop()。
预览小部件属性
小部件具有配置其布局的这些 Kivy 属性:
纵横比
一个字符串属性。“4:3”(默认)或“16:9”。
信箱颜色
颜色属性。几何告诉我们,固定纵横比小部件的布局几乎总是会导致信箱。Art 告诉我们,我们可以通过用与周围小部件匹配的颜色填充信箱来隐藏信箱。
方向
一个字符串属性。“肖像”、“风景”、“相同”、“相反”之一。默认值与设备或窗口“相同”。此选择会修改有效分辨率,请参阅。始终使用“相同”获得最佳分辨率。
预览小部件 API
该小部件具有以下方法:
连接相机
这只能在 之后调用on_start()。
def connect_camera(self,kwargs):
可选参数:
camera_id
指定要连接的相机。例如camera_id = 'front'. 包含整数的字符串(默认为“0”),或者在 Android 或 iOS 上为“后”(默认)或“前”。
镜像
镜像预览图像,默认为True. 此选项在 Android 和 iOS 上被忽略,按照惯例,“前”总是镜像,“后”从不镜像。此选项通常True适用于面向用户的任何摄像头,以及False任何不面向用户的摄像头。
捕获永远不会被镜像,如果预览被镜像,则截图捕获除外。
像素参数image_analysis_callback()永远不会被镜像,如果预览被镜像texture,任何图像分析的结果都将canvas_instructions_callback()通过 tex_size 和 tex_pos 参数自动镜像。如果图像分析生成图像注释位置,则应用程序必须调整这些位置以进行镜像预览。有关代码片段和示例链接,请参阅图像分析部分。
文件路径回调
在捕获照片、视频或屏幕截图时,此参数指定接收保存文件的路径和名称的方法。例如filepath_callback = my_method,def my_method(self, path):应用程序提供的带有字符串参数的方法在哪里。
照片和视频捕获可以在不同的线程中实现。知道捕获完成的唯一方法是 filepath_callback。在开始捕获之后和 filepath_callback 之前断开相机连接可能会有延迟的后果。
filepath_callback 也可用于重置 UI 中的任何“视频录制”指示器。虽然视频录制通常由用户终止,但也可以通过应用暂停、设备旋转或相机选择来终止。在最后这些情况下,任何记录指示器都可以通过回调重置,无论原因如何,这都会在任何捕获终止时发生。
传感器分辨率
覆盖默认传感器分辨率,这是可用的最高分辨率,但 Raspberry Pi 除外(1024、768)。两个整数的元组,例如sensor_resolution = (640, 480). 获得的捕获分辨率取决于相机提供者的行为(例如,它被 GStreamer 忽略)。捕获分辨率还取决于预览的相对方向和纵横比。将指定的值视为可能无法完全接受的请求。
分析像素分辨率
设置通过的像素分辨率analyze_pixels_callback()。一个标量,表示长边上的像素数,短边使用纵横比确定。例如analyze_pixels_resolution = 720. 默认值为裁剪后的传感器分辨率和 1024 的最小值。
作为替代方案,有时分析包需要设置分辨率。这是按照分析配置self.auto_analyze_resolution中的描述完成的。
enable_analyze_pixels
用于enable_analyze_pixels = True启用analyze_pixels_callback()
enable_analyze_imageproxy
仅用于enable_analyze_imageproxy = True启用analyze_imageproxy_callback()
Android。
enable_zoom_gesture
默认真。仅限安卓和 iOS。
enable_focus_gesture
默认真。仅限安卓。
imageproxy_data_format:
仅适用于 Android ImageProxy api。“yuv420”(默认)或“rgba”。
断开相机
始终这样做,重要的是在不使用时断开相机。
def disconnect_camera(self):
在捕获过程中断开连接通常会导致捕获终止并照常保存结果。
但是,在 Android 上,在启动捕获后立即断开连接可能会阻止文件保存的开始,并且不会保存任何内容。filepath_callback 报告了一条警告消息,这可能会被过滤,如本例所示
捕获
def capture_photo(self, kwargs):
def capture_screenshot(self, kwargs):
def capture_video(self, kwargs): # Android only
def stop_capture_video(self): # Android only
视频捕获仅适用于 Android。
捕获永远不会被镜像,如果预览被镜像,则截图捕获除外。此处讨论捕获分辨率。
捕获保存到<location>/<subdir>/<name>.jpg或.mp4。
默认值如下。在桌面上<location>是当前目录.,在 Android 上<location>是DCIM/<appname>,而在 iOS <location> 上是照片应用程序。的值为<subdir>当前日期,格式为 'YYYY_MM_DD'。的值为<name>当前时间,格式为 'hh_mm_ss_xx'(xx 为 1/100 秒)。
filepath_callback发生在捕获完成时,其参数是特定捕获的实际路径。
请注意,在 Android 上 >= 10 个共享存储文件保存在名为 MediaStore 的数据库中,而不是文件系统中。Android 存储的架构超出了本文档的范围。
<location>、<subdir>和的值<name>可以使用三个capture_方法的可选关键字参数进行修改:
地点
该值替换 的默认值<location>。
在桌面上,该值是必须存在的目录。
在 Android 和 iOS 上,该值只能是'shared'或'private',其他值默认为'shared'。
在 Android 上,该值'shared'指定 Android 共享存储DCIM/<appname>。该值'private'指定应用本地存储 app_storage_path()/DCIM。如果您想要不同的位置'private',请根据 filepath_callback 提供的路径使用并移动生成的文件。
在 iOS 上,该值'shared'指定 iOS 照片应用程序。该值'private'指定应用本地存储。对于'shared'filepath_callback 返回一个空字符串,因为'private'它返回应用程序本地存储中文件的路径。
子目录
该值替换 的默认值<subdir>。该子目录将被创建或添加到 Android MediaStore 路径中。对于 iOS,当location='shared'它被忽略时。
姓名
该值替换默认值<name>,.jpg或.mp4扩展名将自动添加。
请注意,Android MediaStore 的一个特性是,具有与第一个相同的子目录和名称值的第二个捕获不会覆盖第一个。它将创建一个名为 的第二个文件<subdir>/<name> (1).jpg,此名称由 Android MediaStore 创建。如果创建太多(31 个?)这样的名称,MediaStore 可能会崩溃。
对于 iOS,当location='shared'它被忽略时。
选择相机
更改当前连接的摄像头,camera_id 必须指定物理连接的摄像头。
def select_camera(self, camera_id):
飞涨
仅在 Android 上,zoom_delta() 通过捏合/展开手势调用,除非禁用。仅在 iOS 上,除非禁用,否则 zoom_abs() 通过捏合/展开手势调用。
def zoom_delta(self, delta_scale):
def zoom_abs(self, scale):
闪光
仅限安卓。仅用于捕获照片,忽略视频和数据。序列闪光:关、开、自动(默认)、
def flash(self)
重点
仅限 Android,如果在设备上可用。除非禁用,否则由点击手势调用
def focus(x, y):
图像分析
概述和示例
视频数据分析的编程模式是创建一个子类Preview并实现两个预定义的方法。一是分析帧,二是用分析结果修改预览图像。一般是这样的:
class CustomAnalyzer(Preview):
def analyze_pixels_callback(self, pixels, size, image_pos,
image_scale, mirror):
### Add your pixels analysis code here
### Add your coordinate transforms here
def canvas_instructions_callback(self, texture, tex_size, tex_pos):
### Add your Preview annotation or image replacement code here
analyze_pixels_callback()每次有新像素可用时都会调用 ,并且在canvas_instructions_callback()Kivy 事件循环的每次迭代中都会调用 。新像素的可用性取决于相机数据速率,以及之前调用analyze_pixels_callback(). 因此analyze_pixels_callback()通常以小于 的速率调用canvas_instructions_callback(),因此注释更新速率通常小于图像帧速率。
在 Android 上,这是 analyze_pixels_callback() 的替代方法,它仅用于 Android 分析包。
def analyze_imageproxy_callback(self, image_proxy, image_pos,
image_scale, mirror, degrees):
### Add your imageproxy specific analysis code here
保持这种模式。在“analyze_pixel_callback”(或 imageproxy)方法中执行分析和坐标转换。而在 'canvas_instructions_callback' 中只显示之前计算的结果。从分析方法传递到显示方法的数据必须以线程安全的方式传递。
该analyze_pixels_callback方法用于分析其 RGBApixels和size参数。、pos和参数可以将分析scale的mirror像素坐标映射到预览坐标。该mirror参数是必需的,因为pixels图像从不镜像,但预览可能是。一个例子:
def analyze_pixels_callback(self, pixels, image_size, image_pos,
scale, mirror):
# Convert the image encoding
pil_image = Image.frombytes(mode='RGBA', size=image_size,
data= pixels)
# Analyze the image
barcodes = pyzbar.decode(pil_image, symbols=[ZBarSymbol.QRCODE])
# Collect the results and transform the coordinates
found = []
for barcode in barcodes:
text = barcode.data.decode('utf-8')
if 'https://' in text or 'http://' in text:
x, y, w, h = barcode.rect
# Map Zbar coordinates to Kivy coordinates
y = image_size[1] -y -h
# Map Analysis coordinates to Preview coordinates
if mirror:
x = image_size[0] -x -w
x = round(x * scale + image_pos[0])
y = round(y * scale + image_pos[1])
w = round(w * scale)
h = round(h * scale)
found.append({'x':x, 'y':y, 'w':w, 'h':h, 't':text})
# Save the results in a thread safe way
self.make_thread_safe(list(found)) ## A COPY of the list
分析和画布注释回调发生在不同的线程上。分析结果必须以线程安全的方式保存,以便可用于画布回调。我们将结果的副本传递给:
@mainthread
def make_thread_safe(self, found):
self.annotations = found
并将线程安全注释添加到画布。
def canvas_instructions_callback(self, texture, tex_size, tex_pos):
# Add the annotations determinined during analyze callback.
Color(1,0,0,1)
for r in self.annotations:
Line(rectangle=(r['x'], r['y'], r['w'], r['h']), width = dp(2))
我们还可以用一些其他纹理替换现有的预览图像,使用 'tex_size' 和 'tex_pos' 参数定位。使用由于某些图像分析而创建的线程安全纹理,如下所示:
def canvas_instructions_callback(self, texture, tex_size, tex_pos):
# Add a different preview image, which is a transformed camera image
# this image has 'analyze_pixels_resolution'
if self.analyzed_texture:
# 'self.analyzed_texture' contents created
# by analyze_pixels_callback()
Color(1,1,1,1)
Rectangle(texture= self.analyzed_texture,
size = tex_size, pos = tex_pos)
如果需要,新纹理将通过“text_size”和“tex_pos”自动镜像。这些 'text_size' 和 'tex_pos' 参数用于添加纹理,不适用于坐标计算,因为它们可能是镜像的。
有关创建线程安全纹理的详细信息,请参阅 OpenCV 示例。
上面的代码片段在两个示例中完全实现:QR Reader和OpenCV。展示此模式的类似示例是tflite和mlkit。
用户交互
但是等等,还有更多,用户可以在预览中与分析结果进行交互。Preview 子类可能有多重继承,例如允许用户与屏幕上的注释进行交互。QR 阅读器示例通过从手势包继承来说明这一点:
class QRReader(Preview, CommonGestures):
该包的手势回调和注释位置测试用于启动某些操作。在这种情况下,根据 QR 码中的 URL 打开 Web 浏览器,然后在 QR 码周围绘制的框内长按或鼠标双击。
def cg_long_press(self, touch, x, y):
self.open_browser(x, y)
def cg_double_tap(self, touch, x, y):
self.open_browser(x, y)
def open_browser(self, x, y):
for r in self.annotations:
if x >= r['x'] and x <= r['x'] + r['w'] and\
y >= r['y'] and y <= r['y'] + r['h']:
webbrowser.open_new_tab(r['t'])
坐标和图像编码
重要的是,请注意不同的坐标系和图像编码。带有第三方分析代码坐标的打印语句的测试可能很有价值。
-
Kivy 图像坐标的原点位于左下角。大多数其他系统使用左上角(正 y 向下增加)作为它们的原点。
-
Kivy 图像属性是一个 (width, height) 元组。一些包,特别是 numpy 图像,将顺序反转为(高度,宽度)。
-
Kivy 像素采用 RGBA 编码。第三方分析代码可能需要一些其他编码,Pillow 和 OpenCV 都提供编码转换。一些图像重新编码在计算上是昂贵的。
-
'canvas_instructions_callback()' 参数 'tex_size' 和 'tex_pos' 可能是镜像的,它们的值对于坐标映射无效。使用 'image_size' 和 'image_pos' 参数在 'analyze_pixels_callback()' 中执行映射。
分析配置
使用以下参数启用图像分析connect_camera():
connect_camera(enable_analyze_pixels = True)
要更改默认分析分辨率,请指定长边中的像素数(默认为 1024 或裁剪分辨率中的较小者):
connect_camera(enable_analyze_pixels = True, analyze_pixels_resolution = 720)
该analyze_pixels_resolution选项提供与预览具有相同方向和纵横比的分析图像。
作为替代方案,分析软件可以设置self.auto_analyze_resolution[width, height] 的两个元素列表。在这种情况下,不必为分析保持纵横比,该analyze_pixels_callback() image_scale参数是一个包含两个元素的列表 [width, height],允许缩放任何结果。如 c4k_tflite_example 中使用的分类object.py。
仅在 Android 上,imageproxy api 是像素 api 的替代品。
connect_camera(enable_analyze_imageproxy = True)
无论预览方向如何,imageproxy api 都提供横向图像。度数参数可以相应地调整分析。Android 实现了在分析慢的情况下自动改变帧率和分辨率。
调试
检查应用程序分析代码是否符合您的预期。如果结果是坐标(大多数情况),则使用打印语句检查这些。将您希望检测到的任何内容移动到相机视图的四个角。查看打印值,它们是否反映了分析的图像像素大小和方向?将坐标映射到 Kivy 小部件后重复这些坐标。
测量分析算法在一帧上执行的时间。在检测到没有检测到的情况下执行此操作。这连同一些开销将定义最大分析帧速率。tflite示例监控分析帧速率作为其正常操作的一部分。
表现
相机提供图像流以通过 进行分析analyze_pixels_callback()。图像通常以 30 fps 的速度到达,因此考虑到一些开销,应用程序进行分析的时间可能不到 30 毫秒。
该 api 具有内置机制,因此仅在先前的分析完成时才对图像进行分析。这种机制不会改变画布指令的帧速率。如果分析结果“不稳定”,那是因为硬件的分析算法很慢。
相反,您可以使用 Kivy Clock 设置的标志显式降低分析帧速率,而无需更改任何其他内容。接近实际分析速率的时钟速率会出现抖动。例如对于一秒的分析间隔:
self.enable_analyze_frame = True
Clock.schedule_interval(self.analyze_filter,1)
def analyze_filter(self, dt):
self.enable_analyze_frame = True
def analyze_pixels_callback(self, pixels, image_size, image_pos,
scale, mirror):
if self.enable_analyze_frame:
self.enable_analyze_frame = False
# place usual analyse code inside this if block
可以通过各种方式对此进行修改,例如延迟一段时间后的单个样本。
提高性能的一种方法是减少analyze_pixels_resolution如上所示的。此选项可能会改变定性行为,可能是由于某些第三方分析仪中的分辨率偏差。实验一下,一些分析代码在远低于 VGA 分辨率的情况下也能很好地工作。
分析代码必须精简。例如,Keras 是一个完整的开发环境,一大堆你不需要运行推理的东西。将应用程序移植到 Tensorflow Lite,然后使用 tflite-runtime 而不是完整的 Tensorflow Lite。
相机行为
物理相机
相机是具有软件 api 的单个物理设备,尽管它看起来像一个软件对象,但它不是软件对象。它是具有物理约束的物理对象。
解析度
在相机的背景下,分辨率有多种用途。在这种情况下,它始终是一个元组(宽度,高度)。
传感器分辨率
这是传感器模块的物理特性。的默认行为connect_camera()是使用相机提供商提供的最大分辨率。可以使用该sensor_resolution选项覆盖它,但通常相机提供商会将此作为提示,可能会被忽略或重新解释。GStreamer忽略此选项,picamera可能需要它。
裁剪的传感器分辨率
传感器分辨率根据传感器的方向、预览的方向和预览的纵横比进行裁剪。这将影响捕获分辨率,例如,可能会从 4:3 传感器图像中裁剪出 16:9 纵横比的图像。因此,在这种情况下,16:9 的宽度和高度的乘积将小于 4:3 的乘积。
旋转移动设备也会旋转传感器,当 Priview 小部件方向与设备方向相同时,将获得最高分辨率的图像。相反,例如,设备处于纵向的横向预览将导致图像宽度分辨率,即传感器高度分辨率。
这种行为是具有物理约束的相机传感器的特征。值得注意的是,图像传感器通常不是方形的,它们是矩形的,当传感器与捕获的图像具有相同的方向时,它们会提供最高质量的结果。除非传感器分辨率低,或者照片捕获的分辨率低于预期,否则这对应用程序用户来说基本上是透明的。
预览分辨率
是屏幕的物理属性(显示分辨率)和屏幕上的预览小部件大小。预览分辨率可以小于或大于裁剪的传感器分辨率。
捕获分辨率
捕获的分辨率。照片捕捉分辨率是裁剪后的传感器分辨率。视频分辨率是标准分辨率之一,具体取决于裁剪的传感器分辨率。以像素为单位的屏幕截图大小是预览分辨率。
分析分辨率
分析分辨率小于或等于裁剪后的传感器分辨率。为了减少分析时间,以分析分辨率为代价减少这一点可能是有用的。
analyze_pixels_callback()可以使用相机连接选项更改分辨率analyze_pixels_resolution。scale 参数允许将分析结果重新缩放为预览分辨率。
实现了优雅的analyze_imageproxy_callback()降级机制。这会自动降低帧速率和/或图像分辨率。一个非常慢的帧分析将导致馈送停止。
显示屏分辨率。
与相机无关,它是屏幕的物理属性。以 dpi 为单位测量的标量。
相机提供商
Camera4Kivy 依赖于“相机提供者”来访问操作系统相机 api。在大多数平台上,它使用与 Kivy 相同的提供程序,并修改了默认值。
| 平台 | 提供者 | 需要 |
|---|---|---|
| 视窗 | 开放式CV | |
| 流媒体 | ||
| 苹果系统 | AV基金会 | OSX >= 10.7 |
| Linux | 流媒体 | |
| 开放式CV | ||
| 覆盆子 | 皮卡梅拉 | <= 克星 |
| 流媒体 | <= 克星 | |
| 开放式CV | <= 克星 | |
| Picamera2 | >= 靶心 | |
| 安卓 | 相机X | 安卓 >= 5.0 |
| iOS | AV基金会 |
与 Kivy 一样,选择了第一个可用的提供程序。应该预料到某些相机提供商的特定行为。例如,在 MacOS 和 Rasberry Pi 上将忽略切换到不存在的相机,但会使用 OpenCV 或 GStreamer 生成屏幕消息。摄像头分辨率默认为最大可用摄像头提供程序分辨率,但在 Raspberry Pi 上默认为 (1024, 768)。
您可以通过在 from kivy.app import App.
from kivy import kivy_options
providers= list(kivy_options['camera'])
providers.remove('picamera')
kivy_options['camera'] = tuple(providers)
Android 相机提供商
cd <project directory>
git clone https://github.com/Android-for-Python/camerax_provider.git
rm -rf camerax_provider/.git
设置p4a.hook为允许应用程序使用相机提供程序。
p4a.hook = camerax_provider/gradle_options.py
开放式CV
pip3 install opencv-python
GStreamer
取决于 Linux 风格,但通常:
sudo apt-get install gstreamer-1.0
sudo apt-get install gstreamer1.0-dev
皮卡梅拉
预装
Picamera2
AV基金会
预装
已知行为
行为:预览没有 aspect_ratio = 'fill'
没有办法指定倒置信箱。预览精确地填充可用空间的位置,导致捕获或分析的图像的一个轴部分隐藏在预览中。
行为:Raspberry PI Bullseye 不可用
RaspberryPI 视频堆栈随 Bullseye 发生了变化。在 Bullseye 中,目前唯一有效的相机源是libcamera. Picamera 不可用,显然RPI Picamera2 Python 接口正在开发中。并且libcamera与 OpenCV 或 Kivy 的 GStreamer 实现不兼容。
行为:Android 旋转
通过“倒置纵向”旋转物理设备可能会导致“倒置横向”显示。额外旋转到“纵向”并返回到“横向”可以更正显示。
行为:Android .mp4 方向
如果预览方向与设备方向不同,则视频文件方向不正确。录制视频时不要使用此布局配置。谷歌问题跟踪器。
行为:Android .jpg 方向。
一些图像查看器(包括 Kivy Image 小部件)会错误地将 .jpg 显示为旋转 90 度。如果捕获预览方向与设备方向不同,并且第三方查看器不使用 Exif 元数据,则会发生这种情况。
行为:on_start() 期间的 Android connect_camera
在 Android 上,connect_camera()调用 duringon_start()将导致应用启动期间间歇性崩溃。未过滤的 logcat 将包含:'找不到库“libdexfile.so”'。使用 Kivy 时钟来安排connect_camera()稍后的一个时间步。
行为:Android 切换摄像头,短时间倒置图像。
切换摄像头时可能会出现短暂的倒置图像,这在较旧的 Android 设备上更可能发生。
行为:Android armeabi-v7a 构建安装在 arm64-v8a 设备上
Google 的 camerax gradle 依赖项的实现是特定于架构的,为 armeabi-v7a 构建的应用程序将在 arm64-v8a 设备上崩溃。要在 arm64-v8a 设备上运行,您必须为 arm64-v8a 构建。
行为:Android“不支持表面组合”
No supported surface combination is found for camera device - Id : 0. May be attempting to bind too many use cases.
在非常低端的 Android 设备上,相机的硬件资源可能有限。到目前为止,只有一台设备出现了这个问题。默认情况下,c4k 为“照片和视频”或“照片和图像分析”配置 connect_camera() - 这使 api 尽可能简单。但在这种情况下,它对硬件来说太贵了。我们可以覆盖这些配置。
如果连接仅用于照片用途connect_camera(enable_video = False, ...other options..)。如果连接仅用于视频或数据分析使用connect_camera(enable_photo = False, ...other options..)。