Показать изображение с omxiv прямо из памяти на RPI - PullRequest
0 голосов
/ 08 ноября 2019

Я хочу создать изображение в PILLOW и показать его на экране Raspberry Pi, например, с помощью omxiv direct из памяти, не сохраняя его на карту памяти, что-то вроде этого:

Python 2.7:

from PIL import Image
import os

img = Image.new('RGB', size=(150, 50), color=(0, 0, 255))
....
im_file = ????
os.system('omxiv im_file')

Может кто-нибудь сказать мне, как это сделать?

Ответы [ 2 ]

0 голосов
/ 12 ноября 2019

Я провел несколько экспериментов с кадровым буфером на моем Raspberry Pi 4. Вот что мне удалось решить ...

Вы можете получить разрешение экрана, используя команду fbset, например:

fbset -fb /dev/fb0 

Пример вывода

mode "1280x1024"
    geometry 1280 1024 1280 1024 32
    timings 0 0 0 0 0 0 0
    accel true
    rgba 8/16,8/8,8/0,0/0
endmode

Это говорит о том, что экран имеет ширину 1280 пикселей и высоту 1024 пикселей, и мне нужно записать 4 байта на пиксель в порядке BGRA888.


Итак, я могу сделать быстрый тест с ImageMagick , чтобы посмотреть, смогу ли я заполнить экран, например:

# Write to screen buffer - BGRA8888, width=1280, height=1024
convert -size 1280x1024 -depth 8 gradient:lime-magenta  bgra:/dev/fb0

и он заполняетсяэкран с известково-пурпурным градиентом. Отлично!


Итак, приобретя эти знания и немного уверенности, давайте попробуем Python ...

#!/usr/bin/env python3

import numpy as np

# Map the screen as Numpy array
# N.B. Numpy stores in format HEIGHT then WIDTH, not WIDTH then HEIGHT!
# c is the number of channels, 4 because BGRA
h, w, c = 1024, 1280, 4
fb = np.memmap('/dev/fb0', dtype='uint8',mode='w+', shape=(h,w,c)) 

# Fill entire screen with blue - takes 29 ms on Raspi 4
fb[:] = [255,0,0,255]

# Fill top half with red - takes 15 ms on Raspi 4
fb[:h//2] = [0,0,255,255]

# Fill bottom right quarter with green - takes 7 ms on Raspi 4
fb[h//2:, w//2:] = [0,255,0,255] 

Затем я попытался показать изображение - Лена, конечно. Итак, просто для краткости и простоты, я сделал Лену точно подходящего размера и добавил альфа-канал с ImageMagick:

convert lena.png -resize 1280x1024\! -alpha opaque png32:lena1280.png

Затем продолжил следующим образом в сеансе Python, который я начал выше:

from PIL import Image

# Load Lena image
im = Image.open('/home/pi/lena1280.png') 

# Convert from PIL Image to Numpy array
n = np.array(im)

# Blit to screen - takes 30ms
fp[:] = n

Обратите внимание, что вам, вероятно, лучше использовать OpenCV для загрузки изображения с cv.imread(...,cv.IMREAD_UNCHANGED), потому что это доставит вам массив Numpy напрямую, без необходимости преобразования, и порядок BGR уже будет соответствовать порядку в буфере кадров.


Другие полезные команды - для справки!

# Retrieve EDID settings from monitor and write into a file called "edid"
tvservice -d edid

# Parse the file we just created to see what the attached monitor is capable of
edidparser edid

Пример вывода

Enabling fuzzy format match...
Parsing edid...
HDMI:EDID version 1.3, 0 extensions, screen size 38x30 cm
HDMI:EDID features - videodef 0x80 standby suspend active off; colour encoding:RGB444|YCbCr444|YCbCr422; sRGB is default colourspace; preferred format is native; does not support GTF
HDMI:EDID found monitor S/N descriptor tag 0xff
HDMI:EDID found monitor name descriptor tag 0xfc
HDMI:EDID monitor name is DELL_1907FP
HDMI:EDID found monitor range descriptor tag 0xfd
HDMI:EDID monitor range offsets: V min=0, V max=0, H min=0, H max=0
HDMI:EDID monitor range: vertical is 56-76 Hz, horizontal is 30-81 kHz, max pixel clock is 140 MHz
HDMI:EDID monitor range does not support GTF
HDMI:EDID found preferred DMT detail timing format: 1280x1024p @ 60 Hz (35)
HDMI:EDID established timing I/II bytes are A5 4B 00
HDMI:EDID found DMT format: code 4, 640x480p @ 60 Hz in established timing I/II
HDMI:EDID found DMT format: code 6, 640x480p @ 75 Hz in established timing I/II
HDMI:EDID found DMT format: code 9, 800x600p @ 60 Hz in established timing I/II
HDMI:EDID found DMT format: code 11, 800x600p @ 75 Hz in established timing I/II
HDMI:EDID found DMT format: code 16, 1024x768p @ 60 Hz in established timing I/II
HDMI:EDID found DMT format: code 18, 1024x768p @ 75 Hz in established timing I/II
HDMI:EDID found DMT format: code 36, 1280x1024p @ 75 Hz in established timing I/II
HDMI:EDID standard timings block x 8: 0x714F 8180 0101 0101 0101 0101 0101 0101 
HDMI:EDID found DMT format: code 21, 1152x864p @ 75 Hz (4:3) in standard timing 0
HDMI:EDID found DMT format: code 35, 1280x1024p @ 60 Hz (5:4) in standard timing 1
HDMI:EDID filtering formats with pixel clock unlimited MHz or h. blanking unlimited
HDMI:EDID best score mode initialised to DMT (4) 640x480p @ 60 Hz with pixel clock 25 MHz (score 0)
HDMI:EDID best score mode is now DMT (4) 640x480p @ 60 Hz with pixel clock 25 MHz (score 36864)
HDMI:EDID DMT mode (6) 640x480p @ 75 Hz with pixel clock 31 MHz has a score of 11520
HDMI:EDID best score mode is now DMT (9) 800x600p @ 60 Hz with pixel clock 40 MHz (score 57600)
HDMI:EDID DMT mode (11) 800x600p @ 75 Hz with pixel clock 49 MHz has a score of 18000
HDMI:EDID best score mode is now DMT (16) 1024x768p @ 60 Hz with pixel clock 65 MHz (score 94370)
HDMI:EDID DMT mode (18) 1024x768p @ 75 Hz with pixel clock 78 MHz has a score of 29491
HDMI:EDID DMT mode (21) 1152x864p @ 75 Hz with pixel clock 108 MHz has a score of 62324
HDMI:EDID best score mode is now DMT (35) 1280x1024p @ 60 Hz with pixel clock 108 MHz (score 5260929)
HDMI:EDID DMT mode (36) 1280x1024p @ 75 Hz with pixel clock 135 MHz has a score of 49152
HDMI0:EDID preferred mode remained as DMT (35) 1280x1024p @ 60 Hz with pixel clock 108 MHz
HDMI:EDID has only DVI support and no audio support
edidparser exited with code 0

Вы можете отключить /отмените текстовый курсор в консоли, как this :

sudo sh -c "TERM=linux setterm -foreground black -clear all >/dev/tty0"

, и снова включите его следующим образом:

sudo sh -c "TERM=linux setterm -foreground white -clear all >/dev/tty0"

Keywords :Raspberry Pi, RasPi, кадровый буфер, fb0, / dev / fb0, Python, Numpy, ImageMagick, прямой доступ к буферу кадров, edid, HDMI, DVI, возможности монитора, функции, tvservice, edidparser, разрешение, bgra8888, blit, bit-blit,курсор

0 голосов
/ 09 ноября 2019

Самый простой способ сделать это - убедиться, что ваша файловая система /tmp смонтирована на tmpfs, которая основана исключительно на памяти и поэтому не записывается на вашу SD-карту. Обратите внимание, это означает, что содержимое теряется при каждой перезагрузке.

Итак, вам нужно стать root и использовать ваш любимый редактор для редактирования /etc/fstab, в моем случае это будет:

sudo vi /etc/fstab

И затем вам нужно добавить строку, подобную этой:

tmpfs   /tmp    tmpfs   defaults,noatime,nosuid 0   0

Затем сохраните файл и перезагрузите RasPi. Если вы затем запустите df, вы увидите, что /tmp включен tmpfs:

df
tmpfs             966620       0    966620   0% /tmp

Итак, теперь к вашему коду. Если это новый проект, который, я полагаю, должен быть, если вы не знаете, с чего начать, рассмотрите возможность использования Python3, срок действия которого истек 10 лет, а не Python2, который будет прекращен через 2 месяца.

Теперь вам нужно использовать этот код:

#!/usr/bin/env python3

from PIL import Image
import sys, os

# Create a new 640x480 magenta image
img = Image.new('RGB', size=(640, 480), color=(255, 0, 255))

filename = '/tmp/image.jpg'
img.save(filename)
os.system('omxiv ' + filename)

Обратите внимание, что вы "можете" передать изображение в omxiv в командной строке:

cat image.jpg | omxiv

или, с программой на Python:

WriteImageWithPIL.py | omxiv

Но , что создает две проблемы. Во-первых, он больше не читает любые клавиши, которые вы вводите на клавиатуре, потому что он читает из stdin. Во-вторых, PIL так расстраивается, что записывает в omxiv, потому что он закрывает канал, прежде чем PIL сможет сбросить данные, поэтому вам, вероятно, придется начать использовать stdbuffer, и это приведет к большому беспорядку.

...