【问题标题】:a simple frame-differencing一个简单的帧差
【发布时间】:2015-10-05 07:58:21
【问题描述】:

背景场景通常会随着时间而变化,例如,照明条件可能会发生变化(例如,从日出到日落),或者可能会从背景中添加或移除新对象。 因此,需要动态构建背景场景的模型。 基于以上,我写了一个简单的帧差分代码。它工作得很好,但它很慢。 我怎样才能让它更快?有什么建议吗?

 #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; 
      }

     }

【问题讨论】:

  • OpenCV 已经实现了类似的东西,也许你可以从this 示例中获得一些启发。提供参考他们从中获取实施的论文。但是,根据我的经验,这些事情通常很慢。
  • 感谢您的建议。我必须编写一个实时移动对象跟踪器。你知道这个主题的任何实时方法吗?
  • 您可以从上面发布的链接开始,并说服自己 opencv 方法比您编写的任何自定义代码更好更快(直到您获得更多经验)。您还可以发布您的执行时间吗?这段代码不可能那么慢...
  • 或许你应该使用if (cv::waitKey(1)&gt;=0)。您的代码有一些小错误(如下面的答案所指出的),但我认为瓶颈是waitKey
  • 您的背景图像需要浮点精度吗?您可以尝试使用 beta=1-alpha 的 addWeighted,但不确定它是否更快(您可能会得到一些开销,但您不必为每帧转换为 8 位。您的 delay 值不关心所需的处理时间(例如,如果您有 25 fps,您的延迟将是 40 毫秒,但如果您的处理时间是 20 毫秒,您将在每帧之间等待 60 毫秒而不是 40 毫秒)。此外, cv::waitKey 不是很精确(在 Windows 系统 waitKey 上,可能等待的时间比您希望的要长)

标签: opencv frame


【解决方案1】:

我修改并更正了您的部分代码:

  • 在您调用cv::namedWindow("back")cv::namedWindow("out") 的while 循环中,只需执行一次。
  • 您使用if (background.empty()) 来查看数组是否为空,这对于矩阵background 为空的第一个循环是必要的,因为剩余的矩阵将被填充,因此您的代码不会错误第一个循环初始化为零background=cv::Mat::zeros(rows,cols,CV_32F),考虑到迭代while循环中所需的类型和大小。也不影响累加的操作。

这里是更新的代码:

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; 
  }

 }

【讨论】:

  • 你能解释一下这段代码对 OP 代码的改进吗?你比较过性能吗?仅代码答案不是很清楚,请考虑通过一些解释来改进它
  • 再次检查答案
  • 好多了。如您所见,我格式化您的答案。了解如何使用格式选项来生成更好的答案。另外,请仔细检查我的编辑,看看是否适合您,或进行相应的编辑。
  • 我是新手,我还在学习如何处理网站,纠正了我写的不好的形式给我留下了深刻的印象,来自哥伦比亚的问候
  • 是的,我同意这是我的回答。
猜你喜欢
  • 1970-01-01
  • 2023-03-24
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多