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



     本文转自fengyuzaitu 51CTO博客,原文链接:http://blog.51cto.com/fengyuzaitu/1637984,如需转载请自行联系原作者




相关文章
|
6月前
|
C++
std::string 不能跨dll的一种解决方法
std::string 不能跨dll的一种解决方法
|
缓存 openCL 算法
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
关于实现Halcon算法加速的基础知识(多核并行/GPU)
2573 0
关于实现Halcon算法加速的基础知识(2)(多核并行/GPU)
|
Windows
C#-利用自定义控件绘制一个箭头控件
利用自定义控件绘制一个箭头控件
527 0
关于Halcon C++常用的两种数据结构Hobject和HTuple
关于Halcon C++常用的两种数据结构Hobject和HTuple
1738 0
|
10天前
|
人工智能 自然语言处理 API
深入浅出LangChain与智能Agent:构建下一代AI助手
LangChain为大型语言模型提供了一种全新的搭建和集成方式,通过这个强大的框架,我们可以将复杂的技术任务简化,让创意和创新更加易于实现。本文从LangChain是什么到LangChain的实际案例到智能体的快速发展做了全面的讲解。
279571 55
深入浅出LangChain与智能Agent:构建下一代AI助手
|
4天前
|
机器人 Linux API
基于Ollama+AnythingLLM轻松打造本地大模型知识库
Ollama是开源工具,简化了在本地运行大型语言模型(ile优化模型运行,支持GPU使用和热加载。它轻量、易用,可在Mac和Linux上通过Docker快速部署。AnythingLLM是Mintplex Labs的文档聊天机器人,支持多用户、多种文档格式,提供对话和查询模式,内置向量数据库,可高效管理大模型和文档。它也是开源的,能与Ollama结合使用,提供安全、低成本的LLM体验。这两款工具旨在促进本地高效利用和管理LLMs。
139031 23
|
9天前
|
缓存 前端开发 JavaScript
年度代码翻车现场 |前端代码评审问题总结
代码评审于技术团队的工程师文化建设非常有意义,它是形成团队统一代码风格最有效的方式,作者把自己团队在一年的CR中常见的那些小问题做了一些梳理,希望能对大家起到一点小帮助。
219330 1
|
11天前
|
消息中间件 Cloud Native Serverless
RocketMQ 事件驱动:云时代的事件驱动有啥不同?
本文深入探讨了云时代 EDA 的新内涵及它在云时代再次流行的主要驱动力,包括技术驱动力和商业驱动力,随后重点介绍了 RocketMQ 5.0 推出的子产品 EventBridge,并通过几个云时代事件驱动的典型案例,进一步叙述了云时代事件驱动的常见场景和最佳实践。
246791 4