有没有办法将OpenCV的imshow()函数集成到python中的kivy或kv文件中
Is there a way to integrate the imshow() function of OpenCV into kivy or kv file in python
我是新来的,希望能得到一点帮助,对此我会很高兴。
我在python、kivy和opencv中写了一个小程序。
问题是我想将我的网络摄像头与 opencv 集成,而不是通过 kivy 现有的摄像头功能。
我已经在这里 发现了类似的问题,但这并不能解决我的问题。
在我的 OpenCV 代码中,还运行了面部识别代码 (https://github.com/ageitgey/face_recognition/blob/master/examples/facerec_from_webcam_faster.py)。因此,发出命令 imshow()
很重要。如何将 Opencv 中 imshow()
的网络摄像头版本集成到 kivy 或 kv 文件中?
不幸的是,我不知道这样的事情是否可行。你们中的一个可以帮助我或有想法吗?非常感谢您的帮助。
Python 文件:
import cv2
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
pass
class Manager(ScreenManager):
pass
kv = Builder.load_file("file.kv")
class Main(App):
def build(self):
return kv
if __name__ == '__main__':
Main().run()
OpenCV - 代码:
import cv2
cam = cv2.VideoCapture(0)
while(True):
ret, frame = cam.read()
# ...
# more code
# ...
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
我的 Kivy 文件(最小):
MainScreen:
MainScreen:
<MainScreen>:
name: "Test"
FloatLayout:
Label:
text: "Webcam from OpenCV?"
pos_hint: {"x":0.0, "y":0.8}
size_hint: 1.0, 0.2
Button:
text: 'Click me!!'
pos_hint: {"x":0.0, "y":0.0}
size_hint: 1.0, 0.2
font_size: 50
这是一个 hack,可以满足您的需求:
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)
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()
# actually put the texture in the kivy Image widget
self.main_screen.ids.vid.texture = texture
if __name__ == '__main__':
Main().run()
这会隐藏 imshow()
window(通过使其大小为 0x0),然后在 Image
Widget
中显示框架。不确定 window 大小的 0x0 是否与您的其他代码混淆。
我使用了上面的代码并做了一些修改。当我 use/return 一个 kivy 文件而不是 ScreenManger 时,问题就出现了。在我的例子中没有视频输出。
代码中的problem/fail是什么?
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 Scan(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("kivy.kv")
class Main(App):
def build(self):
threading.Thread(target=self.doit, daemon=True).start()
self.new_screen = Scan() # ?
return kv
def doit(self):
self.do_vid = True
cv2.namedWindow('Hidden', cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)
cv2.resizeWindow('Hidden', 0, 0)
cam = cv2.VideoCapture(0)
while (self.do_vid):
ret, frame = cam.read()
# ...
Clock.schedule_once(partial(self.display_frame, frame))
cv2.imshow('Hidden', frame)
cv2.waitKey(1)
cam.release()
cv2.destroyAllWindows()
def display_frame(self, frame, dt):
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
texture.blit_buffer(frame.tobytes(order=None), colorfmt='bgr', bufferfmt='ubyte')
texture.flip_vertical()
# No output of the Video Stream
# Scan().ids.vid.texture = texture also doesn't work
self.new_screen.ids.vid.texture = texture
if __name__ == '__main__':
Main().run()
kivy.kv
WindowManager:
Scan:
<Scan>:
name: 'scan'
FloatLayout:
Image:
id: vid
allow_stretch: True
keep_ratio: True
pos_hint: {'x':0.0, 'y':0.2}
size_hint: 1.0, 0.8
Button:
id: button_start
text: 'Button'
pos_hint: {'x':0.0, 'y':0.0}
size_hint: 0.7, 0.2
background_color: 0.7, 0.9, 0.0, 1
font_size: 50
Image:
id: folder
source: 'pic/folder.png'
pos_hint: {'x':0.7, 'y':0.0}
size_hint: 0.3, 0.2
我是新来的,希望能得到一点帮助,对此我会很高兴。
我在python、kivy和opencv中写了一个小程序。
问题是我想将我的网络摄像头与 opencv 集成,而不是通过 kivy 现有的摄像头功能。
我已经在这里 imshow()
很重要。如何将 Opencv 中 imshow()
的网络摄像头版本集成到 kivy 或 kv 文件中?
不幸的是,我不知道这样的事情是否可行。你们中的一个可以帮助我或有想法吗?非常感谢您的帮助。
Python 文件:
import cv2
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
pass
class Manager(ScreenManager):
pass
kv = Builder.load_file("file.kv")
class Main(App):
def build(self):
return kv
if __name__ == '__main__':
Main().run()
OpenCV - 代码:
import cv2
cam = cv2.VideoCapture(0)
while(True):
ret, frame = cam.read()
# ...
# more code
# ...
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
我的 Kivy 文件(最小):
MainScreen:
MainScreen:
<MainScreen>:
name: "Test"
FloatLayout:
Label:
text: "Webcam from OpenCV?"
pos_hint: {"x":0.0, "y":0.8}
size_hint: 1.0, 0.2
Button:
text: 'Click me!!'
pos_hint: {"x":0.0, "y":0.0}
size_hint: 1.0, 0.2
font_size: 50
这是一个 hack,可以满足您的需求:
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)
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()
# actually put the texture in the kivy Image widget
self.main_screen.ids.vid.texture = texture
if __name__ == '__main__':
Main().run()
这会隐藏 imshow()
window(通过使其大小为 0x0),然后在 Image
Widget
中显示框架。不确定 window 大小的 0x0 是否与您的其他代码混淆。
我使用了上面的代码并做了一些修改。当我 use/return 一个 kivy 文件而不是 ScreenManger 时,问题就出现了。在我的例子中没有视频输出。 代码中的problem/fail是什么?
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 Scan(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("kivy.kv")
class Main(App):
def build(self):
threading.Thread(target=self.doit, daemon=True).start()
self.new_screen = Scan() # ?
return kv
def doit(self):
self.do_vid = True
cv2.namedWindow('Hidden', cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)
cv2.resizeWindow('Hidden', 0, 0)
cam = cv2.VideoCapture(0)
while (self.do_vid):
ret, frame = cam.read()
# ...
Clock.schedule_once(partial(self.display_frame, frame))
cv2.imshow('Hidden', frame)
cv2.waitKey(1)
cam.release()
cv2.destroyAllWindows()
def display_frame(self, frame, dt):
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
texture.blit_buffer(frame.tobytes(order=None), colorfmt='bgr', bufferfmt='ubyte')
texture.flip_vertical()
# No output of the Video Stream
# Scan().ids.vid.texture = texture also doesn't work
self.new_screen.ids.vid.texture = texture
if __name__ == '__main__':
Main().run()
kivy.kv
WindowManager:
Scan:
<Scan>:
name: 'scan'
FloatLayout:
Image:
id: vid
allow_stretch: True
keep_ratio: True
pos_hint: {'x':0.0, 'y':0.2}
size_hint: 1.0, 0.8
Button:
id: button_start
text: 'Button'
pos_hint: {'x':0.0, 'y':0.0}
size_hint: 0.7, 0.2
background_color: 0.7, 0.9, 0.0, 1
font_size: 50
Image:
id: folder
source: 'pic/folder.png'
pos_hint: {'x':0.7, 'y':0.0}
size_hint: 0.3, 0.2