服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - opencv实现三帧差法解析

opencv实现三帧差法解析

2021-08-27 13:56xiao__run C/C++

这篇文章主要介绍了opencv实现三帧差法的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

今天和大家谈谈三帧差法来实现运动目标检测吧,其中运动检测画框实现追踪方法多种多样,大家可以自行百度,后面我也会一一实现,今天我先给大家玩玩三帧差法吧;;;;(注释非常清楚哦,程序也极其简单的)

帧差法是最为常用的运动目标检测和分割方法之一,基本原理就是在图像序列相邻两帧或三帧间采用基于像素的时间差分通过闭值化来提取出图像中的运动区域。首先,将相邻帧图像对应像素值相减得到差分图像,然后对差分图像二值化,在环境亮度变化不大的情况下,如果对应像素值变化小于事先确定的阂值时,可以认为此处为背景像素:如果图像区域的像素值变化很大,可以认为这是由于图像中运动物体引起的,将这些区域标记为前景像素,利用标记的像素区域可以确定运动目标在图像中的位置。由于相邻两帧间的时间间隔非常短,用前一帧图像作为当前帧的背景模型具有较好的实时性,其背景不积累,且更新速度快、算法简单、计算量小。算法的不足在于对环境噪声较为敏感,闽值的选择相当关键,选择过低不足以抑制图像中的噪声,过高则忽略了图像中有用的变化。对于比较大的、颜色一致的运动目标,有可能在目标内部产生空洞,无法完整地提取运动目标。

简单说一下程序思路哈,参考了一下opencv官网教程

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include<iostream>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
const unsigned char FORE_GROUD = 255;int thresh = 10;
int main(int argc,char*argv[])
{  
 VideoCapture video(argv[1]); //判断如果video是否可以打开
 if(!video.isOpened()) 
 return -1; 
 
//用于保存当前帧的图片
 
 Mat currentBGRFrame; 
//用来保存上一帧和当前帧的灰度图片
 Mat previousSecondGrayFrame; Mat previousFirstGrayFrame; Mat currentGaryFrame;
 //保存两次的帧差
Mat previousFrameDifference; //previousFrameFirst - previousFrameSecond的差分
Mat currentFrameDifference;  //currentFrame - previousFrameFirst;
 //用来保存帧差的绝对值
Mat absFrameDifferece;
//用来显示前景
 Mat previousSegmentation; Mat currentSegmentation; Mat segmentation;
 //显示前景
 namedWindow("segmentation",1);
 createTrackbar("阈值:","segmentation",&thresh,FORE_GROUD,NULL);
 //帧数
 int numberFrame = 0;
//形态学处理用到的算子
 Mat morphologyKernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1)); 
 for(;;)
 //读取当前帧 
 video >> currentBGRFrame; 
 //判断当前帧是否存在 
 if(!currentBGRFrame.data)  
 break;  
  numberFrame++; 
 //颜色空间的转换 
 cvtColor(currentBGRFrame,currentGaryFrame,COLOR_BGR2GRAY);  
 if( numberFrame == 1)  { 
 //保存当前帧的灰度图  
 previousSecondGrayFrame = currentGaryFrame.clone();   
  //显示视频 
 imshow("video",currentBGRFrame);   continue;  } 
 else if( numberFrame == 2) 
 {  
 //保存当前帧的灰度图 
  previousFirstGrayFrame = currentGaryFrame.clone();  
 //previousFirst - previousSecond  
 subtract(previousFirstGrayFrame,previousSecondGrayFrame,previousFrameDifference,Mat(),CV_16SC1);  
 //取绝对值  
 absFrameDifferece = abs(previousFrameDifference);     
 //位深的改变  
 absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0);  
 //阈值处理 
 threshold(absFrameDifferece,previousSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY);   
  //显示视频 
 imshow("video",currentBGRFrame);  
 continue;  } 
 else
 {  
 //src1-src2  
subtract(currentGaryFrame,previousFirstGrayFrame,currentFrameDifference,Mat(),CV_16SC1);   
   //取绝对值 
  absFrameDifferece = abs(currentFrameDifference);     
 //位深的改变   absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0);
   //阈值处理  
 threshold(absFrameDifferece,currentSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY);  //与运算  
 bitwise_and(previousSegmentation,currentSegmentation,segmentation);    //中值滤波  
medianBlur(segmentation,segmentation,3); //形态学处理(开闭运算)  
 //morphologyEx(segmentation,segmentation,MORPH_OPEN,morphologyKernel,Point(-1,-1),1,BORDER_REPLICATE);  
 morphologyEx(segmentation,segmentation,MORPH_CLOSE,morphologyKernel,Point(-1,-1),2,BORDER_REPLICATE);     
      //找边界  
 vector< vector<oint> > contours;  
 vector<Vec4i> hierarchy;  
 //复制segmentation 
  Mat tempSegmentation = segmentation.clone(); 
  findContours( segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );//CV_RETR_TREE 
  vector< vector<oint> > contours_poly( contours.size() );    
  /*存储运动物体*/  
  vector<Rect> boundRect;  
  boundRect.clear();     
 //画出运动物体  
 for(int index = 0;index < contours.size() ;index++)  
 {  
 approxPolyDP( Mat(contours[index]), contours_poly[index], 3, true );  
  Rect rect = boundingRect( Mat(contours_poly[index]) );   
 rectangle(currentBGRFrame,rect,Scalar(0,255,255),2);   } 
 //显示视频 
 imshow("video",currentBGRFrame);     
 //前景检测  
imshow("segmentation",segmentation);  
 //保存当前帧的灰度图  
 previousFirstGrayFrame = currentGaryFrame.clone();     
 //保存当前的前景检测  
 previousSegmentation = currentSegmentation.clone(); 
 }   
 if(waitKey(33) == 'q')  
 break;
 }
 return 0;
}

编译之后,运行./main.cpp **.avi

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/xiao__run/article/details/76832701

延伸 · 阅读

精彩推荐
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12