Как сделать скриншот (high fps) в Linux (программирование)
Прежде всего я хочу сказать, что я много читал об этом, и я узнал много способов сделать это, но я не смог сделать это в Linux.
Мой проект с Arduino Ambilight, поэтому мне нужно сделать снимок экрана рабочего стола и проанализировать его цвет.
Вначале я использовал Processing 2.0 с классом 'Robot' из 'java.awt'. Первоначально я мог брать 5 кадров в секунду, а затем я получил 13 кадров в секунду. Это работает, но я хочу больше выступлений, поэтому я начинаю читать.
В Windows или Mac у вас есть библиотеки, которые позволяют вам получить прямой доступ к "frameBuffer", поэтому вы можете сделать скриншот действительно "простым" и очень быстрым.
В Ubuntu я пробовал python с Gtk, PIL, Qt... и самый быстрый способ - GTK, но у меня тоже может быть только 15fps.
Моя проблема: я хочу сделать это кроссплатформенным, но я предпочитаю, чтобы моя программа работала в Linux вначале, а затем в Windows (мне это не слишком нравится:P).
Итак, первый вопрос: способен ли python предложить такую производительность? Потому что я думаю, что C++ может быть лучшим вариантом.
И второй вопрос: что мне для этого нужно? Я читал о Xlib (X11), но не могу найти документацию, которая позволила бы мне сделать снимок экрана. Также я знаю, например, FFmpeg, который является мощным инструментом, но я не знаю, как его реализовать.
Я надеюсь, что вы могли бы помочь мне (и извините, если я сделал какие-либо ошибки).
1 ответ
Создание этой кроссплатформенной работы, вероятно, будет довольно трудоемким. Если вашей конечной целью являются окна, то почему бы не использовать проект amblone, который, кажется, делает именно то, что вы хотите?
В любом случае, вот решение с ffmpeg & graphicsmagick, которое довольно быстрое (на моем ноутбуке i7 8GB). ffmpeg захватывает ровно один экран, уменьшает его до наименьшего возможного размера квадрата, направляет вывод в конвертирование graphicsmagick, где его размер изменяется до 1x1 пикселя, а затем сообщает значения rgb изображения.
#!/bin/bash
mkfifo /tmp/screencap.fifo
while true
do
# this version will send the info to a fifo
# ffmpeg -y -loglevel error -f x11grab -s 1920x1080 -i :0.0 -s 32x32 \
# -vframes 1 -f image2 -threads 2 - | gm convert - -resize 1x1 \
# txt:- > /tmp/screencap.fifo
# this version will write out the info to the command line
# and will show you what is going on.
ffmpeg -y -loglevel error -f x11grab -s 1920x1080 -i :0.0 -s 32x32 \
-vframes 1 -f image2 -threads 2 - | gm convert - -resize 1x1 txt:-
done
exit
Это даст вам что-то вроде следующего:
0,0: ( 62, 63, 63) #3E3F3F
0,0: (204,205,203) #CCCDCB
0,0: ( 77, 78, 76) #4D4E4C
0,0 - это местоположение читаемого пикселя. Числа в скобках - это соответствующие значения R, G, B, а числа в конце - ваши типичные шестнадцатеричные значения html-esque. В приведенном выше случае есть только 1 пиксель, но вы можете (если вы хотите, чтобы кардинальные направления были обобщенными значениями RGB), просто изменить -resize 1x1
часть выше, чтобы -resize 3x3
и вы получите что-то вроде:
0,0: ( 62, 63, 65) #3E3F41
1,0: ( 90, 90, 91) #5A5A5B
2,0: (104,105,106) #68696A
0,1: ( 52, 51, 52) #343334
1,1: ( 60, 60, 59) #3C3C3B
2,1: ( 64, 64, 64) #404040
0,2: ( 49, 49, 50) #313132
1,2: ( 60, 60, 60) #3C3C3C
2,2: ( 65, 65, 65) #414141
Я оставлю это вам, чтобы передать эту информацию вашему arduino.
ffmpeg отлично, но вы должны помнить, чтобы отключить бит захвата экрана (здесь в моем примере -f x11grab
) с тем, что использует ваша система Windows. Вот SO ссылка, в которой есть немного больше деталей.
Если вы действительно настаиваете на создании чего-то кроссплатформенного, то я бы порекомендовал погрузиться в openCV с привязками python и использовать устройство кадрового буфера в качестве видеовхода, уменьшив результат до 1x1 пикселя и используя полученное среднее значение цвета, чтобы пропустить ваш ШИМ через некоторые тип UDP-трансляции.