0

I need to create an android application using OpenCV VideoCapture() method with python kivy framework. Please note I'm not going to use KivyCamera available on Kivy, because I need to draw some shapes on top of the video frame. I found a example from (Is there a way to integrate the imshow() function of OpenCV into kivy or kv file in python).Thanks for this Answer. However this is still not working after installing the APK in android phone, application launches but white background screen is displayed in camera section. This is working fine in windows PC. I tried videocapture(-1), videocapture(0), videocapture(1) nothing worked.

If somebody knows of an answer please help me.

main.py

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


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:
            # this is where the video will show
            # the id allows easy access
            id: vid
            size_hint: 1, 0.6
            allow_stretch: True  # allow the video image to be scaled
            keep_ratio: True  # keep the aspect ratio so people don't look squashed
            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):
        # start the camera access code on a separate thread
        # if this was done on the main thread, GUI would stop
        # daemon=True means kill this thread when app stops
        threading.Thread(target=self.doit, daemon=True).start()

        sm = ScreenManager()
        self.main_screen = MainScreen()
        sm.add_widget(self.main_screen)
        return sm

    def doit(self):
        # this code is run in a separate thread
        self.do_vid = True  # flag to stop loop

        # make a window for use by cv2
        # flags allow resizing without regard to aspect ratio
        cv2.namedWindow('Hidden', cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)

        # resize the window to (0,0) to make it invisible
        cv2.resizeWindow('Hidden', 0, 0)
        # cv2.resizeWindow('Hidden', 200, 200)
        cam = cv2.VideoCapture(0)

        # start processing loop
        while (self.do_vid):
            ret, frame = cam.read()
            # ...
            # more code
            # ...

            # send this frame to the kivy Image Widget
            # Must use Clock.schedule_once to get this bit of code
            # to run back on the main thread (required for GUI operations)
            # the partial function just says to call the specified method with the provided argument (Clock adds a time argument)
            Clock.schedule_once(partial(self.display_frame, frame))

            cv2.imshow('Hidden', frame)
            cv2.waitKey(1)
        cam.release()
        cv2.destroyAllWindows()

    def stop_vid(self):
        # stop the video capture loop
        self.do_vid = False

    def display_frame(self, frame, dt):
        # display the current video frame in the kivy Image widget

        # create a Texture the correct size and format for the frame
        texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')

        # copy the frame data into the texture
        texture.blit_buffer(frame.tobytes(order=None), colorfmt='bgr', bufferfmt='ubyte')

        # flip the texture (otherwise the video is upside down
        texture.flip_vertical()
        texture.flip_horizontal()

        # actually put the texture in the kivy Image widget
        self.main_screen.ids.vid.texture = texture


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

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,pyjnius,plyer,requests,urllib3,chardet,idna,pip,Image,PIL
orientation = portrait

# Android specific
fullscreen = 0
android.permissions = INTERNET, ACCESS_FINE_LOCATION, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, CAMERA
android.arch = armeabi-v7a
[buildozer]
log_level = 2
warn_on_root = 1
Jananda
  • 11
  • 1
  • 5
  • Possibly related: [kivy camera application with opencv in android shows black screen](https://stackoverflow.com/q/61122285/295004) If already seen, please [edit](https://stackoverflow.com/posts/69157558/edit) your post with what didn't work and related error log messages. – Morrison Chang Sep 13 '21 at 05:32
  • [kivy-camera-application-with-opencv-in-android-shows-black-screen](https://stackoverflow.com/questions/61122285/kivy-camera-application-with-opencv-in-android-shows-black-screen) is not the solution I'm seeking, because it does not use cv2.videoCapture method. I just want to use cv2.VideoCaptute(0) method. Is it not supported in Android? – Jananda Sep 13 '21 at 08:30
  • Could you explain why do you need to use the cv2.VideoCaptute() method? – Norbert Tiborcz Sep 14 '21 at 18:30
  • I need to add some overlays (shapes) on top of the video stream, also I'm trying to do some edge detection using opencv on top of the video stream. Is there anything wrong with cv2.videoCapture method used in ANDROID? since it is perfectly working on Windows 10. I just need to maintain a single code base for both windows and android rather than writing platform specific implementations – Jananda Sep 15 '21 at 11:52
  • It's not necessary to use cv2.videoCapture() for it. On the solution 1 you can see the cv2.putText() method under the frame_to_screen() function. Just replace it with whatever you want and it should work. link: https://stackoverflow.com/questions/61122285/kivy-camera-application-with-opencv-in-android-shows-black-screen – Norbert Tiborcz Sep 15 '21 at 13:02
  • Thanks [Norbert Tiborcz](https://stackoverflow.com/users/15604109/norbert-tiborcz) for the reply. I tried both solution 1 and solution 2. Solution 1 works only with android. It is showing black screen when run on windows. I could not figure out why is that. Solution 2 works both on windows and android (Still camera rotation issue 90 degrees) and cannot add overlays on top of the video. That's why I'm trying cv2.VideoCapture method. Any idea for solution 1 black screen for windows? – Jananda Sep 15 '21 at 15:52
  • I found this solution [is-there-a-way-to-integrate-the-imshow-function-of-opencv-into-kivy-or-kv-file](https://stackoverflow.com/questions/61615277/is-there-a-way-to-integrate-the-imshow-function-of-opencv-into-kivy-or-kv-file). However this is still not working. It displays only a white screen in camera frame – Jananda Sep 15 '21 at 15:56

2 Answers2

0

If you want to use OpenCV with the android camera you have to update OpenCV in the kivy recipe to the version 4.5.2 and also specify NDK API level in the bulldozer.spec to 24 or higher. https://github.com/opencv/opencv/pull/19597

-2

try to use

VideoCapture(0,cv2.CAP_ANDROID) or VideoCapture(1,cv2.CAP_ANDROID)