我正在使用 kivy 中的相机编写 GUI,但不确定为什么我的代码不起作用。我有一个相机源,以及两种从中捕获图片的方法:一种由gpiozero
when_pressed
回调触发,另一种由kivy.uix.button
on_press
回调触发。
kivy.uix.button
回调成功捕获图像,但gpiozero
回调说,未能保存图像,然后Exception: Shader didnt link, check info log.
使相机输入变黑(尽管稍后仍然可以使用成功选项捕获图像)。为什么一个回调有效,而另一个无效?
这是相关代码,以及相应的终端输出。我已经用# ALL CAPS COMMENTS
. (我的代码受到kivy docs camera example的启发,该示例也成功捕获)。
主文件
import kivy
#kivy.require('1.11.1')
# Uncomment these lines to see all the messages
#from kivy.logger import Logger
#import logging
#Logger.setLevel(logging.TRACE)
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.camera import Camera
from kivy.core.window import Window
from gpiozero import Button as gpiozeroButton # renamed to avoid conflict w/ kivy.uix.button
import time
Window.fullscreen = 'auto' # uses display's current resolution
capture_btn = gpiozeroButton(pin=13, pull_up=False) # set up GPIO
class RootWidget(FloatLayout):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
capture_btn.when_pressed = self.capture # initialize callback for GPIO button
def capture(self):
print('Capture step 1')
camera = self.ids['camera']
print('Capture step 2')
timestr = time.strftime("%Y%m%d_%H%M%S")
print('Capture step 3')
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
class LifterApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
LifterApp().run()
升降机.kv
# #:kivy 1.11.1
<RootWidget>:
Camera:
id: camera
resolution: (640, 480)
play: True
Button:
text: "capture"
pos_hint: {'x':0.0, 'y':0.0}
size_hint: (0.2, 0.2)
on_press: root.capture()
终端输出(带注释)
[INFO ] [Logger ] Record log in /home/pi/.kivy/logs/kivy_20-12-30_27.txt
[INFO ] [Kivy ] v1.11.1
[INFO ] [Kivy ] Installed at "/usr/local/lib/python3.7/dist-packages/kivy/__init__.py"
[INFO ] [Python ] v3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0]
[INFO ] [Python ] Interpreter at "/usr/bin/python3"
[INFO ] [Factory ] 184 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO ] [Text ] Provider: sdl2(['text_pango'] ignored)
[INFO ] [Camera ] Provider: picamera
[INFO ] [Window ] Provider: sdl2(['window_egl_rpi'] ignored)
[INFO ] [GL ] Using the "OpenGL" graphics system
[INFO ] [GL ] Backend used <sdl2>
[INFO ] [GL ] OpenGL version <b'3.1 Mesa 19.3.2'>
[INFO ] [GL ] OpenGL vendor <b'VMware, Inc.'>
[INFO ] [GL ] OpenGL renderer <b'llvmpipe (LLVM 9.0.1, 128 bits)'>
[INFO ] [GL ] OpenGL parsed version: 3, 1
[INFO ] [GL ] Shading version <b'1.40'>
[INFO ] [GL ] Texture max size <8192>
[INFO ] [GL ] Texture max units <32>
[INFO ] [Window ] auto add sdl2 input provider
[INFO ] [Window ] virtual keyboard not allowed, single mode, not docked
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [MTD ] Read event from </dev/input/event0>
[INFO ] [ProbeSysfs ] device match: /dev/input/event0
[INFO ] [HIDInput ] Read event from </dev/input/event0>
[INFO ] [Base ] Start application main loop
[INFO ] [MTD ] </dev/input/event0> range position X is 0 - 800
[INFO ] [MTD ] </dev/input/event0> range position Y is 0 - 480
[INFO ] [HIDMotionEvent] using <WaveShare WS170120>
[INFO ] [MTD ] </dev/input/event0> range touch major is 0 - 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS X position is 0 - 800
[INFO ] [MTD ] </dev/input/event0> range touch minor is 0 - 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS Y position is 0 - 480
[INFO ] [MTD ] </dev/input/event0> range pressure is 0 - 255
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range ABS pressure is 0 - 255
[INFO ] [MTD ] </dev/input/event0> axes invertion: X is 0, Y is 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range position X is 0 - 800
[INFO ] [MTD ] </dev/input/event0> rotation set to 0
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range position Y is 0 - 480
[INFO ] [HIDMotionEvent] <WaveShare WS170120> range pressure is 0 - 255
[INFO ] [GL ] NPOT texture support is available
Capture step 1 # TRIGGERED BY KIVY.UIX.BUTTON ON_PRESS CALLBACK
Capture step 2
Capture step 3
Captured
Capture step 1 # TRIGGERED BY GPIOZERO WHEN_PRESSED CALLBACK
Capture step 2
Capture step 3
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 244, in _call_when_changed
super(RPiGPIOPin, self)._call_when_changed()
File "/usr/lib/python3/dist-packages/gpiozero/pins/local.py", line 143, in _call_when_changed
self.state if state is None else state)
File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 293, in _call_when_changed
method(ticks, state)
File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 197, in _pin_changed
self._fire_events(ticks, bool(self._state_to_value(state)))
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 368, in _fire_events
self._fire_activated()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 397, in _fire_activated
super(HoldMixin, self)._fire_activated()
File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 344, in _fire_activated
self.when_activated()
File "main.py", line 35, in capture
camera.export_to_png("IMG_{}.png".format(timestr))
File "/usr/local/lib/python3.7/dist-packages/kivy/uix/widget.py", line 727, in export_to_png
self.export_as_image().save(filename, flipped=False)
File "/usr/local/lib/python3.7/dist-packages/kivy/uix/widget.py", line 744, in export_as_image
with_stencilbuffer=True)
File "kivy/graphics/fbo.pyx", line 152, in kivy.graphics.fbo.Fbo.__init__
File "kivy/graphics/instructions.pyx", line 777, in kivy.graphics.instructions.RenderContext.__init__
File "kivy/graphics/shader.pyx", line 184, in kivy.graphics.shader.Shader.__init__
File "kivy/graphics/shader.pyx", line 701, in kivy.graphics.shader.Shader.vs.__set__
File "kivy/graphics/shader.pyx", line 557, in kivy.graphics.shader.Shader.build_vertex
File "kivy/graphics/shader.pyx", line 587, in kivy.graphics.shader.Shader.link_program
Exception: Shader didnt link, check info log.
^C[INFO ] [Base ] Leaving application in progress...
Traceback (most recent call last):
File "main.py", line 46, in <module>
LifterApp().run()
File "/usr/local/lib/python3.7/dist-packages/kivy/app.py", line 855, in run
runTouchApp()
File "/usr/local/lib/python3.7/dist-packages/kivy/base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "/usr/local/lib/python3.7/dist-packages/kivy/core/window/window_sdl2.py", line 747, in mainloop
self._mainloop()
File "/usr/local/lib/python3.7/dist-packages/kivy/core/window/window_sdl2.py", line 479, in _mainloop
EventLoop.idle()
File "/usr/local/lib/python3.7/dist-packages/kivy/base.py", line 339, in idle
Clock.tick()
File "/usr/local/lib/python3.7/dist-packages/kivy/clock.py", line 591, in tick
self._process_events()
File "kivy/_clock.pyx", line 384, in kivy._clock.CyClockBase._process_events
File "kivy/_clock.pyx", line 414, in kivy._clock.CyClockBase._process_events
File "kivy/_clock.pyx", line 412, in kivy._clock.CyClockBase._process_events
File "kivy/_clock.pyx", line 167, in kivy._clock.ClockEvent.tick
File "/usr/local/lib/python3.7/dist-packages/kivy/core/camera/camera_picamera.py", line 71, in _update
self._camera.capture(output, self._format, use_video_port=True)
File "/usr/lib/python3/dist-packages/picamera/camera.py", line 1421, in capture
if not encoder.wait(self.CAPTURE_TIMEOUT):
File "/usr/lib/python3/dist-packages/picamera/encoders.py", line 393, in wait
result = self.event.wait(timeout)
File "/usr/lib/python3.7/threading.py", line 552, in wait
signaled = self._cond.wait(timeout)
File "/usr/lib/python3.7/threading.py", line 300, in wait
gotit = waiter.acquire(True, timeout)
KeyboardInterrupt