【问题标题】:Raspberrypi python display image from memoryRaspberry Pi python 从内存中显示图像
【发布时间】:2018-12-27 14:41:50
【问题描述】:

任务如下:在外部事件 (GPIO) 上从 Picamera 捕获帧并将其显示在屏幕上。

使用的方法:

  1. PIL image.show() - 制作临时文件并使用外部查看器,我需要从内存中获取。

  2. Opencv cv.imshow() - 在几个序列事件后冻结窗口和图像。我玩过延迟它仍然冻结。

  3. UPD:带有图像的 Gdk 窗口在几个事件后也会冻结,但如果 GLib 计时器事件调用更新,则不会冻结,但 GPIO 的处理程序不会冻结。

您能建议任何方法来完成这项任务吗?

【问题讨论】:

  • 为什么你需要完全从记忆中?
  • 事件频率约为 1Hz。所以为了避免闪存重写并使其尽可能快。

标签: python image camera raspberry-pi


【解决方案1】:

创建一个小巧的 RAMdisk,它既美观又快速,可避免 SD 卡磨损。将图像写入其中并使用feh 或类似名称显示:

sudo mkdir -p /media/ramdisk
sudo mount -t tmpfs -o size=4M tmpfs /media/ramdisk

df /media/ramdisk
Filesystem     1K-blocks  Used Available Use% Mounted on
tmpfs               4096     0      4096   0% /media/ramdisk

然后启动一个 Python 脚本来更新您的图像。


初始脚本可能如下所示:

#!/bin/bash

# Create a couple of useful variables
MNTPNT="/media/ramdisk"
IMGNAM="$MNTPNT/image.ppm"

# Make ramdisk and mount
sudo mkdir -p /media/ramdisk 2> /dev/null
sudo mount -t tmpfs -o size=4M tmpfs /media/ramdisk 2> /dev/null

# Create initial empty image to display with ImageMagick or any other means
convert -size 800x600 xc:black -depth 8 "$IMGNAM"

# Get 'feh' started in "Slideshow mode" in the background
feh --title "Monitor" -D 0.5 "$IMGNAM" "$IMGNAM" &

# Now start Python script with image name
./monitor.py "$IMGNAM"

那么 Python 脚本 monitor.py 可能如下所示:

#!/usr/bin/python3

import os, sys, time
from PIL import Image, ImageDraw
from random import randint

# Pick up parameters
filename = sys.argv[1]

# Create initial image and drawing handle
w, h = 800, 600
im = Image.new("RGB",(w,h),color=(0,0,0))
draw = ImageDraw.Draw(im)

# Create name of temp image in same directory
tmpnam = os.path.join(os.path.dirname(filename), "tmp.ppm") 

# Now loop, updating the image 100 times
for i in range(100):
   # Select random top-left and bottom-right corners for image
   x0 = randint(0,w)
   y0 = randint(0,h)
   x1 = x0 + randint(10,250)
   y1 = y0 + randint(10,250)
   # Select a random colour and draw a rectangle
   fill = (randint(0,255), randint(0,255), randint(0,255))
   draw.rectangle([(x0,y0),(x1,y1)], fill=fill)
   # Save image to a temporary file, then rename in one immutable operation...
   # ... so that 'feh' cannot read a half-saved image
   im.save(tmpnam)
   os.rename(tmpnam,filename)
   time.sleep(0.3)

本质上,您的应用程序所要做的就是:

 while true:
   ... generate new image ...
   im.save(tmpnam)
   os.rename(tmpnam,filename)

如果您从feh 命令中删除--title "monitor",您将看到它只是在遍历包含2 个图像的列表,而这两个图像恰好是同一个图像。图像每 0.5 秒交换一次,不闪烁。如果你愿意,你可以改变它。如果由于某种原因您不希望它在两者之间连续交替,您可以使延迟更大,并发送SIGUSR1feh (os.kill(pid, signal.SIGUSR1)) 以使其在更新图像时切换。

【讨论】:

  • 我试过了。 Popen,不打开窗口。将多次不同的图像写入标准输入后会刷新图像吗?
  • 需要,shell=True。两次或更多次写入同一窗口后,它不会刷新图像。所以解决方案没有用,因为杀死和恢复过程太慢了。第一个解决方案只能更新 1Hz 我需要更多和同步。也很慢。
  • 疯狂的脚本!也许会尝试... feh 刷新率为每秒 1 次,因此它忽略 0.5 并使 1 我需要更多。我已经绑定到使用 Gdk 库制作图像查看器。而且你知道 ?同样的错误!它在大约 10 个外部事件后挂起。带有 GPIO 处理程序的主程序正在运行,并且 GDK 窗口被冻结。
  • 除了 GPIO 之外,您还知道其他服务外部事件的方式吗?
  • 图像在我的机器上每秒更改两次-D 0.5
猜你喜欢
  • 2018-11-04
  • 2016-06-24
  • 2018-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多