#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. c# 使用GDAL处理大图

    注意问题: 1.GDAL 使用官网生成好的dll,必须把Bin目录下的dll一并加到执行目录下去,否则会出错.  2. 用环境变量设置引用路径可以避免一大堆dll放一起.代码如下: /// <s ...

  2. Java知多少(73)文件的压缩处理

    Java.util.zip 包中提供了可对文件的压缩和解压缩进行处理的类,它们继承自字节流类OutputSteam 和 InputStream.其中 GZIPOutputStream 和 ZipOut ...

  3. ESN 与 MEID

    ESN (Electronic Serial Numbers):电子序列号.在CDMA 系统中,是鉴别一个物理硬件设备唯一的标识.也就是说每个手机都用这个唯一的ID来鉴别自己, 就跟人的身份证一样.一 ...

  4. TSPL学习笔记(1)

    扩展语法(Syntactic extensions) 扩展语法就是通过核心语法或已经定义的扩展语法创建一种新的语法模式. Scheme核心语法模式包括: 顶层定义 常量 变量 过程应用 '(quote ...

  5. redmine增加文本输入框默认格式

    需求:击一个按钮,在文本输入区域自动生成如下图的内容: 1. 详细描述: 2. 详细步骤: 3. 期望结果: 4. 实际结果: 实现过程: 1 打开文件\apps\redmine\public\jav ...

  6. 凭据管理 API

    api 有相应更新 https://www.chromestatus.com/features/4781762488041472 <!DOCTYPE html> <html> ...

  7. maven 配置mirror后,本地库与远端库冲突

    settings.xml中主要包括以下元素: localRepository interavtiveMode offline pluginGroups proxies servers mirrors ...

  8. .NET Core开发日志——Runtime IDentifier

    .NET Core对于传统.NET开发人员而言是既熟悉又陌生的新平台,所以有时遇上出乎意料的事情也纯属正常情况.这时只需点耐心,多查查资料,努力找到原因,也未尝不是件有意义的体验. 比如当建完一个最简 ...

  9. pl-svo代码解读

    pl-svo是在svo的基础上结合点和线特征的半直接法视觉里程计 程序启动通过app文件夹下的run_pipeline.cpp主程序启动,其它的函数文件统一放在src文件夹下,我们先从run_pipe ...

  10. gulp安装及使用流程

    1. 安装nodejs 去 https://nodejs.org/en/下载安装文件安装即可. 安装完成后,在终端输入node -v回车打印出nodejs的版本号,说明nodejs安装成功. 在终端输 ...