2015-06-28 09:38:55 +00:00
|
|
|
Python bindings for RGB Matrix library
|
|
|
|
|
======================================
|
|
|
|
|
|
|
|
|
|
Building
|
|
|
|
|
--------
|
|
|
|
|
|
2016-07-30 11:59:55 +00:00
|
|
|
In the root directory for the matrix library simply type:
|
2015-06-28 09:38:55 +00:00
|
|
|
|
2016-09-06 01:41:06 +00:00
|
|
|
### Python 2
|
|
|
|
|
|
2016-07-30 11:59:55 +00:00
|
|
|
```shell
|
2016-08-28 23:25:45 +00:00
|
|
|
sudo apt-get update && sudo apt-get install python2.7-dev python-pillow -y
|
2016-07-30 11:59:55 +00:00
|
|
|
make build-python
|
|
|
|
|
sudo make install-python
|
|
|
|
|
```
|
|
|
|
|
|
2016-09-06 01:41:06 +00:00
|
|
|
### Python 3
|
2016-07-30 11:59:55 +00:00
|
|
|
You can also build for Python 3:
|
|
|
|
|
|
|
|
|
|
```shell
|
2016-08-28 23:25:45 +00:00
|
|
|
sudo apt-get update && sudo apt-get install python3-dev python3-pillow -y
|
2016-08-29 07:19:34 +00:00
|
|
|
make build-python PYTHON=$(which python3)
|
|
|
|
|
sudo make install-python PYTHON=$(which python3)
|
2016-07-30 11:59:55 +00:00
|
|
|
```
|
2015-06-28 09:38:55 +00:00
|
|
|
|
2016-09-06 01:41:06 +00:00
|
|
|
### PyPy
|
|
|
|
|
The cython binding to PyPy seems to be somewhat working but extremely slow (20x
|
|
|
|
|
slower even than the regular Python binding, 160x slower than C++), so this is
|
2016-09-14 16:59:41 +00:00
|
|
|
not recommended.
|
|
|
|
|
|
|
|
|
|
So Cython is not good together with PyPy which works best with a
|
|
|
|
|
[CFFI](https://cffi.readthedocs.io/) binding. @Duality4Y did an experiment here
|
|
|
|
|
https://github.com/Duality4Y/rgb-matrix-cffi which works well with PyPy and is
|
|
|
|
|
about twice as fast as running Python3+cython (but Python3+cffi is slower than
|
|
|
|
|
Python3+cython, so we can't just replace everything with cffi).
|
|
|
|
|
|
|
|
|
|
Of course, it would be nice to have the fastest possible binding to all kinds
|
|
|
|
|
of Python interpreters. If anyone wants to work on that, this would certainly
|
|
|
|
|
be a welcome pull request.
|
2016-09-06 01:41:06 +00:00
|
|
|
|
|
|
|
|
Performance
|
|
|
|
|
-----------
|
2016-09-03 19:39:09 +00:00
|
|
|
The simplicity of scripting comes at a price: Python is slower than C++ of course.
|
|
|
|
|
If you have to do a lot of pixel updates in your demo, this can be too slow
|
2016-09-04 15:48:51 +00:00
|
|
|
depending on what you do. Here are some rough numbers for calling `SetPixel()`
|
|
|
|
|
in a tight loop:
|
2016-09-03 19:39:09 +00:00
|
|
|
|
2016-09-04 15:48:51 +00:00
|
|
|
* On a Pi-2 and Pi-3, a Python script will be about 1/8 of the speed compared
|
|
|
|
|
to the corresponding C++ program (pushing ~0.43 Megapixels/s Python
|
|
|
|
|
vs. ~3.5 Megapixels/s C++ on a Pi-3 for instance)
|
|
|
|
|
* On a Pi-1, the difference is even worse: 1/24 of the speed to the
|
2016-09-03 19:39:09 +00:00
|
|
|
corresponding C++ program. Given that the Pi-1 is already about 1/10 the
|
|
|
|
|
speed of a Pi-3, this almost makes Python unusable on a Pi-1
|
2016-09-04 15:48:51 +00:00
|
|
|
(~0.015 Megapixels/s Python vs. ~0.36 Megapixels/s C++)
|
2016-09-06 01:41:06 +00:00
|
|
|
* Also interesting: Python3 is a little bit slower than Python2.7.
|
|
|
|
|
So if you can, stick with Python2.7 for now.
|
2016-09-04 15:48:51 +00:00
|
|
|
* The good news is, that this is due to overhead per function call. If you
|
|
|
|
|
can do more per function call, then this is less problematic. For instance
|
|
|
|
|
if you have an image to be displayed with `SetImage()`, that will be faster
|
|
|
|
|
per pixel.
|
|
|
|
|
(Currently, `SetImage()` is still much slower than it could be, because
|
|
|
|
|
it does not send the raw buffer into the C-side but does individual
|
|
|
|
|
SetPixel() calls in the interface layer. If you are interested in improving
|
|
|
|
|
the performance of Python, this would be a good start and welcomed
|
|
|
|
|
pull request).
|
|
|
|
|
|
|
|
|
|
The ~0.015 Megapixels/s on a Pi-1 means that you can update a 32x32 matrix
|
|
|
|
|
at most with ~15Hz. If you have chained 5, then you barely reach 3Hz.
|
|
|
|
|
In a Pi-3, you get about 400Hz update rate (85Hz for 5-chain) with a Python
|
|
|
|
|
program (while with C++, you can do the same thing with a comfortable 3500Hz
|
|
|
|
|
(700Hz for 5)). Keep in mind that this is if all you do is just calling
|
|
|
|
|
`SetPixel()`, it does not include any time of what you actually want to do in
|
|
|
|
|
your demo - so anything in addition to that will drop your update rate.
|
2016-09-03 19:39:09 +00:00
|
|
|
|
2015-06-28 09:38:55 +00:00
|
|
|
Using the library
|
|
|
|
|
-----------------
|
|
|
|
|
|
2016-07-30 11:59:55 +00:00
|
|
|
Be aware of the fact, that using the RGBMatrix requires root privileges.
|
|
|
|
|
Therefore you will need to run all you python scripts as using sudo.
|
|
|
|
|
|
2016-08-29 00:45:53 +00:00
|
|
|
You find examples in the [samples/](./samples) subdirectory.
|
2016-08-29 07:35:57 +00:00
|
|
|
The examples all use the [samplebase.py](./samples/samplebase.py) that provides
|
|
|
|
|
some utility to all example programs, such as command-line parsing: all
|
|
|
|
|
sample-programs accept `--rows`, `--chain` and `--parallel` as options to
|
|
|
|
|
adapt to your configuration
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd samples
|
|
|
|
|
sudo ./runtext.py --chain=4
|
|
|
|
|
```
|
2016-08-29 00:45:53 +00:00
|
|
|
|
2016-08-29 01:14:09 +00:00
|
|
|
Here a complete example how to write an image viewer:
|
2016-03-30 16:33:41 +00:00
|
|
|
```python
|
|
|
|
|
#!/usr/bin/env python
|
|
|
|
|
import time
|
2016-08-29 01:14:09 +00:00
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
from rgbmatrix import RGBMatrix
|
|
|
|
|
from PIL import Image
|
|
|
|
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
|
sys.exit("Require an image argument")
|
|
|
|
|
else:
|
|
|
|
|
image_file = sys.argv[1]
|
|
|
|
|
|
|
|
|
|
image = Image.open(image_file)
|
|
|
|
|
|
|
|
|
|
rows = 32
|
|
|
|
|
chain = 1
|
|
|
|
|
parallel = 1
|
|
|
|
|
matrix = RGBMatrix(rows, chain, parallel)
|
|
|
|
|
|
|
|
|
|
# Make image fit our screen.
|
|
|
|
|
image.thumbnail((matrix.width, matrix.height), Image.ANTIALIAS)
|
|
|
|
|
|
|
|
|
|
matrix.SetImage(image.convert('RGB'))
|
2015-06-28 09:38:55 +00:00
|
|
|
|
2016-08-29 01:14:09 +00:00
|
|
|
try:
|
|
|
|
|
print("Press CTRL-C to stop.")
|
|
|
|
|
while True:
|
|
|
|
|
time.sleep(100)
|
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
sys.exit(0)
|
2016-03-30 16:33:41 +00:00
|
|
|
```
|