注意事项

1)添加命名空间

using namespace cvb;

2)

//     unique_ptr<IplImage, void(*)(IplImage*)> labelImg(cvCreateImage(cvSize(width, height), IPL_DEPTH_LABEL, 1), 

//       [](IplImage* p){ cvReleaseImage(&p); });

错误

无法从“`anonymous-namespace'::<lambda0>”转换为“void (__cdecl *const )

暂时不使用C11的语言特性

3)

需要将使用的库函数导出来,使用如下的宏定义:

__declspec(dllexport)


源码

#include <SDKDDKVer.h>

#include <stdio.h>

#include <tchar.h>

#include<iostream>

#include "cv.h"

#include "cvblob.h"

#include "highgui.h"

#include<opencv2\opencv.hpp>

#include<opencv2\video\background_segm.hpp>


using namespace cv;

using namespace cvb;

using namespace std;


//对轮廓按面积降序排序,目的是去除那些小轮廓目标

bool descSort(vector<Point> p1, vector<Point> p2) {

  return contourArea(p1) > contourArea(p2);

}


void processVideo(char* videoFilename)

{

  Mat frame; // current frame

  Mat fgMaskMOG2; // fg mask fg mask generated by MOG2 method

  Mat bgImg; // background

  Ptr<BackgroundSubtractorMOG2> pMOG2 = createBackgroundSubtractorMOG2(200, 36.0, false); // MOG2 Background subtractor


  while (true)

  {

    VideoCapture capture(videoFilename);

    if (!capture.isOpened())

    {

      cerr << "Unable to open video file: " << videoFilename << endl;

      return;

    }


    int width = (int)capture.get(CV_CAP_PROP_FRAME_WIDTH);

    int height = (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT);


//     unique_ptr<IplImage, void(*)(IplImage*)> labelImg(cvCreateImage(cvSize(width, height), IPL_DEPTH_LABEL, 1), 

//       [](IplImage* p){ cvReleaseImage(&p); });

    IplImage* labelImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_LABEL, 1);

    CvBlobs blobs;

    CvTracks tracks;


    while (true)

    {

      // read input data. ESC or 'q' for quitting

      int key = waitKey(1);

      if (key == 'q' || key == 27)

        return;

      if (!capture.read(frame))

        break;


      // update background

      pMOG2->apply(frame, fgMaskMOG2);

      pMOG2->getBackgroundImage(bgImg);

      imshow("BG", bgImg);

      imshow("Original mask", fgMaskMOG2);


      // post process

      medianBlur(fgMaskMOG2, fgMaskMOG2, 5);

      imshow("medianBlur", fgMaskMOG2);

      morphologyEx(fgMaskMOG2, fgMaskMOG2, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(5, 5))); // fill black holes

      morphologyEx(fgMaskMOG2, fgMaskMOG2, MORPH_OPEN, getStructuringElement(MORPH_RECT, Size(5, 5))); // fill white holes

      imshow("morphologyEx", fgMaskMOG2);


      // track

      cvLabel(&IplImage(fgMaskMOG2), labelImg, blobs);

      cvFilterByArea(blobs, 64, 10000);

      cvUpdateTracks(blobs, tracks, 10, 90, 30);

      cvRenderTracks(tracks, &IplImage(frame), &IplImage(frame));


      // show

      imshow("Frame", frame);


      key = waitKey(30);

    }

  }

}




int main() {


  processVideo("E:/smoky-cars/positive/大庆东路与水机路交叉口(东北)_冀BU0157_02_141502_01_3_50.wh264");

  return 0;

  //读入视频

  VideoCapture capture("E:/smoky-cars/positive/大庆东路与水机路交叉口(东北)_冀BU0157_02_141502_01_3_50.wh264");

  //定义一个Mat变量,用于存储每一帧的图像

  Mat frame;

  //前景

  Mat mask;

  //连通分量

  Mat srcImage;

  //结果

  Mat result;


  //用混合高斯模型训练背景图像

  Ptr<BackgroundSubtractorMOG2> bgsubtractor = createBackgroundSubtractorMOG2();

  bgsubtractor->setVarThreshold(20);


  //for (int  k = 0; k < 100; k++)

  //{

  //    //读取当前帧

  //    capture >> frame;

  //    //若视频播放完成,退出循环

  //    if (frame.empty())

  //    {

  //        break;

  //    }

  //    bgsubtractor->apply(frame, mask, 0.2);

  //}

  //imshow("前景训练结果", mask);


  //循环显示每一帧

  while (true)

  {


    //读取当前帧

    capture >> frame;

    //若视频播放完成,退出循环

    if (frame.empty())

    {

      break;

    }

    frame.copyTo(result);

    //cvtColor(frame, frame, COLOR_GRAY2BGR);

    bgsubtractor->apply(frame, mask, 0.2);


    imshow("原视频", frame);  //显示当前帧

    //waitKey(30);  //延时30ms


    imshow("混合高斯建模", mask);

    //waitKey(30);


    //cvtColor(mask, mask, COLOR_GRAY2BGR);

    //对前景先进行中值滤波,再进行形态学膨胀操作,以去除伪目标和连接断开的小目标

    medianBlur(mask, mask, 5);

    //morphologyEx(mask, mask, MORPH_DILATE, getStructuringElement(MORPH_RECT, Size(5, 5)));


    //测试:先开运算再闭运算

    morphologyEx(mask, mask, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(5, 5)));

    morphologyEx(mask, mask, MORPH_OPEN, getStructuringElement(MORPH_RECT, Size(5, 5)));


    imshow("混合高斯建模", mask);

    waitKey(30);


    //拷贝

    mask.copyTo(srcImage);


    //各联通分量的轮廓

    //外层vector的size代表了图像中轮廓的个数,里面vector的 size代表了轮廓上点的个数

    vector<vector<Point>> contours;

    //只获取最外轮廓,获取每个轮廓的每个像素,并相邻两个像素位置差不超过1

    findContours(srcImage, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);


    //测试轮廓获取

    imshow("轮廓获取", srcImage);


    if (contours.size() < 1) continue;

    //外接矩阵

    Rect rct;


    //对轮廓进行外接矩阵之前先对轮廓按面积降序排序,目的为了去除小目标(伪目标)

    sort(contours.begin(), contours.end(), descSort);


    for (int i = 0; i < contours.size(); i++)

    {

      //当第i个连通分量的外接矩阵面积小于最大面积的1/6,则认为是伪目标

      if (contourArea(contours[i]) < contourArea(contours[0]) / 5)

        break;

      //包含轮廓的最小矩阵

      rct = boundingRect(contours[i]);

      rectangle(result, rct, Scalar(0, 255, 0), 2);


    }

    imshow("结果", result);

  }

  getchar();

  return 0;

}


参考

http://blog.csdn.net/xfgryujk/article/details/61421763