PariticalFilter在MFC上的运行,源代码公开

简介: 由于项目需要,进行过一段时间的 PariticalFilter 研究。主要的工作就是将网络上的Console代码和Mfc融合在一起,并且添加了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);
}
目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com
目录
相关文章
|
3月前
|
移动开发 安全 前端开发
iOS代码混淆工具
iOS代码混淆工具
60 1
|
4月前
|
C++
[MFC] 动态链接库的制作过程和使用方法与总结
[MFC] 动态链接库的制作过程和使用方法与总结
42 0
C++ 编写DLL文件给易语言调用
  摸索了两天了,终于解决了所有问题,在此跟大家分享。   需要三个文件,dll_demo.h、dll_demo.cpp、dll_dome.def   直接上代码:   头文件如下: 1 #ifndef _DLL_DEMO_H_ 2 #define _DLL_DEMO_H_ 3 #ifdef DL...
2097 0
|
编译器 Linux C语言
【C 语言】动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )
【C 语言】动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )
236 0
【C 语言】动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )
|
安全 IDE 小程序
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
204 0
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
|
IDE 程序员 开发工具
如何看懂源代码--(分析源代码方法)
建立架构观点的认识是最重要的事情。虽然这一系列的文章前提为“阅读他人的程式码”,但我们真正想做的工作,并不在于彻底地详读每一行程式码的细节,而是想要透过重点式的程式码“摘读” ,达到对系统所需程度的了解。每个人在阅读程式码的动机不尽相同,需要了解的程度也就有深浅的分别。只有极为少数的情况下,你才会需要细读每一行程式码。
583 0
|
编译器 开发工具 C语言
Qt编写自定义控件插件开放动态库dll使用(永久免费)
一、前言 这套控件陆陆续续完善了四年多,目前共146个控件,除了十几个控件参考网友开源的代码写的,其余全部原创,在发布之初就有打算将动态库开放出来永久免费使用,在控件比较完善的今天抽了半天时间编译了多个qt版本的动态库,目前已经有26个版本,其中包括了linux版本,和头文件一起打包放在百度网盘。
2449 0
一起谈.NET技术,Visual Studio对程序集签名时一个很不好用的地方
  由于我们的项目底层使用到一个通过LogicalCallContext实现的上下文数据管理框架,导致所有的Unit Test不能正常运行。具体的现象在《只在UnitTest和WebHost中的出现的关于LogicalCallContext的严重问题》有过详细的介绍。
848 0