#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 ;
}

最新文章

  1. Eclipse汉化后怎么改回英文版(可切换中英文)
  2. SQL Server里强制参数化的痛苦
  3. JMeter学习(六)集合点
  4. snmp getTable demo :iftable ipAddresstable
  5. ImageView的Scaletype
  6. iOS 语音识别使用讯飞报错
  7. ASP.NET Core MVC – 自定义 Tag Helpers
  8. Eclipse注释模板设置方法
  9. [51nod1232]完美数
  10. python面试题整合
  11. 转-C语言中.h和.c文件解析
  12. webpack Cannot find module &#39;webpack/schemas/WebpackOptions.json&#39;
  13. cad.net DeepCloneObjects WasErased
  14. Linux - 执行命令与脚本
  15. Laravel项目October安装
  16. cassandra java 兼容性问题及其解决方法
  17. Oracle用户密码过期的处理方法
  18. Bogart gFunction.vb
  19. java fastjson 设置全局输出name最小化
  20. jquery 常用工具方法

热门文章

  1. VMware 虚拟机安装OSX el capitan 11.12
  2. 【转】搭建Java版WebService
  3. [原]OpenGL基础教程(一)多边形绘制
  4. [IR] Arithmetic Coding
  5. [OpenCV] Samples 18: Load image and check its attributes
  6. akka cluster 初体验
  7. 【Vue】转-Vue.js经典开源项目汇总
  8. 【JavaScript】--- ES6/ES7/ES8
  9. lombok安装方法
  10. InputStream只能读取一次的解决办法 C# byte[] 和Stream转换