You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy应用内存占满后图片无法显示(仅显示黑框)且内存未释放

Troubleshooting Kivy Slideshow Black Screens & Memory Leaks on Raspberry Pi Touchscreen

Hey there! Let's dig into this slideshow issue you're facing on your Raspberry Pi. The black frames after the 7th image (and worse behavior with larger images) absolutely points to memory management problems—Kivy's default image handling can be greedy on resource-limited devices like the Pi, especially if you're not cleaning up old resources.

First: Verify the Memory Leak

Before jumping to fixes, let's confirm that memory is indeed the culprit. Here are two simple ways to track it:

1. Use psutil for in-code monitoring

Install the psutil library to track your app's memory usage in real-time:

pip install psutil

Add this snippet to your test code to log memory every second:

import psutil
import os
from kivy.clock import Clock

def monitor_memory(self, dt):
    process = psutil.Process(os.getpid())
    print(f"Memory Used: {process.memory_info().rss / 1024 / 1024:.2f} MB")

# In your app's build method, schedule the monitor:
Clock.schedule_interval(self.monitor_memory, 1)

If you see memory climbing steadily with each image and never dropping, you've got a leak on your hands.

2. System-level monitoring

Open a terminal and run htop (install it with sudo apt install htop if needed). Watch the Python process's memory column as your slideshow runs—if it keeps growing until it hits a wall, that's your smoking gun.

The Root Cause: Kivy's Image Cache & Unreleased Textures

By default, Kivy caches every image texture you load to speed up future access. On the Pi, this cache can quickly eat up available RAM, especially with large images. Additionally, if you're creating new Image widgets each time or not explicitly releasing old textures, those resources stay in memory forever.

Fixes to Get Your Slideshow Running Smoothly

Let's implement these changes step by step:

1. Explicitly Release Old Textures

Before loading a new image, make sure to free up the memory used by the previous one. Add this code right before loading your next image:

if self.image_widget.texture:
    self.image_widget.texture.release()  # Free the GPU/CPU memory
    self.image_widget.texture = None     # Clear the reference

This tells Kivy you're done with that texture, so it can garbage collect it.

2. Scale Images to Screen Size

There's no need to load a full-resolution image if your Pi's touchscreen is smaller (e.g., 800x480). Resize images before loading them to cut down memory usage drastically:

from kivy.core.image import CoreImage

def load_scaled_image(self, img_path):
    # Load the image with CoreImage
    ci = CoreImage(img_path)
    # Get screen dimensions
    screen_w, screen_h = self.root.width, self.root.height
    # Calculate scaling factor to fit the screen (maintain aspect ratio)
    scale_w = screen_w / ci.texture.width
    scale_h = screen_h / ci.texture.height
    scale = min(scale_w, scale_h)
    # Scale the texture
    scaled_texture = ci.texture.get_region(0, 0, ci.texture.width, ci.texture.height)
    scaled_texture.scale(scale, scale)
    return scaled_texture

Use this function to load your images instead of letting Kivy handle it directly.

3. Disable Unnecessary Image Caching

If you don't need Kivy's cache at all (since you're only showing each image once), you can disable it globally:

from kivy.config import Config
Config.set('graphics', 'cache_size', 0)

Put this at the very top of your script, before importing any other Kivy modules.

4. Optimized Test Code Example

Here's a revised version of your test script incorporating all these fixes:

from kivy.app import App
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.core.image import CoreImage
import psutil
import os
from kivy.config import Config

# Disable image cache
Config.set('graphics', 'cache_size', 0)

class SlideshowTestApp(App):
    def build(self):
        self.image_widget = Image()
        self.image_paths = [f"test_img_{i}.jpg" for i in range(10)]
        self.current_idx = 0
        
        # Start memory monitoring
        Clock.schedule_interval(self.monitor_memory, 1)
        # Load first image immediately
        Clock.schedule_once(self.load_next_image, 0)
        return self.image_widget

    def load_next_image(self, dt):
        if self.current_idx >= len(self.image_paths):
            self.current_idx = 0
        
        # Release previous texture
        if self.image_widget.texture:
            self.image_widget.texture.release()
            self.image_widget.texture = None
        
        # Load and scale new image
        img_path = self.image_paths[self.current_idx]
        scaled_texture = self.load_scaled_image(img_path)
        self.image_widget.texture = scaled_texture
        
        self.current_idx += 1
        # Schedule next image in 3 seconds
        Clock.schedule_once(self.load_next_image, 3)

    def load_scaled_image(self, img_path):
        ci = CoreImage(img_path)
        screen_w, screen_h = self.root.width, self.root.height
        scale_w = screen_w / ci.texture.width
        scale_h = screen_h / ci.texture.height
        scale = min(scale_w, scale_h)
        texture = ci.texture.get_region(0, 0, ci.texture.width, ci.texture.height)
        texture.scale(scale, scale)
        return texture

    def monitor_memory(self, dt):
        process = psutil.Process(os.getpid())
        print(f"Current Memory: {process.memory_info().rss / 1024 / 1024:.2f} MB")

if __name__ == "__main__":
    SlideshowTestApp().run()

Extra Pi-Specific Optimizations

  • Use the SDL2 Backend: Some Pi users report better memory management with the SDL2 OpenGL backend. Add this to the top of your script:
    os.environ['KIVY_GL_BACKEND'] = 'sdl2'
    
  • Close Unnecessary Background Apps: Free up RAM by closing any unused processes on your Pi (like browsers, file managers, etc.).
  • Overclock (Carefully): If you're comfortable, a small CPU/GPU overclock can help with image processing, but only do this if you have proper cooling.

With these changes, your slideshow should no longer hit memory limits, and those black frames should disappear. Let me know if you run into any other snags!

内容的提问来源于stack exchange,提问作者Victor Van Hee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:40:47