用opencv处理运动车辆跟踪和车辆计数问题

greyrainbow2010 2010-08-18 01:09:54
opencv1.0 + VC开发

现在已经将运动车辆用矩形框圈定

下一步要做跟踪和计数
请问哪位给点相关代码啊?

尤其是计数,一辆车子可能在视频帧里出现了20次,如何确定这辆车是开始计数的车子呢
否则的话会把一辆车子数个几十遍的,那就没意义了
...全文
1731 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
aalalalalalalala 2012-06-30
  • 打赏
  • 举报
回复
跪求,那个车流量计数问题解决了吗?有代码吗?能发给我一份吗?我的邮箱是593811052@qq.com,现在急需知道这个问题,。。感激不尽、、、
luowuxuesheng 2012-05-22
  • 打赏
  • 举报
回复
楼主,你的特征匹配算法完成了吗,可以发我一份吗,谢谢了。邮箱:zhao.yeah.net@163.com

特征匹配算法最好是基于框出来的中心点的
miaojing1103 2012-04-18
  • 打赏
  • 举报
回复
楼主好,那个车流量计数问题解决了吗?有代码吗?能发给我一份吗?我的邮箱是510989579@qq.com,现在急需知道这个问题,。。太感谢了、、、
tlnlove2011 2011-09-02
  • 打赏
  • 举报
回复
楼主 把那个圈起运606动目标的源码给我参考参考好吗 我弄了好几天了 邮箱是603349952@qq.com
ouyurong 2011-08-20
  • 打赏
  • 举报
回复
楼主,不知道现在你那个计数解决了吗?我现在也在做这方面的,如果解决的话,麻烦你把代码给我发发,让我看看,怎么样,谢谢了!!!我的QQ是316216054
yiyeshengge001 2011-05-06
  • 打赏
  • 举报
回复
小弟 也在研究 求帮解答
www_djh 2011-04-07
  • 打赏
  • 举报
回复
我也遇到这样的问题了
nbhx2010 2010-09-02
  • 打赏
  • 举报
回复
帮顶一下,我也想知道精度比较高的车流量统计算法
zhouguoyu2013 2010-08-26
  • 打赏
  • 举报
回复
顶,我也想知道
greyrainbow2010 2010-08-25
  • 打赏
  • 举报
回复
思路有,但是opencv不熟
所以写不出来
wgm001 2010-08-23
  • 打赏
  • 举报
回复
有点难度啊...
不过有思路就好写代码...
greyrainbow2010 2010-08-21
  • 打赏
  • 举报
回复
不过上述程序有问题啊,网上可以搜索到的就是这个了
但是TrackBlock就没定义,然后我自己定义了以后根本无法计数啊

有大牛解释一下吗?
Guassfans 2010-08-20
  • 打赏
  • 举报
回复
这个代码真没有,自己写个也不是难事既然有思路的话
greyrainbow2010 2010-08-20
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 m_tornado 的回复:]

代码到什么XX几百例的光盘里找吧~或者到资源看看~
[/Quote]


哪个光盘??没找到啊
CSDN的资源上也只找到检测和框跟踪,并没有车流量计数的资料
greyrainbow2010 2010-08-20
  • 打赏
  • 举报
回复
我网上抄了一段代码

//打开视频文件以及车辆跟踪和识别,按钮消息响应部分
void CTrackandIDDlg::OnStartTrackandID()
{
// TODO: Add your control notification handler code here
int argc=2;
////打开文件///////////////////////////////////////////////////
CString FilePathName;
CFileDialog dlg(TRUE);
if(dlg.DoModal()==IDOK) //
FilePathName=dlg.GetPathName();

IplImage* pFrame = NULL;
IplImage* pFrImg = NULL;
IplImage* pBkImg = NULL;
IplImage* pFrImg1 = NULL;

CvMat* pFrameMat = NULL;
CvMat* pFrMat = NULL;
CvMat* pBkMat = NULL;
CvMat* pFrMat1 = NULL;

CvMemStorage * storage = cvCreateMemStorage(0);//轮廓边缘提取时的参数
CvSeq * contour = 0;//轮廓边缘提取时的参数
int mode = CV_RETR_EXTERNAL;//轮廓边缘提取时的参数
//形态学处理时内核的大小
IplConvKernel* Element = cvCreateStructuringElementEx(13,13,1,1,CV_SHAPE_RECT,NULL);

CvFont font1;//初始化字体格式
int linetype=CV_AA;
cvInitFont(&font1, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8);
//用字符串时一定要把using namespace std;写在前面,否则不能用,下面是用于显示的字符串
string msg[10]={"JGD01","JGD02","JGD03","JGD04","JGD05","JGD06","JGD07","JGD08","JGD09","JGD10"};
int No=0;//用于记录显示车辆
bool FindCar=false;

//在视频中画出感兴趣的区域,怎么样才能沿车道画线???????
CvPoint pt1,pt2,pt3,pt4,pt5;
pt1.x=292;//(视频中左下点)
pt1.y=100;
pt2.x=412;//(视频中右上点)
pt2.y=280;
CvRect bndRect=cvRect(0,0,0,0);//用cvBoundingRect画出外接矩形时需要的矩形
int avgX = 0;//The midpoint X position of the rectangle surrounding the moving objects
int avgY = 0;//The midpoint Y position of the rectangle surrounding the moving objects
int avgX1=0;//用来合并相近的车辆
int avgY1=0;
for(int i=0;i<10;i++)
{
TrackBlock[i]=NULL;
if((TrackBlock[i]=(struct AvTrackBlock *) malloc(sizeof(struct AvTrackBlock)))==NULL)
{
MessageBox("内存分配错误");
exit(1);
}
}////////////////////

CvCapture* pCapture = NULL;
int nFrmNum = 0;//表示图像的帧数

//创建窗口
cvNamedWindow("video", 1);
//cvNamedWindow("background",1);
cvNamedWindow("foreground",1);
//使窗口有序排列
cvMoveWindow("video", 30, 0);
//cvMoveWindow("background", 360, 0);
cvMoveWindow("foreground", 690, 0);

if( argc > 2 ){
fprintf(stderr, "Usage: bkgrd [video_file_name]\n");
//return -1;
}

////打开摄像头///////////////////////////////////////////////////
if (argc ==1)
if( !(pCapture = cvCaptureFromCAM(-1))){
fprintf(stderr, "Can not open camera.\n");
//return -2;
}

///打开视频文件//////////////////////////////////////////////////
if(argc == 2)
if( !(pCapture = cvCaptureFromFile(FilePathName))){
fprintf(stderr, "Can not open video file %s\n", FilePathName);
//return -2;
}

//逐帧读取视频,cvQueryFrame从摄像头或者文件中抓取并返回一帧
while(pFrame = cvQueryFrame(pCapture))
{
nFrmNum++;
//如果是第一帧,需要申请内存,并初始化
if(nFrmNum == 1)
{
pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1);

pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);
cvConvert(pFrImg, pFrMat);
cvConvert(pFrImg, pBkMat);
}

else if(nFrmNum == 3)
{
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);
//高斯滤波先,以平滑图像
cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);

//在视频中设置并画出感兴趣的区域
cvRectangle(pFrame,pt1,pt2,CV_RGB(255,0,0),2, 8, 0 );

//当前帧跟背景图相减,cvAbsDiff计算两个数组差的绝对值
cvAbsDiff(pFrameMat, pBkMat, pFrMat);

//二值化前景图
cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);

//通过查找边界找出ROI矩形区域内的运动车辆,建立完全目标档案
//cvCanny(pFrImg, pBkImg, 50, 150, 3);
cvDilate(pFrImg,pBkImg,Element,1);
cvFindContours(pBkImg, storage, &contour, sizeof(CvContour),
mode, CV_CHAIN_APPROX_SIMPLE);
//process each moving contour in the current frame用函数cvBoundingRect
for(;contour!=0;contour=contour->h_next)
{
//Get a bounding rectangle around the moving object.
bndRect = cvBoundingRect(contour, 0);

//Get an average X position of the moving contour.
avgX = (bndRect.x + bndRect.x + bndRect.width) / 2;
avgY = (bndRect.y + bndRect.y + bndRect.height) / 2;
pt5.x = bndRect.x;//写字的左下角点
pt5.y = avgY;

//If the center of contour is within ROI than show it
if(avgX>300 && avgX<400 && avgY<300 && avgY>80)
{
pt3.x = bndRect.x;
pt3.y = bndRect.y;
pt4.x = bndRect.x + bndRect.width;
pt4.y = bndRect.y + bndRect.height;
if(bndRect.height>35) //把长度小于某个阀值的干扰矩形去掉
{
cvRectangle(pFrame,pt3,pt4,CV_RGB(255,0,0),1, 8, 0 );
//在车辆的中心写编号
cvPutText( pFrame, msg[No].c_str(), pt5, &font1, cvScalar(0,255,0));
//把当前车辆存入跟踪数组
TrackBlock[No]->Direction=1;
TrackBlock[No]->FramesTracked=nFrmNum;
TrackBlock[No]->avgX=avgX;
TrackBlock[No]->avgY=avgY;
No++;
}
}
}/////查找边界的for 循环结束

//更新背景///////////////////////////////////////////////////
cvRunningAvg(pFrameMat, pBkMat, 0.005, 0);
//将背景转化为图像格式,用以显示
cvConvert(pBkMat, pBkImg);

//显示图像////////////////////////////////////////////////////
cvShowImage("video", pFrame);
//cvShowImage("background", pBkImg);
//cvShowImage("foreground", pFrImg);

//如果有按键事件,则跳出循环,此等待也为cvShowImage函数提供时间完成显示,等待时间可以根据CPU速度调整
if( cvWaitKey(2) >= 0 )
break;
}

else if(nFrmNum > 3)//从第三帧开始,根据完全目标档案来新增或删除运动车辆档案。
{
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);
//高斯滤波先,以平滑图像
cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);

//在视频中设置并画出感兴趣的区域
//cvSetImageROI(pFrame,rect1);
cvRectangle(pFrame,pt1,pt2,CV_RGB(255,0,0),2, 8, 0 );

//当前帧跟背景图相减,cvAbsDiff计算两个数组差的绝对值
cvAbsDiff(pFrameMat, pBkMat, pFrMat);

//二值化前景图,void cvThreshold( const CvArr* src, CvArr* dst, double threshold,
//double max_value, int threshold_type );
cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);

//通过查找边界找出ROI矩形区域内的运动车辆,建立完全目标档案
//cvCanny(pFrImg, pBkImg, 50, 150, 3);
cvDilate(pFrImg,pBkImg,Element,1);
cvFindContours( pBkImg, storage, &contour, sizeof(CvContour),
mode, CV_CHAIN_APPROX_SIMPLE);
//process each moving contour in the current frame用函数cvBoundingRect
for(;contour!=0;contour=contour->h_next)
{
//Get a bounding rectangle around the moving object.
bndRect = cvBoundingRect(contour, 0);

//Get an average X position of the moving contour.
avgX = (bndRect.x + bndRect.x + bndRect.width) / 2;
avgY = (bndRect.y + bndRect.y + bndRect.height) / 2;
pt5.x=bndRect.x;//写字的左下角点
pt5.y=avgY;

//If the center of contour is within ROI than show it
if(avgX > 300 && avgX < 400 && avgY < 280 && avgY > 100)
{
pt3.x = bndRect.x;
pt3.y = bndRect.y;
pt4.x = bndRect.x + bndRect.width;
pt4.y = bndRect.y + bndRect.height;
if(bndRect.height>35) //把长度小于某个阀值的干扰矩形去掉
{
cvRectangle(pFrame,pt3,pt4,CV_RGB(255,0,0),1, 8, 0 );
//cvPutText(pFrame,msg[No].c_str(), pt5, &font1, cvScalar(0,255,0));
//在跟踪数组中寻找看是否有匹配的车辆,没有则表示是新车辆
for(int i=0;i<10;i++)
{
if(TrackBlock[i]->avgX !=0 && abs(avgX-TrackBlock[i]->avgX)<20 &&
abs(avgY-TrackBlock[i]->avgY)<50)
{
cvPutText(pFrame,msg[i].c_str(), pt5, &font1, cvScalar(0,255,0));
TrackBlock[i]->FramesTracked=nFrmNum;
TrackBlock[i]->avgX=avgX;
TrackBlock[i]->avgY=avgY;
i=10;//使跳出for循环
FindCar=true;
}
}
if(FindCar!=true && avgY<120)//表示没有找到车辆
{
TrackBlock[No]->Direction=1;
TrackBlock[No]->FramesTracked=nFrmNum;
TrackBlock[No]->avgX=avgX;
TrackBlock[No]->avgY=avgY;
if(No==9){
No=0;
}
else
No++;
}
FindCar=false;//赋值为false为下一次寻找车辆做准备
}
}
}//轮廓分for循环结束

//对于没有匹配的车辆,表示已经出了边界,清空数组
for(int j=0;j<10;j++)
{
if(TrackBlock[j]->FramesTracked != nFrmNum)
{
//虽然置为零,但是可能零和当前中心的值在设定的范围内,所以不行。
//TrackBlock[j]=NULL;为何用NULL不行。
TrackBlock[j]->Direction=0;
TrackBlock[j]->FramesTracked=0;
TrackBlock[j]->avgX=0;
TrackBlock[j]->avgY=0;
}
}

//更新背景///////////////////////////////////////////////////
cvRunningAvg(pFrameMat, pBkMat, 0.005, 0);
//将背景转化为图像格式,用以显示
cvConvert(pBkMat, pBkImg);

//显示图像////////////////////////////////////////////////////
cvShowImage("video", pFrame);
cvShowImage("background", pBkImg);
cvShowImage("foreground", pFrImg);

/*if(nFrmNum/2 ==0)
pBkMat=pFrameMat;*/
//如果有按键事件,则跳出循环,此等待也为cvShowImage函数提供时间完成显示,等待时间可以根据CPU速度调整
if( cvWaitKey(2) >= 0 )
break;
}//
}//while循环结束

cvReleaseStructuringElement(&Element);//删除结构元素
//销毁窗口
cvDestroyWindow("video");
cvDestroyWindow("background");
cvDestroyWindow("foreground");

//释放图像和矩阵
cvReleaseImage(&pFrImg);
cvReleaseImage(&pBkImg);

cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrMat);
cvReleaseMat(&pBkMat);
}


nbhx2010 2010-08-20
  • 打赏
  • 举报
回复
楼上的,有思路真未必写的出来。也得看看人家对图像处理有没有经验吧?
我最近在研究电子稳像,也有思路。就是做不出来。代码写了不少都没效果
目前好像也没查到国内有谁弄出来,论文倒是有一堆。
呵呵
Normandie007 2010-08-19
  • 打赏
  • 举报
回复
模板匹配,找出运动目标,进行跟踪
greyrainbow2010 2010-08-19
  • 打赏
  • 举报
回复
有没有更加详细一点的?
m_tornado 2010-08-19
  • 打赏
  • 举报
回复
代码到什么XX几百例的光盘里找吧~或者到资源看看~
greyrainbow2010 2010-08-19
  • 打赏
  • 举报
回复
方法我知道,谁给些代码啊
加载更多回复(2)

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧