[Python] cv2.VideoCapture in python not working on android

Discussão em 'Python' iniciado por Stack, Março 23, 2025.

  1. Stack

    Stack Membro Participativo

    I am making a program for Android that shows a demonstration of the PC screen on the phone. On Windows the code works fine, but when I build the apk via Bulldozer and try to connect via IP to the server where the image is taken, an error appears in the console (via adb logcat). Application code:

    from kivymd.app import MDApp
    from kivy.lang import Builder
    from kivy.uix.image import Image
    from kivy.clock import Clock
    from kivy.graphics.texture import Texture
    import cv2
    import numpy as np
    import logging

    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    KV = '''
    #<KvLang>
    MDScreen:
    MDBoxLayout:
    orientation: 'vertical'
    padding: dp(20)
    spacing: dp(10)

    MDTextField:
    id: ip_input
    mode: "outlined"
    size_hint_y: None
    height: "50dp"
    MDTextFieldHintText:
    text: "Enter the server IP address"

    MDButton:
    on_release: app.start_stream()
    size_hint_y: None
    height: "50dp"
    MDButtonText:
    text: "Connect"

    BoxLayout:
    id: image_container
    size_hint: (1, 1)
    pos_hint: {"center_x": 0.5, "center_y": 0.5}

    MDLabel:
    id: status_label
    text: "Status: Waiting for connection"
    halign: "center"
    size_hint_y: None
    height: "50dp"
    #</KvLang>
    '''

    class KivyCamera(Image):
    def __init__(self, url, fps=30, **kwargs):
    super(KivyCamera, self).__init__(**kwargs)
    self.url = url
    self.fps = fps
    self.capture = None
    self.status_label = None
    logger.debug(f"Initializing KivyCamera with URL: {url}")

    Clock.schedule_interval(self.update, 1.0 / fps)

    def set_status(self, text):
    try:
    if self.status_label is None:
    parent = self.parent
    while parent is not None:
    if hasattr(parent, 'ids') and 'status_label' in parent.ids:
    self.status_label = parent.ids['status_label']
    break
    parent = parent.parent
    if self.status_label:
    self.status_label.text = text
    except Exception:
    pass

    def update(self, dt):
    try:
    if self.capture is None:
    self.capture = cv2.VideoCapture(self.url)
    if not self.capture.isOpened():
    self.set_status("Status: Connection Error")
    return
    self.set_status("Status: Connected")

    ret, frame = self.capture.read()
    if ret:
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='rgb')
    texture.blit_buffer(cv2.flip(frame, 0).tobytes(), colorfmt='rgb', bufferfmt='ubyte')
    self.texture = texture
    else:
    self.capture.release()
    self.capture = None
    self.set_status("Status: Reconnecting...")

    except Exception as e:
    self.set_status(f"Status: Error - {str(e)}")
    if self.capture:
    self.capture.release()
    self.capture = None

    def __del__(self):
    if self.capture:
    self.capture.release()

    class MainApp(MDApp):
    def __init__(self, **kwargs):
    super(MainApp, self).__init__(**kwargs)
    self.camera_widget = None

    def build(self):
    return Builder.load_string(KV)

    def start_stream(self):
    screen = self.root
    ip_address = screen.ids.ip_input.text

    if not ip_address:
    screen.ids.status_label.text = "Status: Enter IP address"
    return

    if self.camera_widget is not None:
    screen.ids.image_container.remove_widget(self.camera_widget)

    try:
    url = f'http://{ip_address}:5000/video_feed'
    self.camera_widget = KivyCamera(url=url, fps=30)
    screen.ids.image_container.add_widget(self.camera_widget)
    screen.ids.status_label.text = "Status: Connecting..."

    except Exception as e:
    screen.ids.status_label.text = f"Status: Error - {str(e)}"

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


    buildozer.spec:

    requirements = python3,kivy,https://github.com/kivymd/KivyMD/archive/master.zip,opencv_extras,materialyoucolor,numpy,asyncgui,asynckivy
    android.permissions = android.permission.INTERNET, android.permission.CAMERA, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)


    adb logcat:

    03-22 23:32:58.029 13883 15538 E cv::error(): OpenCV(4.5.1) Error: Bad argument (CAP_IMAGES: can't find starting number (in the name of file): http://192.168.0.11:5000/video_feed) in icvExtractPattern, file /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap_images.cpp, line 253
    03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1: [ERROR:0] global /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap.cpp (142) open VIDEOIO(CV_IMAGES): raised OpenCV exception:
    03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1:
    03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1: OpenCV(4.5.1) /home/mapium/python/PyRemoteControl/project_oop/android/.buildozer/android/platform/build-arm64-v8a_armeabi-v7a/build/other_builds/opencv/arm64-v8a__ndk_target_21/opencv/modules/videoio/src/cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): http://192.168.0.11:5000/video_feed in function 'icvExtractPattern'
    03-22 23:32:58.030 13883 15538 E OpenCV/4.5.1:
    03-22 23:32:58.030 13883 15538 E NativeCodec: failed to stat file: http://192.168.0.11:5000/video_feed (No such file or directory)


    If I go to the site from where the screen sharing is taken from my phone, everything works fine there.

    Continue reading...

Compartilhe esta Página