LED - 3. Let's make a large led display - Part 7 (Tunning)
I covered playing the video in the previous post. I also recommend using Rasbian Jessie to avoid poor screen quality due to unstable brightness.
In this article, I'll show you some ways to improve the quality of your RGB LED matrix output.
First run the nbym.py scripts.
While the process is running, check the thread counts of the python process like this.
And also check the process status with "htop -p 1301" command
From the above, we can know the following.
As shown in the following figure, the two threads do different things. The first main thread is the Python program we run, which is responsible for extracting and converting frames from the video file and storing the images in a buffer.
In the nbym_video.py file, double_buffer.SetImage function stores the image information.
And the second thread do displaying the image that the first thread stored. The RGB LED Matrix must do multiplexing, so the second thread infinitely loops and sens the information to the LED. If the second thread's performance is poor, the loop speed will be decreased, and the multiplexing does not work properly.
So it is very important to allow the second thread to run in real time and keep the loop cycle stable. The reason Zeller recommends Jessie above is that Jessie outperforms Buster in this regard.
If the CPU load is high due to video frame decoding, you might consider increasing the process priority. By monitoring the refresh rate described below, python program's priority boosting up can be considered when the value is too low. But this is not a fundamental solution.
I used the nice command to give it a priority of -20(realtime priority).
Becareful : To give real-time priority using the nice command, you must run with root privileges.
There is an useful option for this purpose. it is "show_refresh_rate" option.
If you set this parameter to 1, then the realtime refresh rate is printed on the console.
If the show_refresh_rate option is enabled, you can see the refresh rate of LED matrix on the console. The higher this value, the better the screen quality.
The uncompressed y4m format has the largest file size but the most stable refresh rate.
The Frozen2.mp4 file has a high CPU load because it needs to decode a large frame size. In particular, the refresh rate's fluctuation range is large because it requires a lot of CPU resources during key frame processing.
But I'm a big fan of python and OpenCV. C++ requires dozens of lines of coding, but with OpenCV in Python, you can process video frames in just a few lines of coding. Using Python has the disadvantage of slowing performance compared to C ++, but many functions of numpy and OpenCV APIs call C / C ++ functions internally to minimize performance degradation. It's a pity that you can't take advantage of the latest high-performance Raspberry Pi 4 when dealing with CPU-intensive video because you use Rasbian Jessie. The Raspberry Pi 3B can handle 256x128 video without any problems, so if you don't have a large LED, you can use it without a problem.
In the next post, I'll show you how to use different HATs that support three chains at the same time.
In this article, I'll show you some ways to improve the quality of your RGB LED matrix output.
OS selection
In the latest Buster Rasibian, the previous article explained that the LED brightness fluctuates because of kernel problems. This does not mean that there is a problem with the Buster kernel. It only means that the accuracy of real-time processing is inferior to the previous version. However, since the human eye is very sensitive to changes in color, this problem causes a decrease in image output quality. Since the Linux OS is not a real-time OS, there is always a chance that this can happen. Just select the appropriate OS to avoid some of these problems. Fortunately, older Jessie versions rarely have this problem, so use Jessie instead of Buster. See the previous post for the Jessie Lite image preparation.Process debugging
You can develop products in C or Python using Henner Jeller's package. But I will focus on Python(Python 3 exactly).First run the nbym.py scripts.
root@raspberrypi:/usr/local/src/rpi-rgb-led-matrix/bindings/python/samples# python3 nbym_video.py --horizontal=2 --vertical=2 --video=Frozen.y4m Matrix H:32 W:256 Image size H:64 W:128 163.3Hz
While the process is running, check the thread counts of the python process like this.
pi@raspberrypi:~ $ sudo ps -eLf|grep python3 daemon 1301 665 1301 17 2 13:28 pts/0 00:00:02 python3 nbym_video.py --horizontal=2 --vertical=2 --video=Frozen.y4m daemon 1301 665 1302 76 2 13:28 pts/0 00:00:09 python3 nbym_video.py --horizontal=2 --vertical=2 --video=Frozen.y4m pi 1220 881 1220 0 1 13:28 pts/1 00:00:00 grep --color=auto python3
And also check the process status with "htop -p 1301" command
From the above, we can know the following.
- There are 2 threads in the same process(process id : 1301)
- The 2 threads occupies the CPU 1 and 4
- python3 process is running with Priority 20, Nice 0(This is the normal value)
As shown in the following figure, the two threads do different things. The first main thread is the Python program we run, which is responsible for extracting and converting frames from the video file and storing the images in a buffer.
In the nbym_video.py file, double_buffer.SetImage function stores the image information.
And the second thread do displaying the image that the first thread stored. The RGB LED Matrix must do multiplexing, so the second thread infinitely loops and sens the information to the LED. If the second thread's performance is poor, the loop speed will be decreased, and the multiplexing does not work properly.
So it is very important to allow the second thread to run in real time and keep the loop cycle stable. The reason Zeller recommends Jessie above is that Jessie outperforms Buster in this regard.
<S/W Diagram>
If the CPU load is high due to video frame decoding, you might consider increasing the process priority. By monitoring the refresh rate described below, python program's priority boosting up can be considered when the value is too low. But this is not a fundamental solution.
I used the nice command to give it a priority of -20(realtime priority).
nice -n -20 python3 nbym_video.py --video=Frozen_s.y4m --horizontal=2 --vertical=2
Becareful : To give real-time priority using the nice command, you must run with root privileges.
Monitoring the refresh rate
Checking the refresh rate of the LED Matrix while displaying the video image is a great help in verifying the performance of the current program.There is an useful option for this purpose. it is "show_refresh_rate" option.
# Configuration for the matrix options = RGBMatrixOptions() options.cols = 64 options.rows = 32 options.chain_length = args.horizontal * args.vertical options.parallel = 1 options.brightness = 80 options.pwm_bits = 11 options.gpio_slowdown = 1.0 options.show_refresh_rate = 1 options.hardware_mapping = 'adafruit-hat-pwm' # If you have an Adafruit HAT: 'adafruit-hat' #options.hardware_mapping = 'adafruit-hat' # If you have an Adafruit HAT: 'adafruit-hat' options.pwm_dither_bits = 0 matrix = RGBMatrix(options = options)
If you set this parameter to 1, then the realtime refresh rate is printed on the console.
Monitoring Environment
- OS : Rasbian Jessie
- Raspberry Pi : 3B
If the show_refresh_rate option is enabled, you can see the refresh rate of LED matrix on the console. The higher this value, the better the screen quality.
<refresh rate>
Video file optimization
Let's take a look at some of these changes using some formats of video.
Video file name
|
Video file size
|
Compressed
|
File Size (Byte)
|
Refresh Rate (Hz)
|
Frozen2.mp4
|
1280X720
|
Y
|
10,876,010
|
60 ~ 180
|
Frozen_s.mp4
|
128X64
|
Y
|
3,684,201
|
140 ~ 190
|
Frozen.y4m
|
256X128
|
N
|
223,128,228
|
150 ~ 190
|
Frozen_s.y4m
|
128X64
|
N
|
55,802,531
|
160 ~ 190
|
The uncompressed y4m format has the largest file size but the most stable refresh rate.
The Frozen2.mp4 file has a high CPU load because it needs to decode a large frame size. In particular, the refresh rate's fluctuation range is large because it requires a lot of CPU resources during key frame processing.
Conclusion
- Prepare a movie of the same frame size as the display size of the RGB Matrix.
- Use uncompressed video format
This video was recorded under the following conditions:
- OS:Rasbian Jessie,
- H/W: Raspberry 3B
- Video Size: 256X128
- Video Format: y4m(uncompressed)
- RGB LED Matrix : 32X64 Matrix 4EA
Wrapping up
There is a C++ video viewer in the util directory. If you are familiar with C/C++, see the page https://github.com/hzeller/rpi-rgb-led-matrix/tree/master/utils. This page explains how to build an image viewer, video viewer using C++, and how to use.But I'm a big fan of python and OpenCV. C++ requires dozens of lines of coding, but with OpenCV in Python, you can process video frames in just a few lines of coding. Using Python has the disadvantage of slowing performance compared to C ++, but many functions of numpy and OpenCV APIs call C / C ++ functions internally to minimize performance degradation. It's a pity that you can't take advantage of the latest high-performance Raspberry Pi 4 when dealing with CPU-intensive video because you use Rasbian Jessie. The Raspberry Pi 3B can handle 256x128 video without any problems, so if you don't have a large LED, you can use it without a problem.
In the next post, I'll show you how to use different HATs that support three chains at the same time.
댓글
댓글 쓰기