FHD 视频流上 OpenCV 文本覆盖的足迹太高 CPU
Too High CPU Footprint of OpenCV Text Overlay on FHD Video Stream
我想显示全高清直播 (25 fps) 并覆盖一些(变化的)文本。为此,我基本上使用下面的代码。
基本上是
- 加载框架
- (
cv::putText
此处略过)
- 如果是
delay
的倍数则显示框架
但与例如相比,代码超级超级慢mpv
并消耗了很多 cpu 时间 (cv::useOptimized() == true
)。
到目前为止 delay
是我不方便的 fiddle 参数,以某种方式使其可行。
delay == 1
导致 180 % CPU 使用率(全帧率)
delay == 5
导致 80 % CPU 使用率
但是 delay == 5
或 5 fps 确实很慢,实际上仍然 cpu 负载太多。
How can I make this code faster or otherwise better or otherwise solve the task (I'm not bound to opencv)?
P.s. 如果没有 cv::imshow
,CPU 使用率低于 30%,无论 delay
.
#include <opencv2/opencv.hpp>
#include <X11/Xlib.h>
// process ever delayth frame
#define delay 5
Display* disp = XOpenDisplay(NULL);
Screen* scrn = DefaultScreenOfDisplay(disp);
int screen_height = scrn->height;
int screen_width = scrn->width;
int main(int argc, char** argv){
cv::VideoCapture cap("rtsp://url");
cv::Mat frame;
if (cap.isOpened())
cap.read(frame);
cv::namedWindow( "PREVIEW", cv::WINDOW_NORMAL );
cv::resizeWindow( "PREVIEW", screen_width, screen_height );
int framecounter = 0;
while (true){
if (cap.isOpened()){
cap.read(frame);
framecounter += 1;
// Display only delay'th frame
if (framecounter % delay == 0){
/*
* cv::putText
*/
framecounter = 0;
cv::imshow("PREVIEW", frame);
}
}
cv::waitKey(1);
}
}
弹出的一件事是您正在创建一个新的 window 并在每次您想要显示某些内容时调整它的大小。
移动这些行
cv::namedWindow( "PREVIEW", cv::WINDOW_NORMAL );
cv::resizeWindow( "PREVIEW", screen_width, screen_height );
到你的 while(true)
之前,看看它能解决这个问题
我现在了解 valgrind
(repository) and gprof2dot
(pip3 install --user gprof2dot
):
valgrind --tool=callgrind /path/to/my/binary # Produced file callgrind.out.157532
gprof2dot --format=callgrind --output=out.dot callgrind.out.157532
dot -Tpdf out.dot -o graph.pdf
这产生了一个很棒的图表,表明 超过 60% 在 cvResize
上蒸发了。
事实上,当我注释掉 cv::resizeWindow
时,cpu 使用率从 180% 降低到 ~ 60%。
由于屏幕的分辨率为 1920 x 1200,流的分辨率为 1920 x 1080,因此除了燃烧 CPU 个循环外,它基本上什么也没做。
到目前为止,这仍然很脆弱。一旦我将它切换到全屏模式并返回,cpu 负载又回到 180%。
为了解决这个问题,我发现我可以使用 cv::WINDOW_AUTOSIZE
完全禁用调整大小 ...
cv::namedWindow( "PREVIEW", cv::WINDOW_AUTOSIZE );
...或者——如Micka建议的那样——在使用 OpenGL 支持编译的 OpenCV 版本上(-DWITH_OPENGL=ON
,我的 Debian 存储库版本不支持),使用 ...
cv::namedWindow( "PREVIEW", cv::WINDOW_OPENGL );
... 将渲染卸载到 GPU,事实证明与调整大小一起速度更快(55% CPU 与我的 65% 相比)。
它只是 does not seem 与 cv::WINDOW_KEEPRATIO
一起工作。*
此外,事实证明 cv:UMat
可以用作 cv:Mat
的直接替代品,从而进一步提高性能(如 ps -e -o pcpu,args
所见):
附录
[*] 所以我们必须手动缩放它并注意纵横比。
float screen_aspratio = (float) screen_width / screen_height;
float image_aspratio = (float) image_width / image_height;
if ( image_aspratio >= screen_aspratio ) { // width limited, center window vertically
cv::resizeWindow("PREVIEW", screen_width, screen_width / image_aspratio );
cv::moveWindow( "PREVIEW", 0, (screen_height - image_height) / 2 );
}
else { // height limited, center window horizontally
cv::resizeWindow("PREVIEW", screen_height * image_aspratio, screen_height );
cv::moveWindow( "PREVIEW", (screen_width - image_width) / 2, 0 );
}
我想显示全高清直播 (25 fps) 并覆盖一些(变化的)文本。为此,我基本上使用下面的代码。
基本上是
- 加载框架
- (
cv::putText
此处略过) - 如果是
delay
的倍数则显示框架
但与例如相比,代码超级超级慢mpv
并消耗了很多 cpu 时间 (cv::useOptimized() == true
)。
到目前为止 delay
是我不方便的 fiddle 参数,以某种方式使其可行。
delay == 1
导致 180 % CPU 使用率(全帧率)delay == 5
导致 80 % CPU 使用率
但是 delay == 5
或 5 fps 确实很慢,实际上仍然 cpu 负载太多。
How can I make this code faster or otherwise better or otherwise solve the task (I'm not bound to opencv)?
P.s. 如果没有 cv::imshow
,CPU 使用率低于 30%,无论 delay
.
#include <opencv2/opencv.hpp>
#include <X11/Xlib.h>
// process ever delayth frame
#define delay 5
Display* disp = XOpenDisplay(NULL);
Screen* scrn = DefaultScreenOfDisplay(disp);
int screen_height = scrn->height;
int screen_width = scrn->width;
int main(int argc, char** argv){
cv::VideoCapture cap("rtsp://url");
cv::Mat frame;
if (cap.isOpened())
cap.read(frame);
cv::namedWindow( "PREVIEW", cv::WINDOW_NORMAL );
cv::resizeWindow( "PREVIEW", screen_width, screen_height );
int framecounter = 0;
while (true){
if (cap.isOpened()){
cap.read(frame);
framecounter += 1;
// Display only delay'th frame
if (framecounter % delay == 0){
/*
* cv::putText
*/
framecounter = 0;
cv::imshow("PREVIEW", frame);
}
}
cv::waitKey(1);
}
}
弹出的一件事是您正在创建一个新的 window 并在每次您想要显示某些内容时调整它的大小。
移动这些行
cv::namedWindow( "PREVIEW", cv::WINDOW_NORMAL );
cv::resizeWindow( "PREVIEW", screen_width, screen_height );
到你的 while(true)
之前,看看它能解决这个问题
我现在了解 valgrind
(repository) and gprof2dot
(pip3 install --user gprof2dot
):
valgrind --tool=callgrind /path/to/my/binary # Produced file callgrind.out.157532
gprof2dot --format=callgrind --output=out.dot callgrind.out.157532
dot -Tpdf out.dot -o graph.pdf
这产生了一个很棒的图表,表明 超过 60% 在 cvResize
上蒸发了。
事实上,当我注释掉 cv::resizeWindow
时,cpu 使用率从 180% 降低到 ~ 60%。
由于屏幕的分辨率为 1920 x 1200,流的分辨率为 1920 x 1080,因此除了燃烧 CPU 个循环外,它基本上什么也没做。
到目前为止,这仍然很脆弱。一旦我将它切换到全屏模式并返回,cpu 负载又回到 180%。
为了解决这个问题,我发现我可以使用 cv::WINDOW_AUTOSIZE
完全禁用调整大小 ...
cv::namedWindow( "PREVIEW", cv::WINDOW_AUTOSIZE );
...或者——如Micka建议的那样——在使用 OpenGL 支持编译的 OpenCV 版本上(-DWITH_OPENGL=ON
,我的 Debian 存储库版本不支持),使用 ...
cv::namedWindow( "PREVIEW", cv::WINDOW_OPENGL );
... 将渲染卸载到 GPU,事实证明与调整大小一起速度更快(55% CPU 与我的 65% 相比)。
它只是 does not seem 与 cv::WINDOW_KEEPRATIO
一起工作。*
此外,事实证明 cv:UMat
可以用作 cv:Mat
的直接替代品,从而进一步提高性能(如 ps -e -o pcpu,args
所见):
附录
[*] 所以我们必须手动缩放它并注意纵横比。
float screen_aspratio = (float) screen_width / screen_height;
float image_aspratio = (float) image_width / image_height;
if ( image_aspratio >= screen_aspratio ) { // width limited, center window vertically
cv::resizeWindow("PREVIEW", screen_width, screen_width / image_aspratio );
cv::moveWindow( "PREVIEW", 0, (screen_height - image_height) / 2 );
}
else { // height limited, center window horizontally
cv::resizeWindow("PREVIEW", screen_height * image_aspratio, screen_height );
cv::moveWindow( "PREVIEW", (screen_width - image_width) / 2, 0 );
}