zoukankan      html  css  js  c++  java
  • PariticalFilter在MFC上的运行,源代码公开

           由于项目需要,进行过一段时间的 PariticalFilter 研究。主要的工作就是将网络上的Console代码和Mfc融合在一起,并且添加了Mfc端的控制功能。

          程序还有不完善的地方,现将相关的函数发布出来,大家相互研究。程序运行界面
    程序的核心为两个部分,一个是核心PF函数,一个是界面操作
    核心函数
    /** @file
        Definitions related to tracking with particle filtering
        @author Rob Hess
        @version 1.0.0-20060307
        jsxyhelu 2016年11月修改 更多代码,请浏览jsxyhelu.cnblogs.com
        jsxyhelu 2016年12月代码梳理,重构
    */

    #include "stdafx.h"
    #include "GOPF.h"
    using namespace std;
    using namespace cv;
    //非常值得注意的一点是,本例中的指针的运用极大地提高了系统速度
    //使用方法
    /*//变量
    int num_particles = 100;//狗的数目
    int iFrame = 0;//当前为第几帧
    Rect rectStart;//初始化矩形
    Mat matFrame;  //原始帧
    Mat matClone;  //原始帧复制
    Mat matHSV;    //原始帧的HSV形式
    particle* particles, * new_particles;
    //gsl初始化
    gsl_rng* rng;
    gsl_rng_env_setup();
    rng = gsl_rng_alloc( gsl_rng_mt19937 );
    gsl_rng_set( rng, time(NULL) );
    //gsl初始化结束,rng为输出
    //打开视频
    VideoCapture videocapture;
    videocapture.open("e:/sandbox/1.avi");
    if (!videocapture.isOpened())
    {
    printf("视频打开失败!");
    return -1;
    }
    //TODO
    rectStart = Rect(449,86,21,13);  
    //主要循环
    for (;;)
    {
    videocapture >> matFrame;
    if (matFrame.empty())
    break;
    matClone = matFrame.clone();
    imshow("原始图像",matFrame);
    //step 0  当前帧转换为hsv模式,注意是在float下转换
    matFrame.convertTo(matHSV,CV_32F,1.0/255);
    cvtColor(matHSV,matHSV,COLOR_BGR2HSV);
    //step 1  如果为第一帧,初始化相关数据
    if (iFrame == 0)
    {
    //计算初始区域的粒子
    histogram* ref_histos = compute_ref_histos( matHSV, rectStart);
    particles = init_distribution( rectStart, ref_histos,1, num_particles );
    iFrame = 1;
    }
    else
    {
    //step 2 放出100狗
    for( int j = 0; j < num_particles; j++ )
    {
    //生成随机狗
    particles[j] = transition( particles[j], matFrame.cols,matFrame.rows, rng );
    float s = particles[j].s;
    //计算相似性
    particles[j].w = likelihood( matHSV, cvRound(particles[j].y),
    cvRound( particles[j].x ),
    cvRound( particles[j].width * s ),
    cvRound( particles[j].height * s ),
    particles[j].histo );
    }
    //step 3 重新规划
    normalize_weights( particles, num_particles );
    new_particles = resample( particles, num_particles );
    free( particles );
    particles = new_particles;
    }
    display_particle( &matClone, *particles );
    imshow("结果图像",matClone);
    waitKey(15);
    iFrame = iFrame +1;
    }*/

     
    //根据hsv的bin的返回结果
    int histo_bin( float h, float s, float v )
    {
        #define H_MAX 360.0
        #define S_MAX 1.0
        #define V_MAX 1.0
        #define S_THRESH 0.1
        #define V_THRESH 0.2
        int hd, sd, vd;
        /* if S or V is less than its threshold, return a "colorless" bin */
        vd = MIN( (int)(v * NV / V_MAX), NV-1 );
        if( s < S_THRESH  ||  v < V_THRESH )
            return NH * NS + vd;
        /* otherwise determine "colorful" bin */
        hd = MIN( (int)(h * NH / H_MAX), NH-1 );
        sd = MIN( (int)(s * NS / S_MAX), NS-1 );    return sd * NH + hd;
    }
    //计算直方图结果,因为所有的值都是计算成直方图,所以这个是核心算法(意味运行次数最多,优化最有效)
    histogram* calc_histogram( IplImage* imgs, int n )
    {
        histogram* histo;
        IplImage* h, * s, * v;
        float* hist;
        int i, r, c, bin;
        histo = (histogram* )malloc( sizeof(histogram) );
        histo->= NH*NS + NV;
        hist = histo->histo;
        memset( hist, 0, histo->* sizeof(float) );
        h = cvCreateImage( cvGetSize(imgs), IPL_DEPTH_32F, 1 );
        s = cvCreateImage( cvGetSize(imgs), IPL_DEPTH_32F, 1 );
        v = cvCreateImage( cvGetSize(imgs), IPL_DEPTH_32F, 1 );
        cvSplit( imgs, h, s, v, NULL );
            /* increment appropriate histogram bin for each pixel */
        for( r = 0; r < imgs->height; r++ )
            for( c = 0; c < imgs->width; c++ )
            {
                bin = histo_bin( /*pixval32f( h, r, c )*/((float*)(h->imageData + h->widthStep*r) )[c],
                    ((float*)(s->imageData + s->widthStep*r) )[c],
                    ((float*)(v->imageData + v->widthStep*r) )[c] );
                hist[bin] += 1;
            }
            cvReleaseImage( &h );
            cvReleaseImage( &s );
            cvReleaseImage( &v );
        return histo;
    }
    //直方图正定化
    void normalize_histogram( histogram* histo )
    {
        float* hist;
        float sum = 0, inv_sum;
        int i, n;
        hist = histo->histo;
        n = histo->n;
        /* compute sum of all bins and multiply each bin by the sum's inverse */
        for( i = 0; i < n; i++ )
            sum += hist[i];
        inv_sum = 1.0 / sum;
        for( i = 0; i < n; i++ )
            hist[i] *= inv_sum;
    }
    //计算n个histogram的数据结构
    histogram* compute_ref_histos(Mat src , Rect rect )
    {
        IplImage matsrc(src);
        IplImage* frame = &matsrc;
        CvRect regions = (CvRect)rect;
        histogram* histos = (histogram*) malloc( sizeof( histogram* ) );
        IplImage* tmp;
        cvSetImageROI( frame, regions );
        tmp = cvCreateImage( cvGetSize( frame ), IPL_DEPTH_32F, 3 );
        cvCopy( frame, tmp, NULL );
        cvResetImageROI( frame );
        histos = calc_histogram( tmp, 1 );
        normalize_histogram( histos );
        cvReleaseImage( &tmp );
        return histos;
    }
    //初始化distribution
    particle* init_distribution( Rect rect, histogram* histos, int n, int p)
    {
        CvRect regions = (CvRect)rect;
        particle* particles;
        int np;
        float x, y;
        int i, j, width, height, k = 0;
        particles =(particle*) malloc( p * sizeof( particle ) );
        np = p / n;
        width = regions.width;
        height = regions.height;
        x = regions.x + width / 2;
        y = regions.y + height / 2;
        for( j = 0; j < np; j++ )
        {
            particles[k].x0 = particles[k].xp = particles[k].x = x;
            particles[k].y0 = particles[k].yp = particles[k].y = y;
            particles[k].sp = particles[k].s = 1.0;
            particles[k].width = width;
            particles[k].height = height;
            particles[k].histo = histos;
            particles[k++].w = 0;
        }
        /* make sure to create exactly p particles */
        i = 0;
        while( k < p )
        {
            width = regions.width;
            height = regions.height;
            x = regions.x + width / 2;
            y = regions.y + height / 2;
            particles[k].x0 = particles[k].xp = particles[k].x = x;
            particles[k].y0 = particles[k].yp = particles[k].y = y;
            particles[k].sp = particles[k].s = 1.0;
            particles[k].width = width;
            particles[k].height = height;
            particles[k].histo = histos;
            particles[k++].w = 0;
            i = ( i + 1 ) % n;
        }
        return particles;
    }
    //预测狗的位置
    particle transition( particle p, int w, int h, gsl_rng* rng )
    {
        #define TRANS_X_STD 1.0
        #define TRANS_Y_STD 0.5
        #define TRANS_S_STD 0.001
        /* autoregressive dynamics parameters for transition model */
        #define A1  2.0
        #define A2 -1.0
        #define B0  1.0000
        float x, y, s;
        particle pn;
        //采用 second-order 进行狗的估算
        /* sample new state using second-order autoregressive dynamics */
        x = A1 * ( p.x - p.x0 ) + A2 * ( p.xp - p.x0 ) +
            B0 * gsl_ran_gaussian( rng, TRANS_X_STD ) + p.x0;
        pn.x = MAX( 0.0, MIN( (float)w - 1.0, x ) );
        y = A1 * ( p.y - p.y0 ) + A2 * ( p.yp - p.y0 ) +
            B0 * gsl_ran_gaussian( rng, TRANS_Y_STD ) + p.y0;
        pn.y = MAX( 0.0, MIN( (float)h - 1.0, y ) );
        s = A1 * ( p.s - 1.0 ) + A2 * ( p.sp - 1.0 ) +
            B0 * gsl_ran_gaussian( rng, TRANS_S_STD ) + 1.0;
        pn.s = MAX( 0.1, s );
        pn.xp = p.x;
        pn.yp = p.y;
        pn.sp = p.s;
        pn.x0 = p.x0;
        pn.y0 = p.y0;
        pn.width = p.width;
        pn.height = p.height;
        pn.histo = p.histo;
        pn.w = 0;
        return pn;
    }
    //histogram比较,马氏距离
    float histo_dist_sq( histogram* h1, histogram* h2 )
    {
      float* hist1, * hist2;
      float sum = 0;
      int i, n;
      n = h1->n;
      hist1 = h1->histo;
      hist2 = h2->histo;
      for( i = 0; i < n; i++ )
        sum += sqrt( hist1[i]*hist2[i] );
      return 1.0 - sum;
    }
    //粒子比较
    int particle_cmp( const void* p1,const void* p2 )
    {
        particle* _p1 = (particle*)p1;
        particle* _p2 = (particle*)p2;
        if( _p1->> _p2->w )
            return -1;
        if( _p1->< _p2->w )
            return 1;
        return 0;
    }
    //相似性计算
    float likelihood( Mat matSrc, int r, int c,int w, int h, histogram* ref_histo )
    {
        #define LAMBDA 20
        IplImage matimg(matSrc);
        IplImage* img = &matimg;
     
        IplImage* tmp;
        histogram* histo;
        float d_sq;
        /* extract region around (r,c) and compute and normalize its histogram */
        cvSetImageROI( img, cvRect( c - w / 2, r - h / 2, w, h ) );
        tmp = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 3 );
        cvCopy( img, tmp, NULL );
        cvResetImageROI( img );
        histo = calc_histogram( tmp, 1 );
        cvReleaseImage( &tmp );
        normalize_histogram( histo );
        /* compute likelihood as e^{lambda D^2(h, h^*)} */
        d_sq = histo_dist_sq( histo, ref_histo );
        free( histo );
        return exp( -LAMBDA * d_sq );
    }
    //权值归一化
    void normalize_weights( particle* particles, int n )
    {
        float sum = 0;
        int i;
        for( i = 0; i < n; i++ )
            sum += particles[i].w;
        for( i = 0; i < n; i++ )
            particles[i].w /= sum;
    }
    //重新采样
    particle* resample( particle* particles, int n )
    {
        particle* new_particles;
        int i, j, np, k = 0;
        //quick sort
        qsort( particles, n, sizeof( particle ), &particle_cmp );
        new_particles =(particle* ) malloc( n * sizeof( particle ) );
        for( i = 0; i < n; i++ )
        {
            np = cvRound( particles[i].w * n );
            for( j = 0; j < np; j++ )
            {
                new_particles[k++= particles[i];
                if( k == n )
                    goto exit;
            }
        }
        while( k < n )
            new_particles[k++= particles[0];
    exit:
        return new_particles;
    }
    //显示PF的结果
    void display_particle( Mat* img, particle p )
    {
        int x0, y0, x1, y1;
        x0 = cvRound( p.x - 0.5 * p.s * p.width );
        y0 = cvRound( p.y - 0.5 * p.s * p.height );
        x1 = x0 + cvRound( p.s * p.width );
        y1 = y0 + cvRound( p.s * p.height );
        cv::rectangle(*img,Point(x0,y0),Point(x1,y1),Scalar(0,0,255));
    }
    界面处理相关
    void CGOMfcTemplate2Dlg::OnMouseMove(UINT nFlags, CPoint point)
    {
        CRect rect_ctr;  
        (this->GetDlgItem(IDC_CAM))->GetWindowRect(&rect_ctr);//获取Picture控件相对屏幕左上角的坐标,  
        ScreenToClient(rect_ctr);//获取Picture控件相对对话框客户区左上角的坐标  
        instant_position.x = point.x;
        instant_position.y = point.y;
        picture_ordinate_x = point.x - rect_ctr.left;
        picture_ordinate_y = point.y - rect_ctr.top;//point获取的是鼠标相对对话框客户区左上角的坐标,减去rect_ctr.left和rect_ctr.top后,即为鼠标相对Picture控件左上角的坐标  
        if ((nFlags == MK_LBUTTON) && Is_LeftButton_Down)
        {
            ::SetCursor(cross);
            CClientDC dc(this);
            CBrush *OldBrush;
            OldBrush=(CBrush*)dc.SelectStockObject(NULL_BRUSH);
            dc.SetROP2(R2_NOT);
            dc.Rectangle(CRect(chosen_position,instant_position));
            dc.Rectangle(CRect(chosen_position,point));
            dc.SelectObject(OldBrush);
            instant_position=point;
        }
        else
            ::SetCursor(arrow);
        CDialogEx::OnMouseMove(nFlags, point);
    }

    void CGOMfcTemplate2Dlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
        Is_LeftButton_Down = true;
        ::SetCursor(cross);
        chosen_position = instant_position = point;
        CDialogEx::OnLButtonDown(nFlags, point);
    }
    void CGOMfcTemplate2Dlg::OnLButtonUp(UINT nFlags, CPoint point)
    {
        if (Is_LeftButton_Down)
        {
            Is_LeftButton_Down = false;
            ::SetCursor(arrow);
            CClientDC dc(this);
            CPen* pOldPen=(CPen*)dc.SelectObject(&pen);
            dc.MoveTo(chosen_position);
            dc.LineTo(chosen_position.x,instant_position.y);
            dc.LineTo(instant_position);
            dc.LineTo(instant_position.x,chosen_position.y);
            dc.LineTo(chosen_position);
            //写到rect_res中区
            int rect_x = min(chosen_position.x,instant_position.x);
            int rect_y = min(chosen_position.y,instant_position.y);
            int rect_w = abs(chosen_position.x - instant_position.x);
            int rect_h = abs(chosen_position.y - instant_position.y);
            rectStart = Rect(rect_x,rect_y,rect_w,rect_h);
        }
        CDialogEx::OnLButtonUp(nFlags, point);
    }
  • 相关阅读:
    软件工程第四次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    软件工程最后一次作业
    软件工程第四次作业
    软件工程第二次作业
    软件工程最后一次作业
    软件工程第二次结对作业
    软件工程第三次作业
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/6336429.html
Copyright © 2011-2022 走看看