Kivy应用程序中的图像在填满内存后不显示(显示黑框),未释放

Posted

技术标签:

【中文标题】Kivy应用程序中的图像在填满内存后不显示(显示黑框),未释放【英文标题】:Images in Kivy app not displayed (show black box) after filling up memory, not released 【发布时间】:2018-10-10 01:05:11 【问题描述】:

我一直在使用 Kivy 示例 Python 代码尝试在官方 Raspberry Pi 触摸屏上制作幻灯片。当我遍历 jpg 照片目录时,图像最终拒绝显示,仅显示一个黑框。我没有收到错误消息。我认为这是内存泄漏,但我不确定如何测试它。以下代码(下载一张照片,复制 9 次并以每张照片延迟 3 秒的时间显示每个文件)在 #7 处停止显示图像。如果我使用更大的图像,它们会更早地停止出现。清除小部件不应该释放内存吗?

main.py

import kivy
kivy.require('1.0.6')
from kivy.clock import Clock
import urllib
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from functools import partial
from kivy.core.window import Window
import shutil    

def displayphoto(i, root, *largs):
    name=str(i)+".jpg"
    root.clear_widgets()
    img = Image(source=name, nocache=False)
    root.add_widget(img)
    label = Label(text=name)
    root.add_widget(label)

class NoscatterApp(App):
    def build(self):
        root = FloatLayout()
        #os.remove("*.jpg")
        urllib.urlretrieve("https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Shed_with_green_roof_at_Lyngen_fjord%2C_2012_June.jpg/1200px-Shed_with_green_roof_at_Lyngen_fjord%2C_2012_June.jpg", "main.jpg")
        for i in range(0, 10):
            name=str(i)+".jpg"
            shutil.copy("main.jpg", name)        
            Clock.schedule_once(partial(displayphoto, i, root), i*3)    
        return root

    def on_pause(self):
        return True

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

【问题讨论】:

您在 PC 上发现过同样的问题吗? PC 上没试过。我猜这是内存泄漏......很多小照片或几张大照片最终都会这样做。我正在简化代码并将更新 对我来说这是树莓派和类似卡由于硬件限制而导致的特定问题,请在普通PC上尝试下载,这是由硬件引起的。 看看上面的代码是否会在 PC 上泄漏内存会很有趣,如果你能测试一下,我将不胜感激,因为我无法轻松访问 PC 可以在树莓派中使用htop监控资源消耗情况。 【参考方案1】:

有点晚了,但请尝试使用AsyncImage 而不是Image

from kivy.uix.image import AsyncImage

img = Image(source=name, nocache=False)

如果这不能解决问题,请尝试设置nocache=True。 这显着减少了我遇到黑色图像的次数,但仍未完全修复。

最后我使用 PIL 调整和压缩原始图像的大小,这完全解决了我的问题。

from PIL import Image as PILImage  # Name conflict with kivy.uix.image

img = Image(nocache=False)
pil_image = PILImage.open(name)
pil_image.thumbnail((512, 512)) # Pick any size you want.

pil_image.save("temp/current_image.jpg", format='JPEG', optimize=True, quality=90)
# Lower quality = more compression

img.source = "temp/current_image.jpg"

磁盘上的原始图像保持不变,只有显示的图像被压缩。任何其他减小图像大小的技术也应该有效。

【讨论】:

以上是关于Kivy应用程序中的图像在填满内存后不显示(显示黑框),未释放的主要内容,如果未能解决你的问题,请参考以下文章

在 Kivy 布局上显示 OpenCV 图像结果和绘图

python-kivy 通过存储在变量中的数据显示图像

在 Kivy 中从内存中加载图像

.gif 图像作为源代码在 Windows kivy 程序中运行良好。通过 kivy Launcher 运行显示 gif 图像的背景

无法用kivy显示图像

创建一个 kivy 应用程序以在一个屏幕上接收用户的输入并在另一个屏幕上显示这些图像