首页 > 解决方案 > Kivy 图像未重新加载且应用程序停止响应

问题描述

我正在尝试使用 Kivy 使用 Python 构建应用程序。这就是我想要实现的目标:

  1. 使用来自视频或相机的输入来检测图像,使用检测器(为了简化)找到图像中的所有圆圈,并以某种方式突出显示它们,从而产生新的图像。这是由我称之为的类完成的detector。Detector 利用 OpenCV 进行图像处理。
  2. 检测器的输出图像被写入display.jpg
  3. Kivy 应用程序的图像字段sourcedisplay.jpg
  4. 这不起作用)我使用重新加载图像源,self.image.reload()以便我的应用程序为用户刷新输出

这是我的代码

class GUI(App):

    def build(self):
        self.capture = cv2.VideoCapture(VIDEO_SOURCE)
        self.detector = detector(self.capture)
        layout = GridLayout(cols=2)
        self.InfoStream = Label(text = 'Info', size_hint=(20,80))
        StartButton = Button(text = 'Start', size_hint=(80,20))
        StartButton.bind(on_press=lambda x:self.start_program())     
        self.image = Image(source = 'display.jpg')
        layout.add_widget(self.image)
        layout.add_widget(self.InfoStream)
        layout.add_widget(StartButton)
        layout.add_widget(Label(text = 'Test'), size_hint=(20,20))
        return layout

    def start_program(self):
        while True:
            self.detector.detect_frame()
            self.update_image() # After detecting each frame, I run this

    def update_image(self, *args):
        if self.detector.output_image is not None:
            cv2.imwrite('display.jpg', self.detector.output_image)
            self.image.reload() # I use reload() to refresh the image on screen

    def exit(self):
        self.stop()

    def on_stop(self):
        self.capture.release()

if __name__ == '__main__':            
    GUI().run()

发生的情况是我可以通过按我的StartButton. 我在控制台上看到输出,证明它循环运行来自我的视频流的帧,并且我还看到源图像display.jpg正在实时更新。

但是,在我启动后,应用程序窗口似乎只是冻结了。它“无响应”并变灰,从不显示任何刷新的图像。

根据其他来源的一些现有代码,我还尝试使用计划任务刷新图像Clock.schedule_interval(self.update_image, dt=1),但结果是相同的。

我刷新图像的方式正确吗?有更好的方法吗?

标签: python-3.xkivyopencv3.0

解决方案


主线程上的while True循环将导致您App无响应。您可以使用Clock.schedule_interval以下方法消除该循环:

class GUI(App):

    def build(self):
        self.capture = cv2.VideoCapture(VIDEO_SOURCE)
        self.detector = detector(self.capture)
        layout = GridLayout(cols=2)
        self.InfoStream = Label(text = 'Info', size_hint=(20,80))
        StartButton = Button(text = 'Start', size_hint=(80,20))
        StartButton.bind(on_press=lambda x:self.start_program())     
        self.image = Image(source = 'display.jpg')
        layout.add_widget(self.image)
        layout.add_widget(self.InfoStream)
        layout.add_widget(StartButton)
        layout.add_widget(Label(text = 'Test'), size_hint=(20,20))
        return layout

    def start_program(self):
        Clock.schedule_interval(self.update_image, 0.05)

    def update_image(self, *args):
        self.detector.detect_frame()
        if self.detector.output_image is not None:
            cv2.imwrite('display.jpg', self.detector.output_image)
            self.image.reload() # I use reload() to refresh the image on screen

    def exit(self):
        self.stop()

    def on_stop(self):
        self.capture.release()

if __name__ == '__main__':            
    GUI().run()

这是另一个问题,海报使用 aTexture而不是将捕获的图像写入文件。可能是更有效的方法。


推荐阅读