如何在Linux中截取高帧率屏幕截图(编程)
首先,我想说我已经读了很多关于这个话题的资料,学到了很多方法,但在Linux上我还是没能做到。
我的项目是用Arduino做一个氛围灯,所以我需要截取桌面的屏幕并分析颜色。
一开始我使用Processing 2.0,利用'java.awt'里的'Robot'类。最开始我能每秒截取5帧,后来提升到13帧每秒。这虽然可以,但我想要更好的性能,所以我开始查资料。
在Windows或Mac上,有一些库可以直接访问'frameBuffer',这样你就可以非常“简单”和快速地截屏。
在Ubuntu上,我尝试了用Python结合Gtk、PIL、Qt等,发现GTK是最快的,但我也只能达到大约15帧每秒。
我的问题是:我想做一个跨平台的程序,但我更希望我的程序先在Linux上运行,然后再在Windows上(我对Windows不太喜欢 :P)。
所以,第一个问题是:Python能提供这样的性能吗?因为我觉得C++可能是更好的选择。
第二个问题是:我需要做些什么?我读过关于Xlib(X11)的资料,但找不到能让我截屏的文档。另外,我知道FFmpeg是一个强大的工具,但我不知道怎么用它。
希望你们能帮我(如果我有任何错误,请多多包涵)。
1 个回答
要让这个在不同平台上都能用,可能需要花不少功夫。如果你最终的目标是Windows,那为什么不试试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格式的十六进制值。在上面的例子中只有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广播来控制你的PWM。