You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓设备Kivy+OpenCV环境下cv2.VideoCapture无法打开摄像头求助

修复方案

核心问题定位

  • 安卓6.0及以上系统要求运行时动态申请敏感权限,仅在buildozer.spec中声明CAMERA权限无效,无权限导致OpenCV无法读取摄像头数据
  • 代码中调用的cv2.namedWindow、cv2.imshow等API依赖桌面端窗口系统,安卓无对应实现,会直接导致摄像头读取线程崩溃
  • 缺少cam.read()返回结果校验,读取失败时处理空帧会触发异常
  • 安卓端OpenCV的VideoCapture需要指定安卓专属接口参数才能正常调用摄像头

第一步:修改buildozer.spec配置

精简依赖项,避免无关包导致打包异常:

[app]
title = OpenCVCam
package.name = opencvcam
package.domain = org.test
source.dir = .
source.include_exts = py,png,jpg,kv,atlas,xml
version = 0.1

requirements = python3,kivy,opencv,numpy,plyer
orientation = portrait

# Android specific
fullscreen = 0
android.permissions = INTERNET,CAMERA,WRITE_EXTERNAL_STORAGE
android.arch = arm64-v8a
android.api = 33
[buildozer]
log_level = 2
warn_on_root = 1

注:推荐将android.arch改为arm64-v8a适配现在的主流安卓设备,armeabi-v7a已经逐步被淘汰。

第二步:修改main.py代码

调整逻辑顺序,新增权限申请,删除无效的窗口API调用:

import threading
from functools import partial
import cv2
from kivy.app import App
from kivy.clock import Clock
from kivy.graphics.texture import Texture
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from plyer import permission


class MainScreen(Screen):
    pass


class Manager(ScreenManager):
    pass


Builder.load_string('''
<MainScreen>:
    name: "Test"

    FloatLayout:
        Label:
            text: "Webcam from OpenCV?"
            pos_hint: {"x":0.0, "y":0.8}
            size_hint: 1.0, 0.2

        Image:
            id: vid
            size_hint: 1, 0.6
            allow_stretch: True
            keep_ratio: True
            pos_hint: {'center_x':0.5, 'top':0.8}

        Button:
            text: 'Stop Video'
            pos_hint: {"x":0.0, "y":0.0}
            size_hint: 1.0, 0.2
            font_size: 50
            on_release: app.stop_vid()
''')


class Main(App):
    def build(self):
        sm = ScreenManager()
        self.main_screen = MainScreen()
        sm.add_widget(self.main_screen)
        # 先申请摄像头权限,授权通过后再启动摄像头线程
        permission.request_permission("android.permission.CAMERA", self.on_camera_permission)
        return sm
    
    def on_camera_permission(self, permissions, results):
        # 检查权限是否申请成功
        if all(res for res in results):
            threading.Thread(target=self.doit, daemon=True).start()
        else:
            self.main_screen.ids.vid.text = "摄像头权限被拒绝,无法使用功能"

    def doit(self):
        self.do_vid = True
        # 安卓端指定CAP_ANDROID接口调用摄像头
        cam = cv2.VideoCapture(cv2.CAP_ANDROID + 0)
        # 可选:设置摄像头分辨率,减少卡顿
        cam.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

        while self.do_vid:
            ret, frame = cam.read()
            # 只有读取到有效帧才做后续处理
            if not ret:
                continue
            
            # 这里可以加你的自定义图形绘制逻辑
            # ...

            Clock.schedule_once(partial(self.display_frame, frame))
        cam.release()

    def stop_vid(self):
        self.do_vid = False

    def display_frame(self, frame, dt):
        texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        texture.blit_buffer(frame.tobytes(order=None), colorfmt='bgr', bufferfmt='ubyte')
        texture.flip_vertical()
        texture.flip_horizontal()
        self.main_screen.ids.vid.texture = texture


if __name__ == '__main__':
    Main().run()

额外注意事项

  • 首次启动应用时会弹出摄像头权限申请弹窗,必须点击允许才能正常使用
  • 如果需要切换前后摄像头,将cv2.CAP_ANDROID + 0改为cv2.CAP_ANDROID + 1即可
  • 打包时建议使用最新版buildozer,避免旧版本的安卓适配问题

内容的提问来源于stack exchange,提问作者Jananda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:21:00