OpenCV学习之寻找轮廓实现视频流的运动目标检测

//寻找轮廓实现视频流的运动目标检测
#include "cv.h"
#include "highgui.h"
#include "time.h"
#include "math.h"
#include "ctype.h"
#include "string.h"
const double MHI_DURATION = 0.5;
const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05;
const int N = 3;
const int CONTOUR_MAX_AERA = 16;
IplImage** buf = 0;
int last = 0;
IplImage* mhi = 0;
int filter = CV_GAUSSIAN_5x5;//高版本不支持CvFilter,用int
CvConnectedComp* cur_comp, min_comp;
CvConnectedComp* comp;
CvMemStorage* storage;
CvPoint pt[4];

//参数:
//img - 输入视频帧
//dst - 检测结果
void update_mhi(IplImage* img, IplImage* dst, int diff_threshold) {
    double timestamp = clock() / 100;//当前时间秒
    CvSize size = cvSize(img->width, img->height);
    int i, idx1, idx2;
    IplImage* silh;
    //uchar val;
    //float temp;
    IplImage* pyr = cvCreateImage(cvSize((size.width&-2) / 2, (size.height&-2) / 2), 8, 1);
    CvMemStorage* stor;
    CvSeq *cont; 
    //CvSeq *result, *squares;
    //CvSeqReader reader;
    if (!mhi || mhi->width != size.width || mhi->height != size.height) {
        if (buf == 0) {
            buf = (IplImage**)malloc(N * sizeof(buf[0]));
            memset(buf, 0, N * sizeof(buf[0]));
        }
        for (i = 0; i < N; i++) {
            cvReleaseImage(&buf[i]);
            buf[i] = cvCreateImage(size, 8, 1);
            cvZero(buf[i]);
        }
        cvReleaseImage(&mhi);
        mhi = cvCreateImage(size, IPL_DEPTH_32F, 1);
        cvZero(mhi);
    }
    cvCvtColor(img, buf[last], CV_BGR2GRAY);
    idx1 = last;
    idx2 = (last + 1) % N;
    last = idx2;

    //做帧差
    silh = buf[idx2];
    cvAbsDiff(buf[idx1], buf[idx2], silh);

    //对差图像做二值化
    cvThreshold(silh, silh, 30, 255, CV_THRESH_BINARY);

    cvUpdateMotionHistory(silh, mhi, timestamp, MHI_DURATION);//update MHI
    cvCvtScale(mhi, dst, 255. / MHI_DURATION, 0);

    //中值滤波,清除小噪声
    cvSmooth(dst, dst, CV_MEDIAN, 3, 0, 0, 0);

    //向下采样,去掉噪声
    cvPyrDown(dst, pyr, 7);
    cvDilate(pyr, pyr, 0, 1);//膨胀,消除不连续空间
    cvPyrUp(pyr, dst, 7);
    //寻找轮廓
    stor = cvCreateMemStorage(0);
    cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), stor);
    //找到所有轮廓
    cvFindContours(dst, stor, &cont, sizeof(CvContour),
        CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
    //直接使用CONTOUR中的矩形来画轮廓
    for (; cont; cont = cont->h_next) {
        CvRect r = ((CvContour*)cont)->rect;
        if (r.height * r.width > CONTOUR_MAX_AERA) {
            //抛弃面积小的方形
            cvRectangle(img, cvPoint(r.x, r.y), cvPoint(r.x + r.width, r.y + r.height), CV_RGB(255, 0, 0), 1, CV_AA, 0);
        }
    }
    cvReleaseMemStorage(&stor);
    cvReleaseImage(&pyr);
}
int main(int argc, char** argv) {
    IplImage* motion = 0;
    CvCapture* capture = cvCreateCameraCapture(0);//初始化相机捕获的指针  
    //capture = cvCaptureFromAVI("沙画.mp4");//从视频获取

    if (!capture)
    {
        system("pause");
        exit(-1);
    }

    if (capture) {
        cvNamedWindow("Motion", 1);
        while (1) {
            IplImage* image;
            if (!cvGrabFrame(capture))
                break;
            //image = cvQueryFrame(capture);
            image = cvRetrieveFrame(capture);
            if (image) {
                if (!motion) {
                    motion = cvCreateImage(cvSize(image->width, image->height), 8, 1);
                    cvZero(motion);
                    motion->origin = image->origin;
                }
            }
            update_mhi(image, motion, 60);
            cvShowImage("Motion", image);
            if (cvWaitKey(10) >= 0)
                break;
        }
        cvReleaseCapture(&capture);
        cvDestroyWindow("Motion");
    }
    return 0;
}

你可能感兴趣的:(OpenCV学习笔记)