i try to make app for read barcode using android machine and i have problem i cant compare between cv and kivy please if someone can help me .
code that read barcode from android camera using kivy
from kivy.app import App
from kivy.uix.camera import Camera
from pyzbar.pyzbar import decode
import numpy as np
import cv2
from kivy.properties import ListProperty
class MainApp(App):
def build(self):
self.capture = cv2.VideoCapture(0)
cam = Camera(play=True, resolution=(640, 480))
#cap=cv2.VideoCapture(0)
success, frame=self.read()
for code in decode(frame):
print(code.type)
print(code.data.decode('utf-8'))
cv2.imshow("Results", frame);
cv2.waitKey(1);
return cam
if __name__== "__main__":
MainApp().run()
what do you mean by " i cant compare between cv and kivy" ? I have working machine learning app in kivy using cam. So what do you exactly need ? You need o display img in cv window, or you want to display camera frames in kivy ? You can update the kivy window every x second:
def __init__(self, **kw):
super().__init__()
self.capture = None
def on_pre_enter(self, *args):
super().__init__()
self.capture = cv.VideoCapture(0)
Clock.schedule_interval(self.update, 1.0 / 30) # update 30 fps
def on_leave(self, *args):
self.capture.release()
And then you can display frame as kivy image texture like this:
def update(self, dt):
ret, frame = self.capture.read()
if ret:
buf1 = cv.flip(frame, 0)
buf = buf1.tobytes()
image_texture = Texture.create(
size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
image_texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
self.ids['image'].texture = image_texture
And Image you can define in kivy:
MDBoxLayout:
size_hint: .65,1
orientation: 'vertical'
Image: #webcam
id: image
Related
The title says it all, the loading of camera video takes a lot of time and stays in "Not Responding" at that time.
It takes almost 1 to 2 minutes to load the camera.
This is my code.
class Attendance(Screen):
def on_enter(self, *args):
self.image = Image()
self.capture = cv2.VideoCapture(0)
Clock.schedule_interval(self.load_video, 1.0/30.0)
self.add_widget(self.image)
return super().on_enter(*args)
def load_video(self, *args):
frame = self.capture.read()
self.iamge_frame = frame
buffer = cv2.flip(frame, 0).tobytes()
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
texture.blit_buffer(buffer, colorfmt='bgr',bufferfmt = 'ubyte')
self.image.texture = texture
I fixed this by changing self.capture to the following:
self.capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
I am running a GUI with kivy, and simultaneously processing some realtime 3D scanner data. I'm using a multiprocessing instance to process the scan data, while the kivy GUI runs. The scanner data is read in by OpenCV, frame by frame.
My issue is that I can share the scanner data with the kivy instance, in order to display it within the GUI. I have tried making the the array "frame" global, but that doesn't seem to be doing the trick.
I have read about the multiprocessing manager, but im unclear on how to use it to manage a numpy array.
frame = np.zeros((480,640))
class CamApp(App):
def update_slider(self, instance, value):
#print(value)
self.slider_value = value*3
def build(self):
self.img1=Image()
layout = GridLayout(cols = 1)
layout.add_widget(self.img1)
Clock.schedule_interval(self.update, 1.0/33.0)
return layout
def update(self, dt):
global frame
#format as texture
buf1 = cv2.flip(frame, 0)
buf = buf1.tobytes()
texture1 = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
texture1.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
# display image from the texture
self.img1.texture = texture1
def cam(message):
print(message)
dc = DepthCamera()
global frame
while True:
ret, depth_frame, colour_frame = dc.get_frame()
frame = cv2.applyColorMap(cv2.convertScaleAbs(depth_frame, alpha=0.2), cv2.COLORMAP_BONE)
#cv2.imshow("Depth frame", frame)
#cv2.imshow("Color frame", colour_frame)
#key = cv2.waitKey(1)
if __name__ == '__main__':
p = Process(target=cam, args=('beginning capture',))
p.start()
CamApp().run()
cv2.destroyAllWindows()
I am new to python and more to kivy, with this it turns out that they helped me to create this code (below), it turns out that after my code seems to work well, many told me that for good practices I did not write I will create graphic environments with python that existed for that .kv, with this clearer it turns out that I have not been able to achieve how I do it, I hope you could help me to transcribe it I thank you from the bottom of my heart thank you, below the code, I just want to transcribe what I have thanks.
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import cv2
class CvCamera(App):
def build(self): # Construcción de interfaz de usuario, etc
self._cap = cv2.VideoCapture(0)
layout2 = BoxLayout(orientation='horizontal', size_hint=(1.0, 0.1))
self.img1 = Image(size_hint=(1.0, 0.7))
layout = BoxLayout(orientation='vertical')
layout.add_widget(self.img1)
layout.add_widget(layout2)
while not self._cap.isOpened():
pass
Clock.schedule_interval(self.update, 1.0 / 30.0)
return layout
def update(self, dt):
ret, img = self._cap.read()
img = cv2.flip(img, 0)
texture1 = Texture.create(size=(img.shape[1], img.shape[0]), colorfmt='bgr')
texture1.blit_buffer(img.tostring(), colorfmt='bgr', bufferfmt='ubyte')
self.img1.texture = texture1
if __name__ == '__main__':
CvCamera().run()
Here is the equivalent using kv language:
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.lang import Builder
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import cv2
kv = '''
BoxLayout:
orientation: 'vertical'
Image:
id: img1
size_hint: 1.0, 0.7
BoxLayout:
orientation: 'horizontal'
size_hint: 1.0, 0.1
'''
class CvCamera(App):
def build(self): # Construcción de interfaz de usuario, etc
self._cap = cv2.VideoCapture(0)
layout = Builder.load_string(kv)
while not self._cap.isOpened():
pass
Clock.schedule_interval(self.update, 1.0 / 30.0)
return layout
def update(self, dt):
ret, img = self._cap.read()
img = cv2.flip(img, 0)
texture1 = Texture.create(size=(img.shape[1], img.shape[0]), colorfmt='bgr')
texture1.blit_buffer(img.tostring(), colorfmt='bgr', bufferfmt='ubyte')
self.root.ids.img1.texture = texture1
if __name__ == '__main__':
CvCamera().run()
Note that, in general, the arguments in () of the Widgets become entries below and indented from the Widget name.
I am making a gui with a button to make webcam on and off. and it is working but when i open it again after closing it then its shows only black screen.
how to resolve this issue.
Here is my code. my whole code is huge so i posted on the webcam part here.
i updated my code .......................
import tkinter as tk
from tkinter import *
import cv2
import numpy as np
from PIL import Image, ImageTk, ImageGrab
cap = cv2.VideoCapture(0)
webcam = None
WEBCAM_SIZE = (280, 200)
def read_frame(imgbox):
if cap.isOpened():
ret, frame = cap.read()
if ret:
frame = cv2.flip(frame, 1)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = cv2.resize(frame, WEBCAM_SIZE)
image = Image.fromarray(frame)
imgbox.image.paste(image)
webcam.after(20, read_frame, imgbox)
def stop_webcam(event):
global webcam
if webcam:
webcam.destroy()
webcam = None
cap.release()
def start_webcam():
global webcam
cap.open()
if webcam is None:
cap.isOpened()
webcam = tk.Toplevel()
#webcam = tk.lift()
webcam.attributes("-topmost", True) #it keep the window on top of others
webcam.geometry('{}x{}+5+520'.format(WEBCAM_SIZE[0], WEBCAM_SIZE[1]))
webcam.overrideredirect(1)
imgbox = tk.Label(webcam)
imgbox.pack()
imgbox.image = ImageTk.PhotoImage(image=Image.new('RGB',WEBCAM_SIZE,(0,0,0)))
imgbox.config(image=imgbox.image)
#webcam.bind('', stop_webcam)
read_frame(imgbox)
cap_btn = ttk.Button(frame, image=web, width=20, command=change_w)
cap_btn.grid(row=0, column=2)
cap_btn.image = web
def change_w():
if cap_btn.image == web:
start_webcam()
cap_btn.config(image=web2)
cap_btn.image = web2
else:
stop_webcam(None)
cap_btn.config(image=web)
cap_btn.image = web
web = PhotoImage(file='webcam.png')
web2 = PhotoImage(file='bl.png')
root.mainloop()
I'm trying to display an rtsp stream via kivy video player, this runs fine but in my video I get a 2 or 3 second delay in the stream which I would ideally like to eliminate to 0.5 to 1 seconds.
Here's what I have:
from kivy.app import App
from kivy.uix.video import Video
class TestApp(App):
def build(self):
video = Video(source='rtsp://my-stream-address', state='play')
video.size = (720, 320)
video.opacity = 0
video.state = 'play'
video.bind(texture=self._play_started)
return video
def _play_started(self, instance, value):
instance.opacity = 1
if __name__ == '__main__':
TestApp().run()
EDIT
I have a working solution to the video streaming BUT I don't know how to get this into my kivy gui.
Here's my streaming solution:
from threading import Thread
import cv2, time
class ThreadedCamera(object):
def __init__(self, src=0):
self.capture = cv2.VideoCapture(src)
self.capture.set(cv2.CAP_PROP_BUFFERSIZE, 2)
self.FPS = 1/30
self.FPS_MS = int(self.FPS * 1000)
# Start frame retrieval thread
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
def update(self):
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
time.sleep(self.FPS)
def show_frame(self):
cv2.imshow('frame', self.frame)
cv2.waitKey(self.FPS_MS)
if __name__ == '__main__':
src = 'rtsp://my-stream-address'
threaded_camera = ThreadedCamera(src)
while True:
try:
threaded_camera.show_frame()
except AttributeError:
pass
EDIT 2
I have also found this implementation of a kivy video widget not using the built in Video widget. I'm still unsure how to combine my working solution with a Kivy widget but perhaps this can help someone help me:
class KivyCamera(Image):
source = ObjectProperty()
fps = NumericProperty(30)
def __init__(self, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self._capture = None
if self.source is not None:
self._capture = cv2.VideoCapture(self.source)
Clock.schedule_interval(self.update, 1.0 / self.fps)
def on_source(self, *args):
if self._capture is not None:
self._capture.release()
self._capture = cv2.VideoCapture(self.source)
#property
def capture(self):
return self._capture
def update(self, dt):
ret, frame = self.capture.read()
if ret:
buf1 = cv2.flip(frame, 0)
buf = buf1.tostring()
image_texture = Texture.create(
size=(frame.shape[1], frame.shape[0]), colorfmt="bgr"
)
image_texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.texture = image_texture
My initial question was for Kivy Video player widget. But now the solution I am finding is using threading with OpenCV, so I have changed the tags on this question and will accept any Kivy implementation of this solution.