zoukankan      html  css  js  c++  java
  • MHI ,运动历史图像的的获取[下载自CSDN]

    #include "cv.h"
    #include "highgui.h"
    #include "stdlib.h"
    #include "malloc.h"
    #include "cxcore.h"
    #include "assert.h"
    #include <time.h>
    #include <math.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <iostream>
    
    using namespace std;
    
    // various tracking parameters (in seconds)
    const double MHI_DURATION = 1;
    const double MAX_TIME_DELTA = 0.5;
    const double MIN_TIME_DELTA = 0.05;
    // number of cyclic frame buffer used for motion detection
    // (should, probably, depend on FPS)
    //用于运动检测的循环帧数
    const int N = 4;
    
    // ring image buffer
    IplImage **buf = 0;
    int last = 0;
    
    // temporary images
    IplImage *mhi = 0; // MHI
    IplImage *orient = 0; // orientation
    IplImage *mask = 0; // valid orientation mask
    IplImage *segmask = 0; // motion segmentation map
    CvMemStorage* storage = 0; // temporary storage
    
    // parameters:
    //  img - input video frame
    //  dst - resultant motion picture
    //  args - optional parameters
    void  update_mhi(IplImage* img, IplImage* dst, int diff_threshold)
    {
        double timestamp = (double)clock() / CLOCKS_PER_SEC; // get current time in seconds
        CvSize size = cvSize(img->width, img->height); // get current frame size
        int i, idx1 = last, idx2;
        IplImage* silh;
        CvSeq* seq;
        CvRect comp_rect;
        double count;
        double angle;
        CvPoint center;
        double magnitude;
        CvScalar color;
    
        // allocate images at the beginning or  为图像分配初始空间
        // reallocate them if the frame size is changed  当帧的大小改变时,重新分配内存空间
        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]));//把申请到的内存空间用0初始化
            }
    
            for (i = 0; i < N; i++) {
                cvReleaseImage(&buf[i]);
                buf[i] = cvCreateImage(size, IPL_DEPTH_8U, 1);
                cvZero(buf[i]);
            }
            cvReleaseImage(&mhi);
            cvReleaseImage(&orient);
            cvReleaseImage(&segmask);
            cvReleaseImage(&mask);
    
            mhi = cvCreateImage(size, IPL_DEPTH_32F, 1);
            cvZero(mhi); // clear MHI at the beginning
            orient = cvCreateImage(size, IPL_DEPTH_32F, 1);
            segmask = cvCreateImage(size, IPL_DEPTH_32F, 1);
            mask = cvCreateImage(size, IPL_DEPTH_8U, 1);
        }
    
        cvCvtColor(img, buf[last], CV_BGR2GRAY); // convert frame to grayscale 转换为灰度图
    
        idx2 = (last + 1) % N; // index of (last - (N-1))th frame
        last = idx2;
        silh = buf[idx2];
        cvAbsDiff(buf[idx1], buf[idx2], silh); // get difference between frames相邻两帧之差
    
        cvThreshold(silh, silh, diff_threshold, 1, CV_THRESH_BINARY); // and threshold it
        cvUpdateMotionHistory(silh, mhi, timestamp, MHI_DURATION); // update MHI
    
        // convert MHI to blue 8u image
        cvCvtScale(mhi, mask, 255. / MHI_DURATION,
            (MHI_DURATION - timestamp)*255. / MHI_DURATION);
        cvZero(dst);
        cvCvtPlaneToPix(mask, 0, 0, 0, dst);
    
        // calculate motion gradient orientation and valid orientation mask计算运动的梯度方向以及正确的方向掩码
        cvCalcMotionGradient(mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3);
    
        if (!storage)
            storage = cvCreateMemStorage(0);
        else
            cvClearMemStorage(storage);
    
        // segment motion: get sequence of motion components运动分割:获取运动组成成分的序列
        // segmask is marked motion components map. It is not used further
        seq = cvSegmentMotion(mhi, segmask, storage, timestamp, MAX_TIME_DELTA);
    
        // iterate through the motion components,迭代运动的组成成分
        // One more iteration (i == -1) corresponds to the whole image (global motion)
        for (i = -1; i < seq->total; i++)
        {
    
            if (i < 0)
            { // case of the whole image
                comp_rect = cvRect(0, 0, size.width, size.height);
                color = CV_RGB(255, 255, 255);
                magnitude = 100;
            }
            else
            { // i-th motion component
                comp_rect = ((CvConnectedComp*)cvGetSeqElem(seq, i))->rect;
                if (comp_rect.width + comp_rect.height < 100) // reject very small components
                    continue;
                color = CV_RGB(255, 0, 0);
                magnitude = 30;
            }
    
            // select component ROI
            cvSetImageROI(silh, comp_rect);
            cvSetImageROI(mhi, comp_rect);
            cvSetImageROI(orient, comp_rect);
            cvSetImageROI(mask, comp_rect);
    
            // calculate orientation在选择区域内计算运动方向
            angle = cvCalcGlobalOrientation(orient, mask, mhi, timestamp, MHI_DURATION);
            angle = 360.0 - angle;  // adjust for images with top-left origin
    
            count = cvNorm(silh, 0, CV_L1, 0); // calculate number of points within silhouette ROI
    
            cvResetImageROI(mhi);
            cvResetImageROI(orient);
            cvResetImageROI(mask);
            cvResetImageROI(silh);
    
            // check for the case of little motion
            if (count < comp_rect.width*comp_rect.height * 0.05)
                continue;
    
            //// draw a clock with arrow indicating the direction画一个“钟表”指向运动的方向
            //center = cvPoint((comp_rect.x + comp_rect.width / 2),
            //    (comp_rect.y + comp_rect.height / 2));
    
            //cvCircle(dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0);
            //cvLine(dst, center, cvPoint(cvRound(center.x + magnitude*cos(angle*CV_PI / 180)),
            //    cvRound(center.y - magnitude*sin(angle*CV_PI / 180))), color, 3, CV_AA, 0);
        }
    }
    
    
    int main(int argc, char** argv)
    {
        IplImage* motion = 0;
        CvCapture* capture = 0;
    
        capture = cvCaptureFromFile("E:Videos\daria_walk.avi");
    
        if (capture)
        {
            cvNamedWindow("Motion", 1);
    
            for (;;)
            {
                IplImage* image;
                if (!cvGrabFrame(capture))
                    break;
                //Decodes and returns the grabbed video frame.
                //C++: bool VideoCapture::retrieve(Mat& image, int channel=0)
                // IplImage* cvRetrieveFrame(CvCapture* capture, int streamIdx=0 )
                image = cvRetrieveFrame(capture);
    
                if (image)
                {
                    if (!motion)
                    {
                        //Creates an image header and allocates the image data.
                        //C: IplImage* cvCreateImage(CvSize size, int depth, int channels)
                        motion = cvCreateImage(cvSize(image->width, image->height), 8, 3);
                        //Clears the array.
                        //C: void cvSetZero(CvArr* arr)
                        cvZero(motion);
                        motion->origin = image->origin;
                    }
                }
    
                update_mhi(image, motion, 30);
                cvShowImage("Motion", motion);
    
                if (cvWaitKey(10) >= 0)
                    break;
            }
            cvReleaseCapture(&capture);
            cvDestroyWindow("Motion");
        }
    
        return 0;
        
    }
  • 相关阅读:
    spring: web学习笔记1异常处理:No adapter for handler
    maven: maven编译时指定maven库,即指定profile
    spring: 一些基本配置也许只有自己能够读懂
    ruby: rdoc生成文档的好工具
    php: eclipse 编辑 php
    ssh免密码登录, 发送命令到多个Linux
    ruby: 使用netbeans debug ruby
    maven: maven创建工程,web工程等普通java app, web app
    IE, firefox竖向 横向滚动条处理
    获取指定进程在一段时间内cpu和内存的最大最小值【调试版】
  • 原文地址:https://www.cnblogs.com/beihaidao/p/5900687.html
Copyright © 2011-2022 走看看