Monday, December 19, 2005

[OpenCV] Some Janpanse Turtorial

http://ace.seman.cs.uec.ac.jp/~takahashi/OpenCV/src/camshift.cpp

/**********************************************************************/
/* ● CamShift ( 連続順応手段変換 ) アルゴリズムの実装 ● */
/* */
/* 参照元:OpenCV ML でのメッセージ */
/* http://groups.yahoo.com/group/OpenCV/message/9679 */
/* */
/* リンク */
/* DirectShow : quartz.lib strmiids.lib strmbase.lib strmbasd.lib */
/* IPL&OpenCV : ipl.lib highgui.lib cv.lib */
/* */
/* 注意 */
/* iCamShift.h をコピーして持ってくる */
/* */
/* 2003.01.30. 高橋 */
/**********************************************************************/
/****************************************************/
/* メイン部分 */
/****************************************************/
// CamShift 実行
mycamshift.callback(image);
// ウィンドウを表示
cvShowImage( wndname, image );



/****************************************************/
/* グローバル宣言 */
/****************************************************/
#include "cv.h"
#include "streams.h"
#include "CV.hpp"
#include "iCamShift.h"
#include "highgui.h"
#include
static bool IsInit = false;
static bool IsTracking = false;
CvCamShiftTracker m_cCamShift;
CvCamShiftParams m_params;
CvRect m_object;
/***************************************************************/
/* コールバック (フレーム取得毎に呼ばれる) */
/***************************************************************/
void CMyCamShift::callback(IplImage *image)
{
if (IsTracking) // ● [分岐1] トラッキング状態なら
{
// CamShift を適用 (ヒストグラムを初期化しない)
ApplyCamShift(image, false);
// ヒストグラムモデルに一致する色分布に十字を描画
DrawCross(image);
}
else // ● [分岐1] トラッキング状態でなければ
{
// 解像度を取得
CvSize size = cvGetSize( image );
if (IsInit) // ● [分岐2] トラッキングボタンを押したら
{
// 確率分布の計算領域(始めの赤い四角) の計算
m_object.x = cvRound( size.width * m_params.x );
m_object.y = cvRound( size.height * m_params.y );
m_object.width = cvRound( size.width * m_params.width );
m_object.height = cvRound( size.height * m_params.height );
// CamShift を初めて適用 (ヒストグラムを初期化)
ApplyCamShift( image, true );
// トラッキングOK
IsTracking = true;
}
else // ● [分岐2] 初期状態ではここにくる
{
CvPoint p1, p2;
// 確率分布の計算領域(始めの赤い四角) の計算
p1.x = cvRound( size.width * 0.4f );
p1.y = cvRound( size.height * 0.3f );
p2.x = cvRound( size.width * (0.4f + 0.2f));
p2.y = cvRound( size.height * (0.3f + 0.3f));
// 計算領域を表示
cvRectangle( image, p1, p2, CV_RGB(255,0,0), 1);
}
}
}
/***************************************************************/
/* トラッキング開始 */
/***************************************************************/
void CMyCamShift::Start_Tracking()
{
m_params.x = 0.4f; // 確率分布の計算領域(始めの赤い四角) の初期倍率
m_params.y = 0.3f;
m_params.width = 0.2f;
m_params.height = 0.3f;
m_params.Smin = 20; // channel-1 の最小値
m_params.Vmin = 40; // channel-2 の最小値
m_params.Vmax = 255; // channel-2 の最大値
m_params.bins = 20; // ヒストグラムの数値
m_params.view = 0;
m_params.threshold = 0; // 閾値
IsInit = true; // 初期化OK
IsTracking = false; // トラッキングはまだ
}
/***************************************************************/
/* CamShift を適用 */
/***************************************************************/
void CMyCamShift::ApplyCamShift(IplImage *image, bool initialize)
{
CvSize size;
int bins = m_params.bins;
// 色ヒストグラムの設定
m_cCamShift.set_hist_dims( 1, &bins ); // ヒストグラム値
// m_cCamShift.set_thresh( 0, 1, 180 ); // (注)Beta_3 では除外
m_cCamShift.set_threshold( 0 ); // ヒストグラム閾値
m_cCamShift.set_min_ch_val( 1, m_params.Smin ); // channel-1 の最小値
m_cCamShift.set_max_ch_val( 1, 255 ); //      の最大値
m_cCamShift.set_min_ch_val( 2, m_params.Vmin ); // channel-2 の最小値
m_cCamShift.set_max_ch_val( 2, m_params.Vmax ); //      の最大値
// 画像データ取得
cvGetImageRawData( image, 0, 0, &size );
// 探索ウィンドウがアプリのウィンドウを超えた場合の処理
if( m_object.x < 0 ) m_object.x = 0;
if( m_object.x > size.width - m_object.width - 1 )
m_object.x = MAX(0, size.width - m_object.width - 1);
if( m_object.y < 0 ) m_object.y = 0;
if( m_object.y > size.height - m_object.height - 1 )
m_object.y = MAX(0, size.height - m_object.height - 1);
if( m_object.width > size.width - m_object.x )
m_object.width = MIN(size.width, size.width - m_object.x);
if( m_object.height > size.height - m_object.y )
m_object.height = MIN(size.height, size.height - m_object.y);
// 探索ウィンドウの位置をセット
m_cCamShift.set_window(m_object);
// 色ヒストグラムを初期化するならば
if( initialize )
{
// ヒストグラムをリセット
m_cCamShift.reset_histogram();
// 探索ウィンドウ内の色ヒストグラムを更新
m_cCamShift.update_histogram( (CvImage*)image );
}
// 探索ウィンドウ内の物体の位置を更新
m_cCamShift.track_object( (CvImage*)image );
// オブジェクトにフィットした探索ウィンドウに再設定
m_object = m_cCamShift.get_window();
}
/***************************************************************/
/* 十字を描画 */
/***************************************************************/
void CMyCamShift::DrawCross(IplImage *image)
{
float cs = (float)cos( m_cCamShift.get_orientation() );
float sn = (float)sin( m_cCamShift.get_orientation() );
int x = m_object.x + m_object.width / 2;
int y = m_object.y + m_object.height / 2;
CvPoint p1 = {(int)(x + m_cCamShift.get_length() * cs / 2),
(int)(y + m_cCamShift.get_length() * sn / 2)};
CvPoint p2 = {(int)(x - m_cCamShift.get_length() * cs / 2),
(int)(y - m_cCamShift.get_length() * sn / 2)};
CvPoint p3 = {(int)(x + m_cCamShift.get_width() * sn / 2),
(int)(y - m_cCamShift.get_width() * cs / 2)};
CvPoint p4 = {(int)(x - m_cCamShift.get_width() * sn / 2),
(int)(y + m_cCamShift.get_width() * cs / 2)};
cvLine( image, p1, p2, CV_RGB(255,0,0), 1, 8 ); // 長径
cvLine( image, p4, p3, CV_RGB(0,0,255), 1, 8 ); // 短径
// 以下はデバッグ用
if((p1.x != p2.x) && (p3.x != p4.x))
{
// 動的に変化する探索ウィンドウを表示
cvRectangle( image,
cvPoint(m_object.x, m_object.y),
cvPoint(m_object.x + m_object.width,
m_object.y + m_object.height),
CV_RGB(255,0,0), 1);
CvFont font;
cvInitFont( &font, CV_FONT_VECTOR0, 0.5, 0.5, 0.0, 2 );
cvPutText( image, "p1", p1, &font, CV_RGB(255,0,0));
cvPutText( image, "p2", p2, &font, CV_RGB(255,0,0));
cvPutText( image, "p3", p3, &font, CV_RGB(0,0,255));
cvPutText( image, "p4", p4, &font, CV_RGB(0,0,255));
}
// 十字が描けなくなったら設定をリセット
else
{
IsInit = false;
IsTracking = false;
}
}

No comments: