天天看點

cvBlob 使用

注意事項

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

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

  //循環顯示每一幀

    //讀取目前幀

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

    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)

      //包含輪廓的最小矩陣

      rct = boundingRect(contours[i]);

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

    imshow("結果", result);

  getchar();

參考

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

     本文轉自fengyuzaitu 51CTO部落格,原文連結:http://blog.51cto.com/fengyuzaitu/1637984,如需轉載請自行聯系原作者