Opencv 一种简单的帧差分法
背景场景通常会随着时间的推移而变化,例如,因为照明条件可能会发生变化(例如,从日出到日落),或者因为可以在背景中添加或删除新对象。 因此,有必要动态地建立背景场景的模型。 基于以上,我编写了一个简单的帧差分代码。它工作得很好,但速度很慢。 我怎样才能使它更快?有什么建议吗Opencv 一种简单的帧差分法,opencv,frame,Opencv,Frame,背景场景通常会随着时间的推移而变化,例如,因为照明条件可能会发生变化(例如,从日出到日落),或者因为可以在背景中添加或删除新对象。 因此,有必要动态地建立背景场景的模型。 基于以上,我编写了一个简单的帧差分代码。它工作得很好,但速度很慢。 我怎样才能使它更快?有什么建议吗 #include <opencv2/highgui/highgui.hpp> #include <opencv2/core/core.hpp> #include <iostream> #i
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/background_segm.hpp >
using namespace cv;
using namespace std;
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/video/tracking.hpp>
int main()
{
cv::Mat gray; // current gray-level image
cv::Mat background; // accumulated background
cv::Mat backImage; // background image
cv::Mat foreground; // foreground image
// learning rate in background accumulation
double learningRate;
int threshold; // threshold for foreground extraction
cv::VideoCapture capture("video.mp4");
// check if video successfully opened
if (!capture.isOpened())
return 0;
// current video frame
cv::Mat frame;
double rate= capture.get(CV_CAP_PROP_FPS);
int delay= 1000/rate;
// foreground binary image
//cv::Mat foreground;
cv::Mat output;
bool stop(false);
while (!stop){
if(!capture.read(frame))
break;
cv::cvtColor(frame, gray, CV_BGR2GRAY);
cv::namedWindow("back");
cv::imshow("back",gray);
// initialize background to 1st frame
if (background.empty())
gray.convertTo(background, CV_32F);
// convert background to 8U
background.convertTo(backImage,CV_8U);
// compute difference between image and background
cv::absdiff(backImage,gray,foreground);
// apply threshold to foreground image
cv::threshold(foreground,output, 10,255,cv::THRESH_BINARY_INV);
// accumulate background
cv::accumulateWeighted(gray, background, 0.01, output);
cv::namedWindow("out");
cv::imshow("out",output);
if (cv::waitKey(delay)>=0)
stop= true;
}
}
#包括
#包括
#包括
#包括
#包括
使用名称空间cv;
使用名称空间std;
#包括
#包括
#包括
int main()
{
cv::Mat gray;//当前灰度图像
cv::Mat background;//累积背景
cv::Mat backImage;//背景图像
cv::Mat前景;//前景图像
//背景积累中的学习率
双学习率;
int threshold;//前景提取的阈值
cv::视频捕获捕获(“video.mp4”);
//检查视频是否成功打开
如果(!capture.isOpened())
返回0;
//当前视频帧
cv::垫架;
双速率=捕获。获取(CV\U CAP\U PROP\U FPS);
int延迟=1000/速率;
//前景二值图像
//cv::Mat前景;
cv::Mat输出;
bool-stop(假);
当(!停止){
如果(!捕获.读取(帧))
打破
cv::CVT颜色(边框、灰色、cv_bgr2灰色);
简历::namedWindow(“背”);
cv::imshow(“背”,灰色);
//将背景初始化为第一帧
if(background.empty())
灰色。convertTo(背景,CV_32F);
//将背景转换为8U
背景转换(背景图像,CV_8U);
//计算图像和背景之间的差异
cv::absdiff(背景图像、灰色、前景);
//对前景图像应用阈值
cv::threshold(前景,输出,10255,cv::THRESH\u BINARY\u INV);
//积累背景
cv::累计加权(灰色,背景,0.01,输出);
cv::namedWindow(“out”);
cv::imshow(“输出”,输出);
如果(cv::waitKey(延迟)>=0)
停止=真;
}
}
我修改并更正了部分代码:
- 在调用
和cv::namedWindow(“back”)
的while循环中,只需执行一次cv::namedWindow(“out”)
- 使用
查看数组是否为空,这对于矩阵if(background.empty())
为空的第一个循环是必需的,因为剩余的矩阵将被填充,这样代码就不会出错,第一个循环初始化为零background
考虑迭代while循环中需要的类型和大小。此外,它不影响积累的运作background=cv::Mat::zeros(行、列、cv_32F)
int main()
{
cv::Mat gray; // current gray-level image
cv::Mat background; // accumulated background
cv::Mat backImage; // background image
cv::Mat foreground; // foreground image
// learning rate in background accumulation
double learningRate;
int threshold; // threshold for foreground extraction
cv::VideoCapture capture("C:/Users/Pedram91/Pictures/Camera Roll/videoplayback.mp4");////C:/Users/Pedram91/Downloads/Video/videoplayback.mp4//C:/FLIR.mp4
// check if video successfully opened
if (!capture.isOpened())
return 0;
// current video frame
cv::Mat frame;
double rate= capture.get(CV_CAP_PROP_FPS);
int delay= 1000/rate;
// foreground binary image
//cv::Mat foreground;
cv::Mat output;
bool stop(false);
cv::namedWindow("back");//This should go here,You only need to call once
cv::namedWindow("out");//This should go here,You only need to call once
int cols=capture.get(CV_CAP_PROP_FRAME_HEIGHT);
int rows=capture.get(CV_CAP_PROP_FRAME_WIDTH);
background=cv::Mat::zeros(rows,cols,CV_32F);//this will save the "if (background.empty())" in the while loop
while (!stop){
if(!capture.read(frame))
break;
cv::cvtColor(frame, gray, CV_BGR2GRAY);
cv::imshow("back",gray);
// initialize background to 1st frame
// if (background.empty())
gray.convertTo(background, CV_32F);
// convert background to 8U
background.convertTo(backImage,CV_8U);
// compute difference between image and background
cv::absdiff(backImage,gray,foreground);
// apply threshold to foreground image
cv::threshold(foreground,output, 10,255,cv::THRESH_BINARY_INV);
// accumulate background
cv::accumulateWeighted(gray, background, 0.01, output);
cv::imshow("out",output);
if (cv::waitKey(delay)>=0)
stop= true;
}
}
OpenCV已经实现了类似的功能,也许你们可以从这个例子中得到一些启发。他们提供了实施过程中参考的文件。然而,根据我的经验,这些事情通常都很慢。谢谢你的建议。我得写一个实时运动物体跟踪器。你知道这个主题的任何实时方法吗?你可以从上面的链接开始,说服自己opencv方法比你将要编写的任何自定义代码都更好更快(直到你获得更多的经验)。你能公布你的执行时间吗?这段代码不会那么慢……如果(cv::waitKey(1)>=0),您可能应该使用
。您的代码有一些小错误(如下面的答案所指出的),但我认为瓶颈是waitKey
。您的背景图像需要浮点精度吗?您可以尝试使用beta=1-alpha的addWeighted,但不确定它是否更快(您可能会有一些开销,但不必为每帧转换为8位。您的延迟值不关心所需的处理时间(例如,如果您有25 fps,您的延迟将是40 ms,但如果您的处理时间是20 ms,您将在每帧之间等待60 ms,而不是40 ms)。此外,cv::waitKey不是非常精确(在windows系统waitKey上,可能会比您希望的等待时间更长)你能解释一下这个代码对OP代码的改进是什么吗?你对性能进行了比较吗?只有代码的答案不是很清楚,考虑用一些解释来改进它。再检查一下答案。你可以看到我格式化了你的答案。学习如何使用格式化选项来产生更好的答案。同时,请仔细检查我的ED。我是新来的,我还在学习如何处理这个网站,纠正了我糟糕的写作方式,给我留下了深刻的印象,哥伦比亚的问候是的,我同意这是我的答案。