Problems with Kivy Camera

1,672 views
Skip to first unread message

Cedric Groyer

unread,
Dec 13, 2021, 10:43:29 AM12/13/21
to Kivy users support
Hi there.

I am trying to simply display a webcam's video stream with Kivy widget Camera.

Running Windows 7 (yeah I know) on a iMac hardware with bootcamp (yeah I know).
When I run some example test app, I get a video that's probably encoded incorrectly and is like a mosaic of gray pics, and the console fills up with     
ret, frame = self._device.read()
cv2.error: Unknown C++ exception from OpenCV code

Here's the test code I use:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
id: camera
#resolution: (640, 480)
index: 0
play: False
ToggleButton:
text: 'Play'
on_press: camera.play = not camera.play
size_hint_y: None
height: '48dp'
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
''')


class CameraClick(BoxLayout):
def capture(self):
# '''
# Function to capture the images and give them the names
# according to their captured time and date.
# '''
# camera = self.ids['camera']
# timestr = time.strftime("%Y%m%d_%H%M%S")
# camera.export_to_png("IMG_{}.png".format(timestr))
# print("Captured")
pass

class TestCamera(App):

def build(self):
return CameraClick()

TestCamera().run()



On the contrary, when I run a test script with opencv, I am able to correctly display the video from the iMac's built in camera, as well as that of a connected external usb webcam with the following code:

import cv2

cap = cv2.VideoCapture(1+cv2.CAP_DSHOW)

# Check if the webcam is opened correctly
if not cap.isOpened():
raise IOError("Cannot open webcam")

while True:
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
cv2.imshow('Input', frame)

c = cv2.waitKey(1)
if c == 27:
break

cap.release()
cv2.destroyAllWindows()

Anyone can help me with getting the Kivy Camera working?
Thank you!

C

PS: this is my first post, and I don't know how to format the code correctly, sorry...

Robert

unread,
Dec 13, 2021, 12:14:25 PM12/13/21
to Kivy users support
Try explicitly setting resolution.

Cedric Groyer

unread,
Dec 13, 2021, 12:31:01 PM12/13/21
to Kivy users support
Hi Robert.
Thanks for your answer.
I commented the resolution line in the kv string because otherwise the app crashes before I can see the UI. I saw this happens to others on some forum, and indeed, removing the resolution line makes it start, and i can press the Start button (giving a wrongly formatted video).
The error output is pretty long when it crashes.
Starting with about 6 warning 0:
[ WARN:0] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (696) CvCapture_MSMF::initStream Failed to set mediaType (stream 0, (640x480 @ 29.97) MFVideoFormat_RGB24(unsupported media type)
and 2 warning 1:
[ WARN:1] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (376) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): OnReadSample() is called with error status: -1072875772
[ WARN:1] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (388) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): async ReadSample() call is failed with error status: -1072875772

Than it starts like that : 
Traceback (most recent call last):
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\lang\builder.py", line 705, in _apply_rule
     setattr(widget_set, key, value)
   File "kivy\weakproxy.pyx", line 35, in kivy.weakproxy.WeakProxy.__setattr__
   File "kivy\properties.pyx", line 498, in kivy.properties.Property.__set__
   File "kivy\properties.pyx", line 840, in kivy.properties.ListProperty.set
   File "kivy\properties.pyx", line 545, in kivy.properties.Property.set
   File "kivy\properties.pyx", line 600, in kivy.properties.Property.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1154, in kivy._event.EventObservers._dispatch
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\uix\camera.py", line 104, in _on_index
     resolution=self.resolution, stopped=True)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\core\camera\camera_opencv.py", line 70, in __init__
     super(CameraOpenCV, self).__init__(**kwargs)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\core\camera\__init__.py", line 70, in __init__
     self.init_camera()
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\core\camera\camera_opencv.py", line 120, in init_camera
     self._resolution = (int(frame.shape[1]), int(frame.shape[0]))
 AttributeError: 'NoneType' object has no attribute 'shape'
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:/Users/Cedric/Documents/GIT/ik_python/Products/Various/TestKivyCamera.py", line 61, in <module>
     TestCamera().run()
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\app.py", line 949, in run
     self._run_prepare()
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\app.py", line 919, in _run_prepare
     root = self.build()
   File "C:/Users/Cedric/Documents/GIT/ik_python/Products/Various/TestKivyCamera.py", line 58, in build
     return CameraClick()
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\uix\boxlayout.py", line 145, in __init__
     super(BoxLayout, self).__init__(**kwargs)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\uix\layout.py", line 76, in __init__
     super(Layout, self).__init__(**kwargs)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\uix\widget.py", line 361, in __init__
     rule_children=rule_children)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\uix\widget.py", line 465, in apply_class_lang_rules
     rule_children=rule_children)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\lang\builder.py", line 543, in apply
     rule_children=rule_children)
   File "C:\Users\Cedric\Documents\GIT\venv\lib\site-packages\kivy\lang\builder.py", line 712, in _apply_rule
     e), cause=tb)
 kivy.lang.builder.BuilderException: Parser: File "<inline>", line 6:
 ...
       4:    Camera:
       5:        id: camera
 >>    6:        resolution: (640, 480)
       7:        index: 0
       8:        play: False
 ...
 AttributeError: 'NoneType' object has no attribute 'shape'


...

If you think it's worth it I can include the full output.
Thank you.

Robert

unread,
Dec 13, 2021, 2:52:35 PM12/13/21
to Kivy users support
Maybe somebody else knows?

Elliot Garbus

unread,
Dec 13, 2021, 5:43:55 PM12/13/21
to kivy-...@googlegroups.com

 

The example below runs on my Windows Laptop.  To preserve indentation when pasting into the google groups kivy users site, right click and select “paste as plain text”.

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
import time


kv =
'''

CameraClick:
    orientation: 'vertical'
    Camera:
        id: camera
        play: True

    Button:
        text: 'Capture'
        size_hint_y: None
        height: '48dp'
        on_release: root.capture()
'''


class CameraClick(BoxLayout):
   
def capture(self):
        time_str = time.strftime(
"%Y%m%d_%H%M%S")
       
self.ids.camera.export_to_png(f'IMG_{time_str}.png')
       
print("Captured")


class TestCamera(App):
   
def build(self):
       
return Builder.load_string(kv)


TestCamera().run()

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/da493590-0bf1-4521-8a22-fb316757d6aen%40googlegroups.com.

 

Cedric Groyer

unread,
Dec 14, 2021, 4:40:34 AM12/14/21
to Kivy users support
Hi Elliott, thanks for your answer/code/time.

Unfortunately your code behaves like mine, and continuously throws:
cv2.error: Unknown C++ exception from OpenCV code
[ERROR  ] [OpenCV      ] Couldn't get image from Camera

Here's a frame captured from the internal webcam to illustrate the problem: 
IMG_20211214_101353.png
With OpenCV, the image is a normal color image.
And while with OpenCV I manage to get the image from the USB webcam, I only get noise with Kivy Camera.

I suppose that using Windows 7 on a Mac Hardware may not help.
I actually need to try that on a Mac Pro (with OSX El Capitan) as well. But the system has no built-in camera and my USB webcam is not recognized by the system so of course the app won't work.... The webcam may be too old and somehow windows only...
Moreover, the installation of OpenCV just fails on that computer, so... the preliminaries are not really promising... 
It's a tough world... :)

Thanks for your help.

If anyone has ever encountered these problems, I'd like to know!

Thanks again.

C

Elliot Garbus

unread,
Dec 14, 2021, 11:01:44 AM12/14/21
to kivy-...@googlegroups.com
I suspect your iMac camera is higher resolution. Try 1280, 720. Look for the specs for your model. 

If that doesn’t work you can grab the frame from Opencv, and apply the texture to an image. 

Sent from my iPhone

On Dec 14, 2021, at 2:40 AM, Cedric Groyer <cgr...@gmail.com> wrote:

Hi Elliott, thanks for your answer/code/time.

Robert

unread,
Dec 14, 2021, 12:22:01 PM12/14/21
to Kivy users support
The really odd thing about this (aside from the image) is the first line of the message could have come from Kivy, but the second line doesn't seem to.

And the Kivy interface to OpenCV works as Elliot suggests

One thing Mac cameras seem to default to 16:9 , Kivy (though in some ways broken) defaults to 4:3, try an explicit 16:9 resolution.

Another is that Kivy camera doesn't use Direct Show (grrrr).  Try adding cv2.CAP_DSHOW to the Kivy camera index.

Cedric Groyer

unread,
Dec 15, 2021, 3:56:33 AM12/15/21
to Kivy users support
Hi Elliot.
If I put the resolution line, even with the spec'ed camera resolution, the app stops.
The OpenCV to image texture way is interesting and I'll investigate that, thanks!
(Although I fail installing opencv-python on the Mac where the app is suppose to run in the end... but this is another story)

Thanks a lot.

Cedric Groyer

unread,
Dec 15, 2021, 4:20:49 AM12/15/21
to Kivy users support
Hi Robert!
Thanks for the link to camera_opencv.py, I'll check it. (hopefully I'll be luckier installing opencv-python on my MacPro first, since it is where the app should end up running)

My built-in camera seems to actually be 640x480. I also tried a few 16:9 ratios as you suggested. Nothing worked.

About Direct Show, I have tried few days ago to use the same cv2.CAP_DSHOW offset in the camera index, but it didn't help. :(

Anyway, in the next days I will try the camera_opencv.py on my windows machine (as opencv-python installs there) and let you know. 
In case of success I'll then have to fix the installation of opencv-python on the Mac Pro to make it all work there.

Many thanks.
C

2019BTEEL00076 Umer Mansoor Ali Bijapure

unread,
Dec 15, 2021, 10:46:28 AM12/15/21
to kivy-...@googlegroups.com
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
import socket
import android
#from pyobjus import autoclass # Specific to iOS

# Client using iPhone and kivy

import time
from kivy.uix.textinput import TextInput


# This client code was built using python 2 when building the kivy ios project
class Client(App):
    counter = 0
    def build(self):
   
        g = GridLayout(cols=1)
        b = Button(on_release=self.go)
        self.l = Label()
        self.host = TextInput(text='192.168.43.179')
        g.add_widget(b)
        g.add_widget(self.host)
        g.add_widget(self.l)
        return g

    def go(self, *args):
        HOST = '192.168.43.179' # The server's hostname or IP address
        HOST = self.host.text
        PORT = 65436 # The port used by the server
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.connect((HOST, PORT))

        while True:
            time.sleep(.25)
            self.send_msg()

    def send_msg(self, *args):
        self.counter += 1
        #gyro_data = self.br.gy_x, self.br.gy_y, self.br.gy_z # iOS specific
        gyro_data = "hello"
        self.s.sendall(bytes(gyro_data ,encoding='utf8'))

    def on_stop(self):
        self.s.close()

Client().run()
Instead of hello values i want to send accelerometer data??

Robert

unread,
Dec 15, 2021, 12:23:38 PM12/15/21
to Kivy users support
1) Send it in the format the server expects. Lots of possible answers
For example. if the server expects a string delimited by ':' use  "{}:{}:{}".format( self.br.gy_x, self.br.gy_y, self.br.gy_z)

2) Using sleep() will stall the Kivy event loop, and freeze the app. The method go() must be in a Thread,
Reply all
Reply to author
Forward
0 new messages