opencv车流量统计算法
#include "cv.h"
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>//必须引此头文件
#include "opencv2/imgproc/imgproc.hpp"
typedef uchar byte;
#define QUEUE_MAX_SIZE 100
#define RANGE 5
#define UPDATE_RATE (0.01)
#define RATIO_QUEUE_LEN 1000
typedef unsigned int uint32;
#define MIN(x,y) (x>y?y:x) int g_QueueSize=;
int threshold=;
int g_CarWidth=;//车的宽和高
int g_CarHeight=;
int g_CarArea=;//检测的范围
int g_Erosion_kernel_size=;
int g_Dilation_kernel_size=;
struct PIXEL_RECORD
{
byte PX_data;
uint32 PX_count;
}; struct QUEUE
{
struct RECORD
{
double ratio;
uint64 count;
}record [RATIO_QUEUE_LEN]; int curPos;
double MostRatio; };
struct RECORD
{
PIXEL_RECORD queue[QUEUE_MAX_SIZE];
uint32 CurPos;//the postion of last element in queue; }; void QUEUE_init(QUEUE* queue)
{
for (int i=;i<RATIO_QUEUE_LEN;i++)
{
queue->record[i].ratio=0.0;
queue->record[i].count=; }
queue->curPos=;
queue->MostRatio=0.0;
}
double UpatePixelRatio(QUEUE& queue,double ratio)
{ int i=;
int MinPos=;
int MaxPos=;
for (;i<RATIO_QUEUE_LEN;i++)
{
if(queue.record[i].ratio == ratio)
{
queue.record[i].count++;
break;
} }
if (i==RATIO_QUEUE_LEN)
{
if(queue.curPos<RATIO_QUEUE_LEN)
{
queue.record[queue.curPos++].ratio=ratio;
}
if(queue.curPos== RATIO_QUEUE_LEN)
{
uint32 MinCount=0xFFFFFFFF;
for(int j=;j<queue.curPos;j++)
{
if(queue.record[j].count<MinCount)
{
MinPos=j;
MinCount=queue.record[j].count;
}
}
queue.record[MinPos].ratio=ratio;
}
}
uint32 MaxCount=;
for (int j=;j<RATIO_QUEUE_LEN;j++)
{
if (queue.record[j].count>MaxCount)
{
MaxCount=queue.record[j].count;
MaxPos=j;
}
}
return queue.record[MaxPos].ratio;
}
uint32 GetMaxValueData(const PIXEL_RECORD* arr,int len)
{
uint32 tmp=;
uint32 MaxPos=;
for (int i=;i<len-;i++)
{
if(arr[i].PX_count>tmp)
{
tmp=arr[i].PX_count;
MaxPos=i;
}
}
return arr[MaxPos].PX_data;
} uint32 GetMinValuePos(const PIXEL_RECORD* arr,int len)
{
byte tmp=;
uint32 MinPos=g_QueueSize;
for (int i=;i<len-;i++)
{
if(arr[i].PX_count<tmp)
{
tmp=arr[i].PX_count;
MinPos=i;
}
}
return MinPos;
} byte UpdateQueue(RECORD* record,byte Vpixel,uint32 nFrm)
{
PIXEL_RECORD tmp;
int i=;
double UpdateRate;
for (;i<g_QueueSize;i++)
{ if ((record->queue[i].PX_data)/RANGE == Vpixel/RANGE )
{
record->queue[i].PX_count++;
record->queue[i].PX_data=(record->queue[i].PX_data)*(-UPDATE_RATE)+Vpixel*UPDATE_RATE; }
}
if (i==g_QueueSize)
{
if (record->CurPos < g_QueueSize)
{
record->queue[record->CurPos++].PX_data=Vpixel;
}
else
{
uint32 Pos=GetMinValuePos(record->queue,record->CurPos);
record->queue[Pos].PX_data=Vpixel;
} }
return GetMaxValueData(record->queue,record->CurPos);
} void RecordFrame(IplImage* pFrame,IplImage* pBKImg ,const int nFrm,RECORD* pRecordMap,QUEUE& PX_queue)
{
IplImage* pFrmGrayImg=NULL;
pFrmGrayImg=cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,);
if(pFrame->colorModel != CV_8U && pFrame->nChannels != )
{
cvCvtColor(pFrame,pFrmGrayImg,CV_BGR2GRAY);
}
else
pFrmGrayImg=pFrame; uint32 ROW=pFrmGrayImg->width;
uint32 COL=pFrmGrayImg->height; for (uint32 i=;i<ROW*COL;i++)
{
pBKImg->imageData[i]=UpdateQueue(pRecordMap+i,pFrmGrayImg->imageData[i], nFrm); } } void TouchTag(int* buf,int ROW,int COL,int& ctag,int x,int y)
{
int tag=ctag;
bool mark=;
for (int i=-;i<;i++)
{ for (int j=-;j<;j++)
{ if (buf[(x+i)*COL+(y+j)]>)
{
tag= MIN(buf[(x+i)*COL+(y+j)],tag);
mark=;
}
}
}
if(mark==)
{
ctag++;
tag=ctag;
}
buf[x*COL+y]=tag;
} size_t DetectRect(CvMat* Img,int* buf)
{
uint32 ROW=Img->rows;
uint32 COL=Img->cols;
int cTag=;
for (int i=;i<ROW -;i++)//! 图像中的横轴为X轴,即为列坐标
{
for (int j=;j<COL-;j++)
{
if(*(byte*)(CV_MAT_ELEM_PTR(*Img,i,j)) == )
{
TouchTag(buf,ROW,COL,cTag,i,j);
}
}
} return cTag;
} struct TAG_RECORD
{
uint32 MinX;
uint32 MaxX;
uint32 MinY;
uint32 MaxY;
uint32 count;
};
void GetRect(std::vector<TAG_RECORD>& TagArry,size_t cTag,int* buf,uint32 ROW,uint32 COL)
{
for (size_t i=;i<TagArry.size();i++)
{
TagArry[i].MaxX=;
TagArry[i].MaxY=;
TagArry[i].MinX=COL;
TagArry[i].MinY=ROW;
TagArry[i].count=;
}
int index=;
for (int i=;i<ROW;i++)
{
for (int j=;j<COL;j++)
{
index=buf[i*COL+j];
if (index> && index<TagArry.size())
{
TagArry[index].count++;
if (i<TagArry[index].MinY)
{
TagArry[index].MinY=i;
}
if(i>TagArry[index].MaxY)
{
TagArry[index].MaxY=i;
}
if (j<TagArry[index].MinX)
{
TagArry[index].MinX=j;
}
if (j>TagArry[index].MaxX)
{
TagArry[index].MaxX=j;
}
} }
} } void onTrackbarSlide(int)
{ }
int main()
{ //声明IplImage指针
IplImage* pFrame = NULL;
IplImage* pFrImg = NULL;
IplImage* pBkImg = NULL;
CvMat* pDiff =NULL;
CvMat* pFrameMat = NULL;
CvMat* pFrMat = NULL;
CvMat* pBkMat = NULL;
RECORD* pRecordMap=NULL;
int* TagMap=NULL;
CvCapture* pCapture = NULL;
CvRect FrRect;
int nFrmNum = ;
int ncount=;
QUEUE PX_queue;
size_t RecordSize;
int ROW;
int COL;
//! 文字输出
CvFont font;
char str[]="flow:";
double hscale = 0.6;
double vscale = 0.6;
int linewidth = ;
double flow;
char ncar[]="cars:";
char nframe[]="frames:";
char sframeRate[]="[FPS]:";
//创建窗口
cvNamedWindow("video", );
cvNamedWindow("background",);
cvNamedWindow("foreground",);
//使窗口有序排列
cvMoveWindow("video", , );
cvMoveWindow("background", , );
cvMoveWindow("foreground", , ); char* filename="d:\\test.mp4";
//打开视频文件 if( !(pCapture = cvCaptureFromFile(filename)))
{
fprintf(stderr, "Can not open video file %s\n", filename);
return -;
} QUEUE_init(&PX_queue); double framesRate=cvGetCaptureProperty(pCapture,CV_CAP_PROP_FPS);
int frames=cvGetCaptureProperty(pCapture,CV_CAP_PROP_FRAME_COUNT); cvCreateTrackbar("QueueSize","background", &g_QueueSize, QUEUE_MAX_SIZE,onTrackbarSlide);
cvCreateTrackbar("CarWiedth","video", &g_CarWidth, ,onTrackbarSlide);
cvCreateTrackbar("CarHeight","video", &g_CarHeight, ,onTrackbarSlide);
cvCreateTrackbar("CarArea","video", &g_CarArea, ,onTrackbarSlide);
cvCreateTrackbar("Threshold","foreground", &threshold, ,onTrackbarSlide);
cvCreateTrackbar("dilate","foreground", &g_Dilation_kernel_size, ,onTrackbarSlide);
cvCreateTrackbar("erode","foreground", &g_Erosion_kernel_size, ,onTrackbarSlide);
//逐帧读取视频
while(pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++; //如果是第一帧,需要申请内存,并初始化
if(nFrmNum == )
{ pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,);
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,);
pDiff =cvCreateMat(pFrame->height, pFrame->width, CV_8U);
pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
ROW=pDiff->rows;
COL=pDiff->cols;
//转化成单通道图像再处理
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
RecordSize=pFrame->width * pFrame->height;
pRecordMap=new RECORD[RecordSize];
TagMap=new int[RecordSize]; for (int i=;i<RecordSize;i++) //init
{
for (int j=;j<g_QueueSize;j++)
{ pRecordMap[i].queue[j].PX_count=;
pRecordMap[i].queue[j].PX_data=;
pRecordMap[i].CurPos=;
}
} cvConvert(pFrImg, pFrameMat);
cvConvert(pBkImg, pBkMat); }
else
{ cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvSmooth(pFrImg, pFrImg, CV_GAUSSIAN, , , ); RecordFrame(pFrImg,pBkImg,nFrmNum,pRecordMap,PX_queue); //高斯滤波先,以平滑图像
cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, , , ); //当前帧跟背景图相减
cvAbsDiff(pFrImg, pBkImg, pDiff); //二值化前景图
cvThreshold(pDiff, pDiff, threshold, , CV_THRESH_BINARY);
//进行形态学滤波,去掉噪音 IplConvKernel* element_erode=cvCreateStructuringElementEx(g_Erosion_kernel_size + , g_Erosion_kernel_size+,
g_Erosion_kernel_size/, g_Erosion_kernel_size/, ); IplConvKernel* element_dilate = cvCreateStructuringElementEx(g_Dilation_kernel_size + , g_Dilation_kernel_size+,
g_Dilation_kernel_size/, g_Dilation_kernel_size/, ); //! 腐蚀操作
cvErode( pDiff, pDiff, element_erode ); /// 膨胀操作
cvDilate( pDiff, pDiff, element_dilate ); // cvErode(pDiff, pDiff, 0, 1);
// cvDilate(pDiff, pDiff, 0, 1);
// for (int i=;i<RecordSize;i++)
{
TagMap[i]=;
} size_t cTag=DetectRect(pDiff,TagMap);
TAG_RECORD tmp; tmp.MinX=pDiff->cols;
tmp.MinY=pDiff->rows;
tmp.MaxX=;
tmp.MaxY=;
std::vector<TAG_RECORD> TagRecord(cTag+,tmp); GetRect(TagRecord,cTag,TagMap,pDiff->rows,pDiff->cols);
ncount=;
for (size_t i=;i<TagRecord.size();i++)
{ if (TagRecord[i].count<g_CarArea)
{
continue;
} int MinX=TagRecord[i].MinX;
int MinY=TagRecord[i].MinY;
int MaxX=TagRecord[i].MaxX;
int MaxY=TagRecord[i].MaxY; if (MaxX-MinX<g_CarWidth || MaxY-MinY<g_CarHeight)
{
continue; }
ncount++;
cvRectangle( pFrame, cvPoint(MinX,MinY), cvPoint(MaxX,MaxY), CV_RGB(,,), , , ); } flow=framesRate*ncount/(double)nFrmNum; sprintf(nframe+,"%d",nFrmNum);
sprintf(ncar+,"%d",ncount); sprintf(str+,"%f",flow);
sprintf(sframeRate+,"%f",framesRate); cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,hscale,vscale,,linewidth);
cvPutText(pFrame,sframeRate,cvPoint(,),&font,cvScalar(,,));
cvPutText(pFrame,ncar,cvPoint(,),&font,cvScalar(,,));
cvPutText(pFrame,nframe,cvPoint(,),&font,cvScalar(,,)); cvPutText(pFrame,str,cvPoint(,),&font,cvScalar(,,));
//显示图像
cvShowImage("video", pFrame);
cvShowImage("background", pBkImg);
cvShowImage("foreground", pDiff); //如果有按键事件,则跳出循环
//此等待也为cvShowImage函数提供时间完成显示
//等待时间可以根据CPU速度调整
if( cvWaitKey() >= )
break; } } cvWaitKey(); //销毁窗口
cvDestroyWindow("video");
cvDestroyWindow("background");
cvDestroyWindow("foreground"); //释放图像和矩阵
cvReleaseImage(&pFrImg);
cvReleaseImage(&pBkImg); cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrMat);
cvReleaseMat(&pBkMat); cvReleaseCapture(&pCapture);
delete[] pRecordMap;
delete[] TagMap;
return ;
}
opencv车流量统计算法的更多相关文章
- 基于OpenCV的KNN算法实现手写数字识别
基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...
- OpenCV实现KNN算法
原文 OpenCV实现KNN算法 K Nearest Neighbors 这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值.这种方 ...
- java 在centos6.5+eclipse环境下调用opencv实现sift算法
java 在centos6.5+eclipse环境下调用opencv实现sift算法,代码如下: import org.opencv.core.Core; import org.opencv.core ...
- 基于FPGA的HDTV视频图像灰度直方图统计算法设计
随着HDTV的普及,以LCD-TV为主的高清数字电视逐渐进入蓬勃发展时期.与传统CRT电视不同的是,这些高清数字电视需要较复杂的视频处理电路来驱动,比如:模数转换(A/D Converter).去隔行 ...
- OPENCV下SIFT算法使用方法笔记
这几天继续在看Lowe大神的SIFT神作,看的眼花手脚抽筋.也是醉了!!!!实在看不下去,来点干货.我们知道opencv下自带SIFT特征检测以及MATCH匹配的库,这些库完全可以让我们进行傻瓜似的操 ...
- 用OpenCV实现Photoshop算法(三): 曲线调整
http://blog.csdn.net/c80486/article/details/52499919 系列文章: 用OpenCV实现Photoshop算法(一): 图像旋转 用OpenCV实现Ph ...
- OpenCV中Camshitf算法学习(补充)
结合OpenCV中Camshitf算法学习,做一些简单的补充,包括: 实现全自动跟随的一种方法 参考opencv中的相关demo,可以截取目标物体的图片,由此预先计算出其色彩投影图,用于实际的目标跟随 ...
- SEO 统计算法
1)简单粗暴型的,这里不用去管浏览器的user-agent,不管cookie等信息,每产生一次PV,就直接计数,优点:简单,缺点:可能不真实,也可能有刷量数据 2) 稍微细腻点的统计,会区分新老用户, ...
- OpenCV: Canny边缘检测算法原理及其VC实现详解(转载)
原文地址:http://blog.csdn.net/likezhaobin/article/details/6892176 原文地址:http://blog.csdn.net/likezhaobin/ ...
随机推荐
- visio操作
1.上下标:选中要成为上标的文字,ctrl+shift+"=" 选中要成为下标的文字,ctrl+"="
- unable to locate package gparted
在unbuntu安装gparted的时候出现这个错误提示,意思为:找不到这个安装包 可能的原因: 1.当前系统更新包没有更新,执行命令:sudo apt-get update 2.命令错误,重新检查需 ...
- 第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置
第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置 1.Linux安装配置 注意事项: 虚拟机网卡桥接模式 不要拨VPN 如果,网络怎么都 ...
- Android Demos
SDK Manager 下载demo后,可以到SDK目录下面找 例如 C:\Program Files (x86)\Java\adt-bundle-windows-x86\sdk\samples\ ...
- Android_照相机Camera_调用系统照相机返回data为空
本博文为子墨原创,转载请注明出处! http://blog.csdn.net/zimo2013/article/details/16916279 1.调用系统照相机 [java] view plain ...
- day_5.21 py 高级编程
1.禁止模块之间的循环调用 2.浅拷贝 只拷贝引用!!\ 3. 深拷贝 只要里面有引用就继续拷贝 4.copy,copy() 5. '''2018-5-21 11:39:52就业班 py高级 ...
- 可访问性(Accessibility) => 无障碍功能
了解无障碍功能及其范围和影响可令您成为更出色的网络开发者 复杂的一笔 https://developers.google.cn/web/fundamentals/accessibility/ ARIA ...
- Java基础语法<八> 继承 多态 抽象 反射
1.超类和子类 超类和子类 父类与子类 多态: 一个对象变量可以指示多种实际类型的现象称为多态 一个变量可以引用父类对象,也可以引用其子类对象,这就是多态. 不能将一个超类的引用赋给子类变量,因为调用 ...
- Men and women can't be 'just friends
Men and women can't be 'just friends' Can heterosexual men and women ever be "just friends" ...
- 转发一篇好文:36氪翻译自medium的文章: 读书没有 KPI:为什么坚持“一年读 100 本书”没用?
你只是为了达成所谓的数量目标而读书. 编者按:读书本是一项安静.缓慢的活动,但随着现代社会节奏的加快,信息技术的广泛普及,读书这一行为模式也开始发生了变化.越来越多的人开始碎片化阅读,并且越来越多的文 ...