zoukankan      html  css  js  c++  java
  • CamShift+Kalman跟踪[转载]

    // CamShift+Kalman.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    
    //#include 
    #include 
    #include 
    #include 
    //*************************************
    //调整矩形框B,使其在A的范围
    CvRect my_ChangeRect(CvRect A,CvRect B)
    {
    if(B.x<a.x)
    B.x=A.x;
    if(B.x+B.width>A.width)
    B.width=A.width-B.x;
    if(B.y<a.y)
    B.y=A.y;
    if(B.y+B.height>A.height)
    B.height=A.height-B.y;
    return(B);
    }
    //**************************************
    //kalman初始化
    CvKalman* InitializeKalman(CvKalman* kalman)
    {
    
    const float A[] = {1,0,1,0,
    0,1,0,1,
    0,0,1,0,
    0,0,0,1};
    kalman = cvCreateKalman( 4, 2, 0 );
    memcpy( kalman->transition_matrix->data.fl, A, sizeof(A));//A
    cvSetIdentity( kalman->measurement_matrix, cvScalarAll(1) );//H
    cvSetIdentity( kalman->process_noise_cov, cvScalarAll(1e-5) );//Q w ;
    cvSetIdentity( kalman->measurement_noise_cov, cvScalarAll(1e-1) );//R v
    cvSetIdentity( kalman->error_cov_post, cvScalarAll(1));//P
    return kalman;
    }
    //***************************************
    //point1上一帧中心,point2当前帧中心,把x,y,vx,vy存入kalman->state_post
    void GetCurentState( CvKalman* kalman, CvPoint point1, CvPoint point2)
    {
    float input[4] = {point2.x, point2.y, point2.x-point1.x, point2.y-point1.y};//currentstate
    memcpy( kalman->state_post->data.fl, input, sizeof(input));
    }
    //****************************************
    //point1上一帧中心,point2当前帧中心,把x,y,vx,vy存入矩阵
    CvMat* GetMeasurement(CvMat* mat,CvPoint point1, CvPoint point2)
    {
    float input[4] = {point2.x, point2.y, point2.x-point1.x, point2.y-point1.y};
    memcpy( mat->data.fl, input, sizeof(input));
    return mat;
    }
    /*****************************************/
    #define region 50
    #define calc_point(kalman) cvPoint( cvRound(kalman[0]),cvRound(kalman[1]))
    
    IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *histimg = 0;
    CvHistogram *hist;
    IplImage *backproject;
    
    CvPoint lastpoint; //上一帧的中心坐标
    CvPoint predictpoint, measurepoint;//预测坐标以及当前帧的坐标
    
    int select_object = 0;
    int track_object;
    
    CvPoint origin;
    CvPoint point_text;
    CvRect selection;
    CvRect origin_box;
    
    CvRect track_window;
    CvBox2D track_box; // tracking 返回的区域 box,带角度
    CvConnectedComp track_comp;
    int hdims = 256; // 划分HIST的个数,越高越精确
    float hranges_arr[] = {0,180};
    float* hranges = hranges_arr;
    int vmin = 10, vmax = 256, smin = 30;
    int start_track=0;
    CvFont font;//显示的文本字体
    char nchar[10];//显示数字字符串用
    CvMat* measurement;
    CvMat* realposition;
    const CvMat* prediction;
    CvRect search_window;
    int filename1_n=0;
    int frame_count=0;
    
    void on_mouse( int event, int x, int y, int flags ,void *p)
    {
    if( !image )
    return;
    
    if( image->origin )
    y = image->height - y;
    
    if( select_object )
    {
    selection.x = MIN(x,origin.x);
    selection.y = MIN(y,origin.y);
    selection.width = selection.x + CV_IABS(x - origin.x);
    selection.height = selection.y + CV_IABS(y - origin.y);
    
    selection.x = MAX( selection.x, 0 );
    selection.y = MAX( selection.y, 0 );
    selection.width = MIN( selection.width, image->width );
    selection.height = MIN( selection.height, image->height );
    selection.width -= selection.x;
    selection.height -= selection.y;
    
    }
    
    switch( event )
    {
    case CV_EVENT_LBUTTONDOWN:
    origin = cvPoint(x,y);
    selection = cvRect(x,y,0,0);
    select_object = 1;
    break;
    case CV_EVENT_LBUTTONUP:
    select_object = 0;
    if( selection.width > 0 && selection.height > 0 )
    track_object = -1; 
    origin_box=selection;
    
    
    #ifdef _DEBUG
    printf("\n # 鼠标的选择区域:"); 
    printf("\n X = %d, Y = %d, Width = %d, Height = %d",
    selection.x, selection.y, selection.width, selection.height);
    #endif
    break;
    }
    }
    /*************************************main***************************/
    int main( int argc, char** argv )
    {
    CvCapture* capture = 0;
    IplImage* frame = 0; 
    capture = cvCaptureFromCAM(0); 
    if( !capture )
    {
    fprintf(stderr,"Could not initialize capturing...\n");
    return -1;
    }
    
    cvNamedWindow( "CamShiftDemo", 1 );
    cvSetMouseCallback( "CamShiftDemo", on_mouse, NULL ); // on_mouse 自定义事件
    cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
    cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
    cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
    //初始化kalman
    CvKalman* kalman =0; 
    kalman= InitializeKalman(kalman);
    measurement = cvCreateMat( 2, 1, CV_32FC1 );//Z(k)
    realposition = cvCreateMat( 4, 1, CV_32FC1 );//real X(k)
    
    for(;;)
    {
    int i=0,c;
    frame = cvQueryFrame( capture );
    if( !frame )
    break;
    if( !image )
    {
    /* allocate all the buffers */
    image = cvCreateImage( cvGetSize(frame), 8, 3 );
    image->origin = frame->origin;
    hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
    hue = cvCreateImage( cvGetSize(frame), 8, 1 );
    mask = cvCreateImage( cvGetSize(frame), 8, 1 );
    
    backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); 
    backproject->origin = frame->origin;
    hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); // 计算直方图
    
    } 
    cvCopy( frame, image, 0 );
    cvCvtColor( image, hsv, CV_BGR2HSV ); // 彩色空间转换 BGR to HSV 
    frame_count++;
    //*******************************************************************************************
    if(track_object)
    {
    int _vmin = vmin, _vmax = vmax; 
    cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
    cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); // 得到二值的MASK
    cvSplit( hsv, hue, 0, 0, 0 ); // 只提取 HUE 分量 
    if( track_object < 0 )
    {
    float max_val = 0.f;
    cvSetImageROI( hue, origin_box ); // 得到选择区域 for ROI
    cvSetImageROI( mask, origin_box ); // 得到选择区域 for mask
    cvCalcHist( &hue, hist, 0, mask ); // 计算直方图
    cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); // 只找最大值
    cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); // 缩放 bin 到区间 [0,255] 
    cvResetImageROI( hue ); // remove ROI
    cvResetImageROI( mask );
    track_window = origin_box; 
    track_object=1;
    lastpoint = predictpoint = cvPoint(track_window.x + track_window.width/2,
    track_window.y + track_window.height/2 );
    GetCurentState(kalman, lastpoint, predictpoint);//input curent state
    }
    //预测目标框的位置(x,y,vx,vy), 
    prediction = cvKalmanPredict( kalman, 0 );//predicton=kalman->state_post 
    predictpoint = calc_point(prediction->data.fl); 
    //预测出的矩形框
    track_window = cvRect(predictpoint.x - track_window.width/2, predictpoint.y - track_window.height/2, 
    track_window.width, track_window.height); 
    track_window=my_ChangeRect(cvRect(0,0,frame->width,frame->height),track_window); 
    //只对目标周围计算投影
    search_window = cvRect(track_window.x - region, track_window.y - region, 
    track_window.width + 2*region, track_window.height + 2*region);
    //修正search_window,使其范围在图像内
    search_window=my_ChangeRect(cvRect(0,0,frame->width,frame->height),search_window);
    cvSetImageROI( hue, search_window );
    cvSetImageROI( mask, search_window );
    cvSetImageROI( backproject, search_window ); 
    cvCalcBackProject( &hue, backproject, hist ); // 使用 back project 方法
    cvAnd( backproject, mask, backproject, 0 ); 
    //因为设置了_1ROI,所以更新track_window
    track_window = cvRect(region, region, track_window.width, track_window.height);
    // calling CAMSHIFT 算法模块 
    /* cvCamShift( backproject, track_window,
    cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
    &track_comp, &track_box );*/
    cvMeanShift( backproject, track_window,
    cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
    &track_comp);
    //******************************************************************************** 
    cvResetImageROI( hue);
    cvResetImageROI( mask );
    cvResetImageROI( backproject );
    track_window=track_comp.rect;
    track_window = cvRect(track_window.x + search_window.x, track_window.y +search_window.y, 
    track_window.width, track_window.height);
    //实际的质心坐标 
    measurepoint = cvPoint(track_window.x + track_window.width/2, 
    track_window.y + track_window.height/2 ); 
    realposition->data.fl[0]=measurepoint.x;
    realposition->data.fl[1]=measurepoint.y;
    realposition->data.fl[2]=measurepoint.x - lastpoint.x;
    realposition->data.fl[3]=measurepoint.y - lastpoint.y;
    lastpoint = measurepoint;//keep the current real position
    //实际算出的measurement只是当前的x,y
    cvMatMulAdd( kalman->measurement_matrix/*2x4*/, realposition/*4x1*/,/*measurementstate*/ 0, measurement );
    cvKalmanCorrect( kalman, measurement ); 
    cvRectangle( image , cvPoint(track_window.x,track_window.y),
    cvPoint(track_window.x+track_window.width,track_window.y+track_window.height),
    CV_RGB(255,0,0),2, 8, 0 );
    //把目标是第几个标出来
    cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX,1.0F,1.0F,0,3,8);
    sprintf(nchar,"ID:%d",i+1);
    point_text=cvPoint(track_window.x,track_window.y+track_window.height);
    cvPutText(image,nchar,point_text,&font,CV_RGB(255,255,0)); 
    }
    //*********************************************************************************************** 
    if( select_object && selection.width > 0 && selection.height > 0 )
    {
    cvSetImageROI( image, selection );
    cvXorS( image, cvScalarAll(255), image, 0 );
    cvResetImageROI( image );
    }
    cvShowImage( "CamShiftDemo", image );
    c = cvWaitKey(30);
    //根据键盘关闭跟踪目标
    if( c == 27 )
    break; // exit from for-loop 
    }
    cvReleaseCapture( &capture );
    cvDestroyWindow("CamShiftDemo");
    return 0;
    }
  • 相关阅读:
    看懂SqlServer查询计划
    Android开发16——获取网络资源之基础应用
    Android开发15——给TextView加上滚动条
    PeekMessage、GetMessage的区别
    获取不到Repeater控件中的CheckBox选中状态
    第十九讲:动态链接库
    孙鑫VC++视频教程笔记
    CEdit 控制键盘操作
    网络编程中粘包的处理方法
    VC++编程之道读书笔记(2)
  • 原文地址:https://www.cnblogs.com/polly333/p/4498429.html
Copyright © 2011-2022 走看看