#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车流量统计算法的更多相关文章

  1. 基于OpenCV的KNN算法实现手写数字识别

    基于OpenCV的KNN算法实现手写数字识别 一.数据预处理 # 导入所需模块 import cv2 import numpy as np import matplotlib.pyplot as pl ...

  2. OpenCV实现KNN算法

    原文 OpenCV实现KNN算法 K Nearest Neighbors 这个算法首先贮藏所有的训练样本,然后通过分析(包括选举,计算加权和等方式)一个新样本周围K个最近邻以给出该样本的相应值.这种方 ...

  3. java 在centos6.5+eclipse环境下调用opencv实现sift算法

    java 在centos6.5+eclipse环境下调用opencv实现sift算法,代码如下: import org.opencv.core.Core; import org.opencv.core ...

  4. 基于FPGA的HDTV视频图像灰度直方图统计算法设计

    随着HDTV的普及,以LCD-TV为主的高清数字电视逐渐进入蓬勃发展时期.与传统CRT电视不同的是,这些高清数字电视需要较复杂的视频处理电路来驱动,比如:模数转换(A/D Converter).去隔行 ...

  5. OPENCV下SIFT算法使用方法笔记

    这几天继续在看Lowe大神的SIFT神作,看的眼花手脚抽筋.也是醉了!!!!实在看不下去,来点干货.我们知道opencv下自带SIFT特征检测以及MATCH匹配的库,这些库完全可以让我们进行傻瓜似的操 ...

  6. 用OpenCV实现Photoshop算法(三): 曲线调整

    http://blog.csdn.net/c80486/article/details/52499919 系列文章: 用OpenCV实现Photoshop算法(一): 图像旋转 用OpenCV实现Ph ...

  7. OpenCV中Camshitf算法学习(补充)

    结合OpenCV中Camshitf算法学习,做一些简单的补充,包括: 实现全自动跟随的一种方法 参考opencv中的相关demo,可以截取目标物体的图片,由此预先计算出其色彩投影图,用于实际的目标跟随 ...

  8. SEO 统计算法

    1)简单粗暴型的,这里不用去管浏览器的user-agent,不管cookie等信息,每产生一次PV,就直接计数,优点:简单,缺点:可能不真实,也可能有刷量数据 2) 稍微细腻点的统计,会区分新老用户, ...

  9. OpenCV: Canny边缘检测算法原理及其VC实现详解(转载)

    原文地址:http://blog.csdn.net/likezhaobin/article/details/6892176 原文地址:http://blog.csdn.net/likezhaobin/ ...

随机推荐

  1. visio操作

    1.上下标:选中要成为上标的文字,ctrl+shift+"=" 选中要成为下标的文字,ctrl+"="

  2. unable to locate package gparted

    在unbuntu安装gparted的时候出现这个错误提示,意思为:找不到这个安装包 可能的原因: 1.当前系统更新包没有更新,执行命令:sudo apt-get update 2.命令错误,重新检查需 ...

  3. 第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置

    第三百九十八节,Django+Xadmin打造上线标准的在线教育平台—生产环境部署CentOS6.5系统环境设置 1.Linux安装配置 注意事项: 虚拟机网卡桥接模式 不要拨VPN 如果,网络怎么都 ...

  4. Android Demos

    SDK Manager   下载demo后,可以到SDK目录下面找 例如 C:\Program Files (x86)\Java\adt-bundle-windows-x86\sdk\samples\ ...

  5. Android_照相机Camera_调用系统照相机返回data为空

    本博文为子墨原创,转载请注明出处! http://blog.csdn.net/zimo2013/article/details/16916279 1.调用系统照相机 [java] view plain ...

  6. day_5.21 py 高级编程

    1.禁止模块之间的循环调用 2.浅拷贝    只拷贝引用!!\ 3. 深拷贝  只要里面有引用就继续拷贝 4.copy,copy() 5. '''2018-5-21 11:39:52就业班 py高级 ...

  7. 可访问性(Accessibility) => 无障碍功能

    了解无障碍功能及其范围和影响可令您成为更出色的网络开发者 复杂的一笔 https://developers.google.cn/web/fundamentals/accessibility/ ARIA ...

  8. Java基础语法<八> 继承 多态 抽象 反射

    1.超类和子类 超类和子类 父类与子类 多态: 一个对象变量可以指示多种实际类型的现象称为多态 一个变量可以引用父类对象,也可以引用其子类对象,这就是多态. 不能将一个超类的引用赋给子类变量,因为调用 ...

  9. 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" ...

  10. 转发一篇好文:36氪翻译自medium的文章: 读书没有 KPI:为什么坚持“一年读 100 本书”没用?

    你只是为了达成所谓的数量目标而读书. 编者按:读书本是一项安静.缓慢的活动,但随着现代社会节奏的加快,信息技术的广泛普及,读书这一行为模式也开始发生了变化.越来越多的人开始碎片化阅读,并且越来越多的文 ...