opencv学习(一) 简单的背景差法实现车辆检测

本文的环境为opencv3.0+vs13,使用库函数简单的实现了背景差方法下的车辆检测。

PS:但检测的效果并不理想,所以改用haar+adaboost的方法去做检测了,但有幸看到国外一个Urban Track 的项目,介绍里提及使用背景差实现了检测和跟踪,本人还没看完下面贴出链接,感兴趣的可以去研究下:https://www.jpjodoin.com/urbantracker/

基本的思路都体现在注释里了较为简单,任何提高识别率的方法还不吝赐教!

/*
*Author: ruby
*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <string>
#include "cv.h"
#include <math.h>

using namespace cv;
using namespace std;

void chao_thinimage(Mat &srcimage);

void main(){
    IplImage* pFrame = NULL;//视频中截取的一帧
    IplImage* pFrImg = NULL;//当前帧的灰度图
    IplImage* pBkImg = NULL;//当前背景的灰度图
    IplImage* pFrameTemp = NULL;

    CvMat* pFrameMat = NULL;//当前灰度矩阵
    CvMat* pFrMat = NULL;//当前前景图矩阵
    CvMat* pBkMat = NULL;//当前背景图矩阵


    //形态学处理时内核大小
    IplConvKernel* Element = cvCreateStructuringElementEx(13, 13, 1, 1, CV_SHAPE_RECT, NULL);

    //轮廓边缘提取时的参数
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* contour = 0;//可动态增长元素序列
    int mode = CV_RETR_EXTERNAL;//只检索最外面的轮廓

    //在视频中画出感兴趣的区域
    CvPoint pt1, pt2, pt3, pt4, pt5;//pt3,pt4为轮廓矩阵的左下右上
    pt1.x = 292;//视频左下点
    pt1.y = 100;
    pt2.x = 412;//视频右上点
    pt2.y = 280;
    //用cvBoundingRect画出外接矩形时需要的矩形
    CvRect bndRect = cvRect(0, 0, 0, 0);
    //运动对象中心坐标
    int avgX = 0;
    int avgY = 0;


    //视频捕获
    CvCapture* pCapture = NULL;
    //图像的帧数
    int nFramNum = 0;

    //创建窗口
    cvNamedWindow("video", 1);
    cvNamedWindow("foreground", 1);
    cvMoveWindow("video", 30, 0);
    cvMoveWindow("foreground", 690, 0);

    pCapture = cvCaptureFromFile("C:\\Users\\Ruby\\Desktop\\A.avi");
    //pFrame = cvQueryFrame(pCapture);


    pFrameTemp = cvQueryFrame(pCapture);
    pFrame = cvCreateImage(cvGetSize(pFrameTemp), 8, 3);//大小和pFrameTemp相同,8Bit深度3通道图像
    cvCopy(pFrameTemp, pFrame);//将所生成的临时帧复制到pFrame

    //逐帧读取视频,cvQueryFrame从摄像头或者文件中抓取并返回一帧
    while (pFrameTemp = cvQueryFrame(pCapture)){
        cvCopy(pFrameTemp, pFrame);
        nFramNum++;

        //如果是第一帧,申请内存并初始化
        if (nFramNum == 1){
            pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U, 1);//8Bit深度,单通道图像
            pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U, 1);

            pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);//CV_32FC1 代表32位浮点型单通道矩阵
            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 (nFramNum >= 2){
            cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
            cvConvert(pFrImg, pFrameMat);
            //先高斯滤波平滑图像
            cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);

            //在视频中设置并画ROI区域
            cvRectangle(pFrame, pt1, pt2, CV_RGB(255, 0, 0), 2, 8, 0);//线条亮度(255,0,0)为白色,粗细2,类型8

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

            //二值化前景图
            cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);//阈值函数,类型为CV_THRESH_BINARY 二值化

            //膨胀操作,内核为Element
            cvDilate(pFrImg, pBkImg, Element, 1);

            //通过查找边界找出ROI矩形区域内的运动车辆
            cvFindContours(pBkImg, storage, &contour, sizeof(CvContour), mode, CV_CHAIN_APPROX_SIMPLE);//二值图像中寻找轮廓

            //处理当前框架中移动的轮廓,用函数cvBoundingRect
            for (; contour != 0; contour = contour->h_next){
                //获得运动车辆的矩形
                bndRect = cvBoundingRect(contour, 0);
                //获得运动轮廓的平均x坐标
                avgX = bndRect.x + (bndRect.width) / 2;
                avgY = bndRect.y + (bndRect.height) / 2;

                //如果轮廓中心点在ROI内,显示
                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 && 600<(bndRect.width*bndRect.height)<10000){
                        cvRectangle(pFrame, pt3, pt4, CV_RGB(255, 0, 0), 1, 8, 0);
                    }
                }
            }//查找边界for结束

            //更新背景//

            //输入图像或序列-用于累加的图像或序列-移动平均时第一个空image所占的权重-操作符掩码
            cvRunningAvg(pFrameMat, pBkMat, 0.005, 0);//将pFrameMat累加到pBkMat
            //将背景转换成图像格式,用以显示
            cvConvert(pBkMat, pBkImg);

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


            //如果有按键操作,则等待
            if (cvWaitKey(2) >= 0)
                break;

        }   

        waitKey(50);
    }//while循环结束

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

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

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

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值