Как сделать скриншот (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, который, кажется, делает именно то, что вы хотите?

http://amblone.com/guide

В любом случае, вот решение с 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-трансляции.

Другие вопросы по тегам