Play video inside kivy canvas - python

I have put the video inside kivy canvas, first 3 sec showing image afterthat will be play video. But only show all time image only.
Any suggestion.
Thanks
import kivy
from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle ,Color
from kivy.core.video import Video as CoreVideo
from kivy.clock import Clock
class Mycanvas(Widget):
def __init__(self,**kw):
super(Mycanvas,self).__init__(**kw)
with self.canvas:
self.bg = Rectangle(source='Flower.jpg', pos=self.pos, size=self.size)
self.video = CoreVideo()
self.video.bind(on_frame=self.set_bg_texture)
self.video.filename = 'Garden.mp4'
Clock.schedule_once(self.start_vid, 3)
self.start_vid(3)
def start_vid(self, dt):
self.video.play()
def set_bg_texture(self, *args):
self.bg.texture = self.video.texture
class mainapp(MDApp):
def build(self):
return Mycanvas()
mainapp().run()

Related

Simultaneous placement of camera images and buttons in GUI applications using Kivy

I am currently trying to create an app using Kivy that will turn the video into grayscale when the button is pressed.
At first, I was able to display the camera image on the GUI, but I'm having trouble figuring out how to place buttons and other parts from here.
import sys
import numpy as np
import cv2
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.clock import Clock
from kivy.core.window import Window
import datetime
import random
WINDOW_WIDTH = 1500
WINDOW_HEIGHT = 1008
### Setting of the window
Window.size = (WINDOW_WIDTH, WINDOW_HEIGHT)
class MyApp(App, Widget):
title = "opencv on kivy"
def __init__(self, **kwargs):
super(MyApp, self).__init__(**kwargs)
Clock.schedule_interval(self.update, 1.0 / 30)
self.widget = Widget()
# self.cap = cv2.VideoCapture(0)
self.cap = cv2.VideoCapture(1)
# The method by the intarval
def update(self, dt):
ret, img = self.cap.read()
### The color sequence in openCV is BGR, so fix it to RGB.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
### The origin of Kivy's coordinates is the lower left, so flip it upside down.
img = cv2.flip(img, 0)
# if img is not None:
texture = Texture.create(size=(img.shape[1], img.shape[0]))
texture.blit_buffer(img.tostring())
with self.widget.canvas:
Rectangle(texture=texture ,pos=(0 + int(WINDOW_WIDTH/2) - int(img.shape[1]/2), WINDOW_HEIGHT - img.shape[0]), size=(img.shape[1], img.shape[0]))
return self.widget
def build(self):
return self.widget
# return MyApp()
if __name__ == '__main__':
MyApp().run()
Also, the application that displays the button works fine.
However, I have no idea how to combine these since build(self) can only return a button or a single widget for the camera image.
# import kivy module
import kivy
# this restrict the kivy version i.e
# below this kivy version you cannot
# use the app or software
kivy.require("1.9.1")
# base Class of your App inherits from the App class.
# app:always refers to the instance of your application
from kivy.app import App
# creates the button in kivy
# if not imported shows the error
from kivy.uix.button import Button
# class in which we are creating the button
class ButtonApp(App):
def build(self):
btn = Button(text ="Push Me !")
return btn
# creating the object root for ButtonApp() class
root = ButtonApp()
# run function runs the whole program
# i.e run() method which calls the
# target function passed to the constructor.
root.run()
thank you in advance.
You can use self.add_widget(..) to add other widgets inside Widget, Button, etc. but it doesn't have function to automatically arange layout.
But build() can use any widget - it doesn't have to Button or Widget.
If you use BoxLayout then you can use self.add_widget(...) to add widgets in rows or columns.
Other layout widgets can be useful to organize widgets in different way.
class MyApp(App, BoxLayout): # class MyApp(App, Widget)
def __init__(self, **kwargs):
# ... code ...
self.orientation = 'vertical' # BoxLayout
self.widget = Widget()
self.add_widget(self.widget)
self.button = Button(text='Gray', on_press=self.change_color)
self.add_widget(self.button)
Full working code.
I use BoxLayout with orientation = 'vertical' to organize in rows I put Widget in top row, and Button in bottom row.
Button runs function which switch value self.convert_to_grey - True/False - and update() uses this value to convert image to gray (and back to RGB but with gray color)
import sys
import numpy as np
import cv2
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.clock import Clock
from kivy.core.window import Window
import datetime
import random
WINDOW_WIDTH = 1500
WINDOW_HEIGHT = 1008
### Setting of the window
Window.size = (WINDOW_WIDTH, WINDOW_HEIGHT)
class MyApp(App, BoxLayout):
title = "opencv on kivy"
def __init__(self, **kwargs):
super(MyApp, self).__init__(**kwargs)
self.orientation = 'vertical' # BoxLayout
self.convert_to_grey = False #
self.cap = cv2.VideoCapture(0)
#self.cap = cv2.VideoCapture(1)
self.widget = Widget()
self.add_widget(self.widget)
self.button = Button(text='Gray', on_press=self.change_color)
self.add_widget(self.button)
Clock.schedule_interval(self.update, 1.0 / 30)
def change_color(self, *args):
print('args:', args)
self.convert_to_grey = not self.convert_to_grey
def update(self, dt):
ret, img = self.cap.read()
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.flip(img, 0)
if self.convert_to_grey:
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
texture = Texture.create(size=(img.shape[1], img.shape[0]))
texture.blit_buffer(img.tostring())
with self.widget.canvas:
Rectangle(texture=texture, pos=(0 + int(WINDOW_WIDTH/2) - int(img.shape[1]/2), WINDOW_HEIGHT - img.shape[0]), size=(img.shape[1], img.shape[0]))
return self.widget
def build(self):
return self
if __name__ == '__main__':
MyApp().run()
More layouts in Kivy doc:
Getting Started ยป Layouts
BTW: you can nested layouts - ie. inside BoxLayout you can use one row with GridLayout and other row with different layout or widget.

Problem when trying to make a circular button on kivy

from kivy.uix.button import Button
from kivy.uix.behaviors.button import ButtonBehavior
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
from kivy.uix.widget import Widget
from kivy.graphics import BorderImage
from kivy.graphics import Color, RoundedRectangle, Rectangle, Triangle
from kivy.core.window import Window
#from kivy.config import Config
from kivy.uix.checkbox import CheckBox
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.filechooser import FileChooserListView
from kivy.properties import ObjectProperty
class OpeningPage(FloatLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.but = RoButton(text = 'START', pos = (350,100), font_size=14, size=(100,60), size_hint=(None,None))
self.add_widget(self.but)
class RoButton(Button):
butt = ObjectProperty()
def __init__(self, **kwargs):
super(RoButton, self).__init__(**kwargs)
text = self.text
with self.canvas:
# Color(1., 0, 0)
self.butt = RoundedRectangle( size= self.size, pos = self.pos, radius =[400])
class UI(App):
def build(self):
self.screen_manager = ScreenManager()
self.opening_page = OpeningPage()
screen = Screen(name ='Opening_Page')
screen.add_widget(self.opening_page)
self.screen_manager.add_widget(screen)
return self.screen_manager
if __name__ == '__main__':
the_app = UI()
the_app.run()
Everytime I try to make a circular button using this code I get a box behind the circle. I tried doing self.canvas.before but still no luck if possible could answers be in python rather than .kv language thanks.
Attached image of problem]1
The box you see is the normal Button image. If you don't want that, probably don't use a Button, instead use class RoButton(ButtonBehavior, Widget):.

Updating multiple Labels with kivy

Hello i'm relatively new to python and kivy and I've been looking around but i cant quite find the answer, i'm trying to make a hub where I can display live data from my rasberry-pi. I made a clock widget using a Label, and it updates time, but when i try to add my CPU usage only one label shows up. I thought the widgets might be covering each other but I used size_hint and it wont help. When i run the code below, only the timex will show up and only if i delete the Clock.schedule_interval(display32.timex, (1)) will the *updatex * display.
Thanks alot for the help
from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
import psutil
from kivy.lang import Builder
import time
class Display(Label, FloatLayout):
def __init__(self):
super(Display, self).__init__()
def updatex(self, *args):
self.cpu2 = psutil.cpu_percent()
self.text=str(self.cpu2)
self.size_hint=(.5, .25)
self.pos=(500, 500)
self.texture_size=(0.1,0.1)
def timex(self, *args):
self.time2 = time.asctime()
self.text = str(self.time2)
self.size_hint = (.5, .25)
self.pos = (30, 500)
self.size_hint=(0.1,0.1)
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.updatex, (1))
Clock.schedule_interval(display32.timex, (1))
return display32
if __name__ == "__main__":
TimeApp().run()
Instead of passing both labels to the clock, you can define a widget, add both labels and start the clock on the widget.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.clock import Clock
import psutil
import time
class Display(Widget):
def draw(self, *args):
self.clear_widgets()
self.add_widget(Label(text=str(psutil.cpu_percent()), pos=(500, 500)))
self.add_widget(Label(text=str(time.asctime()), pos=(30, 500)))
class TimeApp(App):
def build(self):
display32 = Display()
Clock.schedule_interval(display32.draw, 1)
return display32
if __name__ == '__main__':
TimeApp().run()

Kivy stop Video and show photo

I'm working on a kivy framework (v1.10). I'm trying to create a simple photo booth software that runs a video loop and stops the video when someone clicks on the screen. After that the camera takes a picture and the program displays it on the monitor together with two buttons yes or no. they will allow you to repeat the photo. I am developing this application for Raspberry PI. My question is how do I stop the video and make something else.
ok, so if I want to add another movie between the first movie and the buttons, do I have to add a new screen or maybe change the video source in this funtion self.bind (on_touch_down = self.on_stop)? I would like to add a video with a countdown time and let him release the camera by taking pictures. then display this photo once with the buttons: repeat and continue.
from kivy.app import App
from kivy.logger import Logger
from kivy.uix.videoplayer import Video
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class Player(Video):
def __init__(self, **kwargs):
super(Player, self).__init__(**kwargs)
self.source = './START.mp4'
self.state='play'
self.options={'eos': 'loop'}
self.bind(on_touch_down = self.on_stop)
self.get_set_current_video_state = self.get_set_current_video_state()
def check(self):
Logger.info("film position:" + str(self.position))
def on_stop(self, *args):
print ('I have been clicked')
Player.state='stop'
#App.get_running_app().stop()
#self.get_set_current_video_state = ('pause')
return MyWindowApp().run()
class VideoPlayerApp(App):
def build(self):
return Player()
class MyWindowApp(App):
def __init__(self):
super(MyWindowApp, self).__init__()
self.btn = Button(text='Push Me!')
self.lbl = Label(text='Read Me!')
Instead of trying to use two Apps, just use two Screens. Here is a modification of your code using Screens:
from kivy.app import App
from kivy.logger import Logger
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.video import Video
from kivy.uix.label import Label
from kivy.uix.button import Button
class Player(Video):
def __init__(self, **kwargs):
super(Player, self).__init__(**kwargs)
self.source = './START.mp4'
self.state='play'
self.options={'eos': 'loop'}
self.bind(on_touch_down = self.on_stop)
def check(self):
Logger.info("film position:" + str(self.position))
def on_stop(self, *args):
print ('I have been clicked')
self.state='stop' # stop the video
sm.current = 'WindowApp' # switch to the other Screen
class MyWindowApp(Screen):
def __init__(self, **kwargs):
super(MyWindowApp, self).__init__(**kwargs)
self.btn = Button(text='Push Me!', pos_hint={'center_x': 0.5, 'center_y': 0.75}, size_hint=(0.2, 0.2))
self.lbl = Label(text='Read Me!', pos_hint={'center_x': 0.5, 'center_y': 0.25})
self.add_widget(self.btn)
self.add_widget(self.lbl)
sm = ScreenManager()
screen1 = Screen(name='video')
screen1.add_widget(Player())
sm.add_widget(screen1)
screen2 = MyWindowApp(name='WindowApp')
sm.add_widget(screen2)
class VideoPlayerApp(App):
def build(self):
return sm
VideoPlayerApp().run()
I corrected your import to from kivy.uix.video import Video

Removing a widget with Kivy

I'm trying to remove an Image widget after its animation is complete.
So far I have managed to animate the widget and then call the animation_complete method after the animation ends. Unfortunately, the widget is not removed.
What am I doing wrong?
class ShootButton(Widget):
def bullet_fly(self):
def animation_complete(animation, widget):
print "removing animation"
self.remove_widget(widget=bullet1)
with self.canvas:
bullet1 = Image(source='bullet.png', pos = (100,200))
animation1 = Animation(pos=(200, 300))
animation1.start(bullet1)
animation1.bind(on_complete=animation_complete)
You do not have to use the canvas to add an animation but add the widget directly using add_widget() and then remove it with remove_widget(). In your initial case bullet1 is not the children of ShootButton.
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.animation import Animation
Window.size = (360, 640)
class ShootButton(Widget):
def bullet_fly(self):
def animation_complete(animation, widget):
self.remove_widget(widget)
bullet1 = Image(source='bullet.png', pos = (100,200))
self.add_widget(bullet1)
animation1 = Animation(pos=(200, 300))
animation1.start(bullet1)
animation1.bind(on_complete=animation_complete)
class MyApp(App):
def build(self):
button = ShootButton()
button.bullet_fly()
return button
if __name__ == '__main__':
MyApp().run()

Categories