我想显示一个FHD直播(25 fps),并叠加一些(变化的)文本。为此,我基本上使用下面的代码。
基本上是这样的
cv::putText
此处略过)delay
但与e.g.相比,这段代码超级超级慢。mpv
消耗了大量的cpu时间(cv::useOptimized() == true
).
到目前为止 delay
是我不方便的摆弄参数,以某种方式使其可行。
delay == 1
结果是 180%的CPU使用率 (全帧率)delay == 5
导致80%的CPU使用率但是 delay == 5
或5 fps真的很迟钝,实际上还是cpu负载太大。
我怎样才能让这段代码更快或者更好或者以其他方式解决这个任务(我不绑定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);
}
}
我现在发现 valgrind
(储存库)和 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×1200,而流媒体为1920×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%)。不似 协同工作 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 );
}
有一件事是你要创建一个新的窗口,每次你想显示什么东西时都要调整它的大小。
移动这些线条
cv::namedWindow( "PREVIEW", cv::WINDOW_NORMAL );
cv::resizeWindow( "PREVIEW", screen_width, screen_height );
到你之前 while(true)
并看到它,解决了这个