Changes between Version 34 and Version 35 of Tutorial/Practice0


Ignore:
Timestamp:
07/23/09 14:59:24 (8 years ago)
Author:
ddeguchi
Comment:

新しい動画の入出力に対応させた

Legend:

Unmodified
Added
Removed
Modified
  • Tutorial/Practice0

    v34 v35  
    196196'''パーティクルフィルタ'''を用いて"色特徴を用いて動画中のテニスボールを追跡する"というタスクを行うサンプルプログラムです。[[BR]] 
    197197入力動画はMPEG形式で、input.mpgという入力映像が必要です。[[BR]] 
    198 MPEGの読み書きについては、[wiki:Tutorial/Seminar4 MPEGの入出力]を参考にしてください。[[BR]] 
     198MPEGの読み書きについては、[wiki:Tutorial/Seminar4 ビデオの入出力]を参考にしてください。[[BR]] 
    199199サンプル動画は[//download/download.cgi?name=input.mpg こちら]から(約3MB)。[[BR]] 
    200200 
     
    208208#!cpp 
    209209#include <mist/mist.h> 
    210 #include <mist/io/mpeg.h> 
     210#include <mist/io/video.h> 
    211211#include <mist/random.h> 
    212212#include <mist/timer.h> 
     
    221221struct particle_type 
    222222{ 
    223         int             x; 
    224         int             y; 
    225         double  weight; 
     223        int     x; 
     224        int     y; 
     225        double  weight; 
     226 
    226227        particle_type( const int x0 = 0, const int y0 = 0, const double weight0 = 0.0 ) : x( x0 ), y( y0 ), weight( weight0 ) 
    227228        { 
     
    229230}; 
    230231 
    231 bool    initialize              ( mist::array1< particle_type > &particles, const image_type &image ); 
    232 bool    resample                ( mist::array1< particle_type > &particles, mist::uniform::random &urnd ); 
    233 bool    predict                 ( mist::array1< particle_type > &particles, mist::gauss::random &grnd ); 
    234 bool    weight                  ( mist::array1< particle_type > &particles, const image_type &image ); 
    235 bool    measure                 ( const mist::array1< particle_type > &particles, particle_type &result_particle ); 
    236 bool    show_rectangle  ( const particle_type &result_particle, image_type &image, mist::mpeg::output_video &out_video ); 
    237 bool    show_particle   ( const mist::array1< particle_type > &particles, image_type &image, mist::mpeg::output_video &out_video ); 
    238 double  likelihood              ( const int &x, const int &y, const image_type &image ); 
    239 bool    is_in_image             ( const int &x, const int &y, const image_type &image ); 
    240 bool    is_yellow               ( const mist::rgb< unsigned char > &color ); 
    241  
    242 int main() 
     232bool    initialize      ( mist::array1< particle_type > &particles, const image_type &image ); 
     233bool    resample        ( mist::array1< particle_type > &particles, mist::uniform::random &urnd ); 
     234bool    predict         ( mist::array1< particle_type > &particles, mist::gauss::random &grnd ); 
     235bool    weight          ( mist::array1< particle_type > &particles, const image_type &image ); 
     236bool    measure         ( const mist::array1< particle_type > &particles, particle_type &result_particle ); 
     237bool    show_rectangle  ( const particle_type &result_particle, image_type &image, mist::video::encoder &out_video ); 
     238bool    show_particle   ( const mist::array1< particle_type > &particles, image_type &image, mist::video::encoder &out_video ); 
     239double  likelihood      ( int x, int y, const image_type &image ); 
     240bool    is_in_image     ( int x, int y, const image_type &image ); 
     241bool    is_yellow       ( const mist::rgb< unsigned char > &color ); 
     242 
     243int main( int argc, char *argv[] ) 
    243244{ 
    244245        image_type                                              image; 
    245246        particle_type                                   result_particle; 
    246         mist::array1< particle_type >   particles( 500 );       // パーティクル数500とする 
    247         mist::mpeg::input_video                 in_video; 
    248         mist::mpeg::output_video                out_rect; 
    249         mist::mpeg::output_video                out_particle; 
     247        mist::array1< particle_type >   particles( 500 );   // パーティクル数500とする 
     248        mist::video::decoder                    in_video; 
     249        mist::video::mpeg1::encoder             out_rect; 
     250        mist::video::mpeg1::encoder             out_particle; 
    250251        mist::uniform::random                   urnd( std::clock( ) ); 
    251252        mist::gauss::random                             grnd( std::clock( ) ); 
    252253        mist::timer                                             time; 
    253          
     254 
    254255        // 入力mpegファイルのオープン 
    255         mist::mpeg::open( in_video, "input.mpg" ); 
    256         mist::mpeg::dump_format( in_video ); 
    257          
     256        in_video.open( "input.mpg" ); 
     257        in_video.dump( ); 
     258 
    258259        // 出力mpegファイル(結果表示用)のオープン 
    259         mist::mpeg::copy_format( in_video, out_rect ); 
    260         mist::mpeg::open( out_rect, "out_rect.mpg" ); 
    261         mist::mpeg::dump_format( out_rect ); 
    262          
     260        out_rect.open( "out_rect.mpg" ); 
     261        out_rect.dump( ); 
     262 
    263263        // 出力mpegファイル(パーティクル表示用)のオープン 
    264         mist::mpeg::copy_format( in_video, out_particle );       
    265         mist::mpeg::open( out_particle, "out_particle.mpg" ); 
    266         mist::mpeg::dump_format( out_particle ); 
    267          
     264        out_particle.open( "out_particle.mpg" ); 
     265        out_particle.dump( ); 
     266 
    268267        // パーティクルの初期値を決定する 
    269268        unsigned int i = 0; 
    270269        std::cout << "\r" << "フレーム:" << i; 
    271         mist::mpeg::read_frame( in_video, image ); 
    272         initialize( particles, image );  
    273          
    274         while( mist::mpeg::read_frame( in_video, image ) ) 
    275         { 
     270        in_video >> image; 
     271        initialize( particles, image );  
     272 
     273        while( !in_video.is_eof( ) ) 
     274        { 
     275                in_video >> image; 
     276 
    276277                std::cout << "\r" << "フレーム:" << i ++; 
     278 
    277279                // パーティクルのリサンプリング 
    278280                resample( particles, urnd ); 
     281 
    279282                // 各パーティクルの予測 
    280283                predict( particles, grnd ); 
     284 
    281285                // 各パーティクルを尤度に従い重み付け 
    282286                weight( particles, image ); 
     287 
    283288                // 観測 
    284289                measure( particles, result_particle ); 
     290 
    285291                // 出力 
    286292                show_rectangle( result_particle, image, out_rect ); 
    287293                show_particle( particles, image, out_particle ); 
    288294        } 
    289          
     295 
    290296        // 入力・出力mpegファイルのクローズ 
    291         mist::mpeg::close( in_video ); 
    292         mist::mpeg::close( out_rect ); 
    293         mist::mpeg::close( out_particle ); 
    294          
     297        in_video.close( ); 
     298        out_rect.close( ); 
     299        out_particle.close( ); 
     300 
    295301        // 経過時間を表示 
    296302        std::cout << std::endl << time << std::endl; 
    297          
    298         return 0; 
     303 
     304        return( 0 ); 
    299305} 
    300306 
    301307// パーティクルの初期値を決定する 
    302 bool initialize                 ( mist::array1< particle_type > &particles, 
    303                                                   const                                                 image_type      &image ) 
     308bool initialize( mist::array1< particle_type > &particles, const image_type &image ) 
    304309{ 
    305310        particle_type max_particle( 0, 0, 0.0 ); 
    306          
     311 
    307312        // 最も尤度の高いピクセルを探索 
    308313        for( size_t j = 0 ; j < image.height( ) ; j ++ ) 
     
    317322                } 
    318323        } 
    319          
     324 
    320325        // すべてのパーティクルの値を最尤値で設定する 
    321326        for( size_t i = 0 ; i < particles.size( ) ; i ++ ) 
     
    324329        } 
    325330 
    326         return true; 
     331        return( true ); 
    327332} 
    328333 
    329334// パーティクルのリサンプリング 
    330 bool resample                   ( mist::array1< particle_type > &particles,  
    331                                                   mist::uniform::random                 &urnd ) 
    332 { 
    333     //省略(サンプルコード1参照) 
     335bool resample( mist::array1< particle_type > &particles, mist::uniform::random &urnd ) 
     336{ 
     337        // 累積重みの計算 
     338        mist::array1< double > weights( particles.size( ) ); 
     339        weights( 0 ) = particles( 0 ).weight; 
     340        for( size_t i = 1 ; i < weights.size( ) ; i ++ ) 
     341        { 
     342                weights( i ) = weights( i - 1 ) + particles( i ).weight; 
     343        } 
     344 
     345        // 重みを基準にパーティクルをリサンプリングして重みを1.0に 
     346        mist::array1< particle_type > tmp_particles = particles; 
     347        for( size_t i = 0 ; i < particles.size( ) ; i ++ ) 
     348        { 
     349                const double weight = urnd.real2( ) * weights( weights.size( ) - 1 ); 
     350                size_t n = 0; 
     351                while( weights( ++ n ) < weight ); 
     352                particles( i ) = tmp_particles( n ); 
     353                particles( i ).weight = 1.0; 
     354        } 
     355 
     356        return( true ); 
    334357} 
    335358 
    336359 
    337360// 各パーティクルの予測 
    338 bool predict                    ( mist::array1< particle_type > &particles, 
    339                                                   mist::gauss::random                   &grnd ) 
    340 { 
    341     //省略(サンプルコード2参照) 
     361bool predict( mist::array1< particle_type > &particles, mist::gauss::random &grnd ) 
     362{ 
     363        const double variance = 13.0; 
     364 
     365        // 位置の予測 
     366        // 「次状態もほぼ同じ位置(ほとんど動かない)」と仮定、分散(13.0)は実験的に決定 
     367        for( size_t i = 0 ; i < particles.size( ) ; i ++ ) 
     368        { 
     369                double vx = grnd.generate( ) * variance; 
     370                double vy = grnd.generate( ) * variance; 
     371 
     372                particles( i ).x += static_cast< int >( vx ); 
     373                particles( i ).y += static_cast< int >( vy ); 
     374        } 
     375 
     376        return( true ); 
    342377} 
    343378 
    344379// 各パーティクルを尤度に従い重み付け 
    345 bool weight                     ( mist::array1< particle_type > &particles, 
    346                                           const image_type                              &image ) 
    347 { 
    348     //省略(サンプルコード3-2参照) 
     380bool weight( mist::array1< particle_type > &particles, const image_type &image ) 
     381{ 
     382        // 尤度に従いパーティクルの重みを決定する 
     383        double sum_weight = 0.0; 
     384        for( size_t i = 0 ; i < particles.size( ) ; i++ ) 
     385        { 
     386                particles( i ).weight = likelihood( particles( i ).x, particles( i ).y, image ); 
     387                sum_weight += particles( i ).weight; 
     388        } 
     389        // 重みの正規化 
     390        for( size_t i = 0; i < particles.size( ) ; i++ ) 
     391        { 
     392                particles( i ).weight = ( particles( i ).weight / sum_weight ) * particles.size( ); 
     393        } 
     394 
     395        return( true ); 
    349396} 
    350397 
    351398// 観測 
    352 bool measure                    ( const mist::array1< particle_type >   &particles, 
    353                                                   particle_type                                                 &result_particle ) 
    354 { 
    355     //省略(サンプルコード4参照) 
     399bool measure( const mist::array1< particle_type > &particles, particle_type &result_particle ) 
     400{ 
     401        double  x = 0.0; 
     402        double  y = 0.0; 
     403        double  weight = 0.0; 
     404 
     405        // 重み和 
     406        for( size_t i = 0 ; i < particles.size( ) ; i ++ ) 
     407        { 
     408                x       += particles[ i ].x         * particles[ i ].weight; 
     409                y       += particles[ i ].y         * particles[ i ].weight; 
     410                weight  += particles[ i ].weight; 
     411        } 
     412 
     413        // 正規化 
     414        result_particle.x       = static_cast< int >( x / weight ); 
     415        result_particle.y       = static_cast< int >( y / weight ); 
     416        result_particle.weight  = 1.0;      // 任意 
     417 
     418        return( true ); 
    356419} 
    357420 
    358421// 尤度を計算する 
    359 double likelihood               ( const int                     &x, 
    360                                                   const int                     &y, 
    361                                                   const image_type      &image ) 
    362 { 
    363     //省略(サンプルコード3-1参照) 
     422double likelihood( int x, int y, const image_type &image ) 
     423{ 
     424        const int width  = 30; 
     425        const int height = 30; 
     426 
     427        // 今回はパーティクルを中心とした30x30の矩形領域に 
     428        // 指定した範囲の色の存在率を尤度とした 
     429        size_t count = 0; 
     430        for( int j = y - height / 2 ; j < y + height / 2 ; j ++ ) 
     431        { 
     432                for( int i = x - width / 2 ; i < x + width / 2 ; i ++ ) 
     433                {                
     434                        if( is_in_image( i, j, image ) && is_yellow( image( i, j ) ) ) 
     435                        { 
     436                                count++; 
     437                        } 
     438                } 
     439        } 
     440        if( count == 0 ) 
     441        { 
     442                return( 0.0001 ); 
     443        } 
     444        else 
     445        { 
     446                return( static_cast< double >( count ) / ( width * height ) ); 
     447        } 
    364448} 
    365449 
     
    368452 
    369453// (x,y)が画像内に収まっているかどうか 
    370 bool is_in_image                ( const int                     &x,  
    371                                                   const int                     &y,  
    372                                                   const image_type      &image ) 
    373 { 
    374         return 0 <= x && x < static_cast< int >( image.width( ) ) && 0 <= y && y < static_cast< int >( image.height( ) ); 
     454bool is_in_image( int x, int y, const image_type &image ) 
     455{ 
     456        return( 0 <= x && x < static_cast< int >( image.width( ) ) && 0 <= y && y < static_cast< int >( image.height( ) ) ); 
    375457} 
    376458 
    377459// color(RGB値)が指定した範囲の色か 
    378 bool is_yellow                  ( const mist::rgb< unsigned char > &color ) 
    379 { 
    380         return color.r > 200 && color.g > 200 && color.b < 150; 
     460bool is_yellow( const mist::rgb< unsigned char > &color ) 
     461{ 
     462        return( color.r > 200 && color.g > 200 && color.b < 150 ); 
    381463} 
    382464 
    383465// 結果を矩形で出力 
    384 bool show_rectangle             ( const particle_type           &particle, 
    385                                                   image_type                            &image, 
    386                                                   mist::mpeg::output_video      &out_video ) 
     466bool show_rectangle( const particle_type &particle, image_type &image, mist::video::encoder &out_video ) 
    387467{ 
    388468        const size_t width  = 30; 
    389469        const size_t height = 30; 
    390470 
    391         const int rect_top              = particle.y - static_cast< int >( height / 2 ); 
    392         const int rect_bottom   = particle.y + static_cast< int >( height / 2 ); 
    393         const int rect_left             = particle.x - static_cast< int >( width  / 2 ); 
    394         const int rect_right    = particle.x + static_cast< int >( width  / 2 ); 
    395          
     471        const int rect_top      = particle.y - static_cast< int >( height / 2 ); 
     472        const int rect_bottom   = particle.y + static_cast< int >( height / 2 ); 
     473        const int rect_left     = particle.x - static_cast< int >( width  / 2 ); 
     474        const int rect_right    = particle.x + static_cast< int >( width  / 2 ); 
     475 
    396476        //// 検出・追跡の結果を赤色の矩形で表示 
    397         mist::draw_line( image, rect_left,      rect_top,               rect_right,     rect_top,               mist::rgb< unsigned char >( 255, 0, 0 ) );      //上端 
    398         mist::draw_line( image, rect_left,      rect_bottom,    rect_right,     rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );      //下端 
    399         mist::draw_line( image, rect_left,      rect_top,               rect_left,      rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );      //左端 
    400         mist::draw_line( image, rect_right,     rect_top,               rect_right,     rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );      //右端 
    401         mist::mpeg::write_frame( out_video, image ); 
    402  
    403         return true; 
     477        mist::draw_line( image, rect_left,  rect_top,       rect_right, rect_top,       mist::rgb< unsigned char >( 255, 0, 0 ) );  //上端 
     478        mist::draw_line( image, rect_left,  rect_bottom,    rect_right, rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );  //下端 
     479        mist::draw_line( image, rect_left,  rect_top,       rect_left,  rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );  //左端 
     480        mist::draw_line( image, rect_right, rect_top,       rect_right, rect_bottom,    mist::rgb< unsigned char >( 255, 0, 0 ) );  //右端 
     481 
     482        out_video << image; 
     483 
     484        return( true ); 
    404485} 
    405486 
    406487// パーティクルを出力 
    407 bool show_particle              ( const mist::array1< particle_type >   &particles, 
    408                                                   image_type                                                    &image, 
    409                                                   mist::mpeg::output_video                              &out_video ) 
    410 {        
     488bool show_particle( const mist::array1< particle_type > &particles, image_type &image, mist::video::encoder &out_video ) 
     489{    
    411490        // パーティクルのあるピクセルは、画素値=rgb(255,0,0) 
    412491        for( size_t i = 0 ; i < particles.size( ) ; i ++ ) 
     
    417496                } 
    418497        } 
    419         mist::mpeg::write_frame( out_video, image ); 
    420  
    421         return true; 
     498 
     499        out_video << image; 
     500 
     501        return( true ); 
    422502} 
    423503}}}