#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. 模板, 保存&发布

    单击“视图”菜单中的“幻灯片模板”按钮,会弹出“幻灯片母版”选项卡,在此选项卡中,可以修改当前PPT的模板, 例如网上下载的幻灯片上的LOGO都可在这里去除. 模板设计总结 1. 背景可以选择纯色,也 ...

  2. Java知多少(32)instanceof

    多态性带来了一个问题,就是如何判断一个变量所实际引用的对象的类型 . C++使用runtime-type information(RTTI),Java 使用 instanceof 操作符. insta ...

  3. Oracle Enterprise Linux 6.4 下挂载ISCSI 设备

    Oracle Enterprise Linux 6.4 下挂载ISCSI 设备一.发现① 要求安装iscsi客户端软件   yum install iscsi-initiator-utils ② 发现 ...

  4. Git服务器环境搭建(打造属于自己的存储库)

    Git服务器搭建之CentOs7-阿里云搭建 首先使用连接工具连接到远程的阿里云服务器CentOs7上. 1.安装Git及创建用户 # 安装Git $ yum install git # 创建一个gi ...

  5. HTML jQuery实现的expend row

    问 题:今天接到个任务,在一个老的系统页面里实现可展开的表格行. 寻找: 1.首先想到了在easyUI里见过的expand row form: 2.但是我们的老系统管理只有jQuery,如果使用eas ...

  6. C#WinForm应用程序中嵌入ECharts图表

    C#WinForm应用程序中嵌入ECharts图表 程序运行效果: 下载ECharts: 官网下载ECharts :http://echarts.baidu.com/download.html 或者直 ...

  7. Sciter返回json

    sciter::value arr[200]; for (int i = 0; i < (int)m_fileList.size(); i++) { cv::Mat img = cv::imre ...

  8. callback 模式

    回调,是一种机制,同时也是一种设计模式. 我们定义一个函数,让能够回调 import _products from './products.json' const TIMEOUT = 100 cons ...

  9. db2pd工具

    内容 概览 简介 使用 db2pd 工具 监控的例子 db2pd 工具 用于监控 DB2 实例和数据库的新的 DB2 UDB 工具 简介 DB2 UDB V8.2 带来了一种新工具称为 db2pd,用 ...

  10. cc2640 细节展示

    1. 对于 cc2640内部有两个单片机,一个m3负责内核,另一个是一个16位单片机,应该是msp430可以替代主机完成一些数据采集,adc采集,iic等等功能,传感器软件内部可以进行外设配置,并使用 ...