基于opencv3.0下的运动车辆识别
在opencv的初等应用上,对运动物体的识别主要有帧差或背景差两种方式。
帧差法主要的原理是当前帧与前一帧作差取绝对值;
背景差主要的原理是当前帧与背景帧作差取绝对值;
在识别运动车辆上主要需要以下9个步骤:
(1)读取帧(VideoCapture,Mat)
(2)ROI选定(Rect)
(3)平滑处理(GaussianBlur)
(4)灰度处理(cvtColor,CV_RGB2GRAY)
(5)帧差或背景差(absdiff)
(6)二值化(threshold)
(7)膨胀(dilate)
(8)腐蚀(erode)
(9)绘制运动车辆(findContours,rectangle)
(1)读取帧(外部视频读取:Videocapture;帧读取:Mat)
这个属于比较基础的内容这里不做解释,直接附上源码:
/******************************************************
函数名称: MyClass
函数功能: 初始化
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
MyClass::MyClass()
{
//capture.open("F:/code/vsc++/Car_Find/Car_Find/交大七公里交通监控.avi");
capture.open("交大七公里交通监控.avi");
//capture = 0;
if (!capture.isOpened())//判断是否打开视频文件
{
exit();
}
FPS = capture.get(CV_CAP_PROP_FPS);
}
/******************************************************
函数名称: ~MyClass
函数功能: 释放空间
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
MyClass::~MyClass()
{
capture.release();
}
/******************************************************
函数名称: play
函数功能: 播放法
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void MyClass::play(){
Mat frame;
namedWindow("播放界面按Esc退出", );
cvResizeWindow("播放界面按Esc退出", , );
while (true)
{
capture >> frame;
if (frame.empty())break;
imshow("播放界面按Esc退出", frame);
if (waitKey(1000.0 / FPS) == )//按原FPS显示
{
cout << "ESC退出!" << endl;
break;
}
}
}
处理结果:
(2)ROI选定(Rect)
这里使用Rect进行划ROI(感兴趣区域),画出一个矩阵的ROI。在这里最好的ROI是梯形(减少除了道路外的不必要的干扰)
这里提下做法:做一个灰度的mask(遮罩层),然后调整mask的形状大小。ps:感兴趣的可以做下。
(3)平滑处理(处理方法:GaussianBlur)
这里采用高斯平滑处理,在拍摄视频的时候会受到电流的干扰,但这个干扰时均匀存在的,所以采用高斯平滑处理可以去除电流的干扰。
方法很简单,源码如下:
/******************************************************
函数名称: getSmooth
函数功能: 平滑处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getSmooth(Mat frame)
{
Mat img;
GaussianBlur(frame, img, Size(, ),,);
return img;
}
处理结果:
(4)灰度处理(处理方法:cvtColor;核:CV_RGB2GRAY)
RGB的图对我们的识别会造成一定的干扰或者说增加处理的难度,这里将原帧转换为灰度图像;
在平滑处理 后,直接调用opencv的cvtColor方法:
/******************************************************
函数名称: getGray
函数功能: 灰度处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getGray(Mat frame)
{
Mat img;
cvtColor(frame, img, CV_RGB2GRAY);
return img;
}
处理结果:
(5)帧差或背景差(处理方法:absdiff)
不管是帧差和背景差都是需要获取当前帧跟对比帧,其中对比帧的获取和帧的作差是处理的关键。
在获取到处理好的灰度图在进行帧差处理。
以下为对比帧的获取 的源码:
/******************************************************
函数名称: play
函数功能: 播放帧差法
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
void MyClass::play(){
Mat frame,preframe,curframe,result;
namedWindow("播放界面按Esc退出", );
//cvResizeWindow("播放界面按Esc退出", 600, 500);
while (true)
{
capture >> frame;
if (frame.empty())break;
if (preframe.empty())preframe = frame.clone();//首帧处理
curframe = frame.clone();
imshow("播放界面按Esc退出", frame);
if (waitKey(1000.0 / FPS) == )//按原FPS显示
{
cout << "ESC退出!" << endl;
break;
}
preframe = frame.clone();//记录当前帧为下一帧的前帧
}
}
以下为帧差处理的源码:
/******************************************************
函数名称: getDiff
函数功能: 帧差化处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getDiff(Mat preframe,Mat frame)
{
Mat img;
absdiff(preframe, frame, img);
return img;
}
处理结果:
这里一个车的灰度轮廓已经可以识别出来了,但是我们的目的是将车辆的轮廓识别处理,为了更加精准,去除不必要的干扰,需要下面的处理。
(6)二值化(处理方法:threshold,阈值类型:CV_THRESH_BINARY)
Threshold函数详解,其中CV_THRESH_BINARY:当前点值大于阈值时,取Maxval,也就是第四个参数,下面再不说明,否则设置为0
由于这些车辆原画偏暗,这里设定阈值为30,处理当前点值大于阈值时,取白色255。
源码如下:
/******************************************************
函数名称: getEz
函数功能: 二值化处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getEz(Mat frame)
{
Mat img;
threshold(frame, img,, , CV_THRESH_BINARY);
return img;
}
处理结果:
车的黑白轮廓已经显示出来了,不过这里还不是一块整体,所以需要进行膨胀处理。
ps:有些博文的处理方式是先腐蚀处理后膨胀处理,这个在一定程度上会消除干扰点。但是这里考虑到车辆中有摩托车,如果先腐蚀处理的话会将摩托车给消除掉,造成识别精度不高。
(7)膨胀(处理方法:dilate)
膨胀的目的在于将一辆车拼合成一块完整的个体,以达到标识的目的
opencv提供了dilate的方法进行处理,源码如下:
/******************************************************
函数名称: getPz
函数功能: 膨胀处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getPz(Mat frame)
{
Mat img;
Mat element=getStructuringElement(MORPH_RECT, Size(, ));
dilate(frame, img, element);
return img;
}
处理结果:
这时候已经合成一块了,但是如果旁边的车靠的太近的话,会导致多辆车黏合成一块,所以下面做腐蚀处理。
(8)腐蚀(处理方法:erode)
腐蚀的目的在于将因为膨胀而导致的黏合,还有非关键点和区域的清除,以达到区分标识的目的。
opencv提供了erode的方法进行处理,源码如下:
/******************************************************
函数名称: getFs
函数功能: 腐蚀处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::getFs(Mat frame)
{
Mat img;
Mat element = getStructuringElement(MORPH_RECT, Size(, ));
erode(frame, img, element);
return img;
}
处理结果:
ps:这里截的图不是很好,看不出效果分离的效果。感兴趣的可以下载下源码去调试。
(9)绘制运动车辆(处理方法:findContours,rectangle)
这里需要将车辆的外围轮廓描绘出来即可,所以findContours采用
mode取值“CV_RETR_EXTERNAL”,method取值“CV_CHAIN_APPROX_NONE”,即只检测最外层轮廓,并且保存轮廓上所有点;
rectangle的使用并不难,但是这里要注意的是:
a.处理的图像是原图像的ROI;
b.findContours输出的是处理过图像的坐标位置
所以在使用rectangle的时候,画区域的时候要加上原来ROI的起始位置的坐标,改成原来图像的坐标位置。
源码如下:
/******************************************************
函数名称: Deal
函数功能: ROI区域处理
传入参数:
返 回 值:
建立时间: 2018-05-17
修改时间:
建 立 人:
修 改 人:
其它说明:
******************************************************/
Mat MyClass::Deal(Mat preframe, Mat frame)
{
Mat result = frame.clone();
Mat curimageROI = preframe(Rect(preframe.cols / , preframe.rows / , preframe.cols / 1.5, preframe.rows / 1.5));
Mat preimageROI = frame(Rect(frame.cols / , frame.rows / , frame.cols / 1.5, frame.rows / 1.5)); Mat sm_pre, sm_cur;
sm_pre = getSmooth(preimageROI);
sm_cur = getSmooth(curimageROI);
imshow("平滑处理", sm_cur); Mat gray_pre, gray_cur;
gray_pre = getGray(sm_pre);
gray_cur = getGray(sm_cur);
imshow("灰度处理",gray_cur); Mat diff;
diff = getDiff(gray_pre, gray_cur);
imshow("帧差处理",diff); Mat ez;
ez = getEz(diff);
imshow("二值化处理", ez); Mat pz;
pz = getPz(ez);
imshow("膨胀处理", pz); Mat fs;
fs = getFs(pz);
imshow("腐蚀处理", fs); vector<vector<Point> > contours;
findContours(fs, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size());
for (int i = ; i < contours.size(); i++)
{
boundRect[i] = boundingRect(contours[i]);
rectangle(result, Rect(boundRect[i].x + frame.cols/, boundRect[i].y + frame.rows/, boundRect[i].width, boundRect[i].height), Scalar(, , ), );//在result上绘制正外接矩形
}
return result;
}
处理结果:
这里效果不是非常好可以勉强识别出车辆轮廓。但作为初级应用是足够的。
如需要源码请转移至码云:https://gitee.com/cjqbaba/MediaTest/tree/Car_Find进行源码克隆下载
如有问题请留言评论。转载请注明出处,谢谢。
基于opencv3.0下的运动车辆识别的更多相关文章
- 基于opencv3.0下的人脸检测和检测部分的高斯模糊处理
如题 这里将任务分解为三大部分: 1.录播放视频 2.人脸检测 3.部分高斯模糊 其中重点放在人脸检测和部分高斯模糊上 1.录播放视频(以opencv中的VideoCapture类进行实现) 首先罗列 ...
- 基于opencv3.0和下的条形码与二维码识别
其中对条码与二维码的识别分为以下4个步骤 1. 利用opencv和Zbar(或者Zxing)对标准的条形码图片(即没有多余背景干扰,且图片没有倾斜)进行解码,将解码信息显示出来,并与原始信息对比. 2 ...
- 【OpenCV】opencv3.0中的SVM训练 mnist 手写字体识别
前言: SVM(支持向量机)一种训练分类器的学习方法 mnist 是一个手写字体图像数据库,训练样本有60000个,测试样本有10000个 LibSVM 一个常用的SVM框架 OpenCV3.0 中的 ...
- ubuntu14.04下安装cudnn5.1.3,opencv3.0,编译caffe及配置matlab和python接口过程记录
已有条件: ubuntu14.04+cuda7.5+anaconda2(即python2.7)+matlabR2014a 上述已经装好了,开始搭建caffe环境. 1. 装cudnn5.1.3,参照: ...
- ubuntu14.04下配置使用openCV3.0
[操 作 系 统] Ubuntu 14.04 LTS [OpenCV版本] 3.0.0-beta [Eclipse 版 本] 3.8.1 需要知识: Linux系统shell命令基础 编译原理 ...
- windows下配置caffe(环境:win7+vs2013+opencv3.0)
说明:大部分转载于initialneil的大作Caffe + vs2013 + OpenCV in Windows Tutorial (I) – Setup 准备工作: 1.下载CUDA7.5: ht ...
- 在CUDA8.0下编译安装OpenCV3.1.0来实现GPU加速(Compiling OpenCV3.1.0 with CUDA8.0 support)
在CUDA8.0下编译安装OpenCV3.1.0 一.本人电脑配置:ubuntu 14.04, NVIDIA GTX1060. 二.编译OpenCV3.1.0前,读者需要成功安装CUDA8.0(网上有 ...
- 在win10下给vs2013配置opencv3.0
opencv这玩意是真难搞呀. 先吐槽下..... 下面进入正文. 1准备工具: opencv3.0+vs2013 这里面不提供链接下载,自行谷歌百度. 2配置环境: a.打开下载好的opencv(解 ...
- 在已配置成功的opencv3.2.0下配置opencv_contrib模块
简介: 之前在Ubuntu下配置OpenCV时,因为对opencv3..0不是特别了解,没有把opencv_contrib进行安装,这里提醒大家尽量要一次性安装完毕,减少不必要的麻烦. .0文件夹 ( ...
随机推荐
- C# 操作Excel数据透视表
一.概述 数据透视表(Pivot Table)是一种交互式的表,可以进行某些计算,如求和与计数等,可动态地改变透视表版面布置,也可以重新安排行号.列标和页字段.当改变版面布置时,数据透视表也会按照新的 ...
- Sublime Text3激活
Sublime Text 3激活 最近Sublime Text3总是自动将激活码移除,查了下解决办如下: 首先.修改hosts文件,路径位:C:\Windows\System32\drivers\et ...
- python 3下基于select模型的事件驱动机制程序
它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程.它的流程如图: 当用户进程调用了select,那么整个 ...
- java常用数据库连接池 (DBCP、c3p0、Druid) 配置说明
1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据库 ...
- happens-before规则和指令重排
...
- 6.3 Query 语句对系统性能的影响
我们重点分析实现同样功能的不同SQL 语句在性能方面会产生较大的差异的根本原因,并通过一个较为典型的示例来对我们的分析做出相应的验证. 为什么返回完全相同结果集的不同SQL 语句,在执行性能方面存在差 ...
- 手把手教你用Jenkins自动发布dotnet core程序
Jenkins部分 首先,我们要有个Jenkins咯,下载链接:https://jenkins.io/download/ 我们安装官网教程安装好jenkins,安装教程略.... 嗯?不是说好手把手么 ...
- FFPLAY的原理(三)
播放声音 现在我们要来播放声音.SDL也为我们准备了输出声音的方法.函数SDL_OpenAudio()本身就是用来打开声音设备的.它使用一个叫做SDL_AudioSpec结构体作为参数,这个结构体中包 ...
- Jmeter(二十七)_Beanshell保存响应内容到本地
利用Jmeter-BeanShell PostProcessor可以提取响应结果并保存到本地文件,这种操作在jmeter做爬虫时非常有用,可以帮助你迅速的获取想要的内容到本地文件! 1:在本地新建一个 ...
- 解决ExtJs Uncaught TypeError: c is not a constructor错误
ExtJs项目使用sencha app build编译以后,浏览时很容易抛出Uncaught TypeError: c is not a constructor的错误,而且会加载没有名称的js,例如 ...