Media Kinect2014 day7

20
kinect演習 72014/11/18 神奈川工科大学 情報メディア学科 白井研究室

description

情報メディア専門ユニット Kinect演習 第7回 リファクタリング in Kinect SDK

Transcript of Media Kinect2014 day7

Page 1: Media Kinect2014 day7

kinect演習第7回

2014/11/18

神奈川工科大学情報メディア学科白井研究室

Page 2: Media Kinect2014 day7

課題6に追加

1. kinectの前を通過した人数をカウントするカウンター同時認識の管理

2. 5秒以上kinectの前にいた人数をカウントするカウンター

3. 撮影された曜日・時間の可視化(グラフ)

4. 身長と距離の関係をグラフで表す

KineMotionの実装

今回やること

Page 3: Media Kinect2014 day7

【Refactoring】外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること。

機能の見た目を変えずにコードを整理・再構築

自分の頭の整理、クラスの整理

複数人で分業できるようにする

Visual Studioの機能で「リファクター」もあるが、まずは自力で。

リファクタリングをしよう

Page 4: Media Kinect2014 day7

失敗してもいいようにブランチを切る ソリューションエクスプローラ右クリック→新しい項目の追加「MyGraphics.cs」を作成

usingの追加&移動 using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Kinect;

メンバの移動 public static float RenderWidth, RenderHeight; //constからstaticに変更 private DrawingGroup drawingGroup; private DrawingImage imageSource; ブラシ類(ただ移動すればよい)

private const double JointThickness = 3;private const double BodyCenterThickness = 10;private const double ClipBoundsThickness = 10;private readonly Brush centerPointBrush = Brushes.Blue;private readonly Brush trackedJointBrush = new SolidColorBrush(Color.FromArgb(255, 68, 192, 68));private readonly Brush inferredJointBrush = Brushes.Yellow;private readonly Pen trackedBonePen = new Pen(Brushes.Green, 6);private readonly Pen inferredBonePen = new Pen(Brushes.Gray, 1);

グラフィックス関係のクラス分け1/4

Page 5: Media Kinect2014 day7

メソッドの移動

DrawBone

DrawBonesAndJoints

RenderClippedEdges

SkeletonPointToScreenに変更

DepthImagePoint depthPoint = this.sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(skelpoint, DepthImageFormat.Resolution640x480Fps30);

このままではthisオブジェクトがないとsensorが取得できない

クラスのメンバに追加

private KinectSensor sensor; //現在動いているKinectセンサ

グラフィックス関係のクラス分け2/4

Page 6: Media Kinect2014 day7

SensorSkeletonFrameReady()の描画部分を移植

public void Update(KinectSensor givenSensor, Skeleton[] skeletons)

SensorとSkeletonsを受け取る以外、特に変更はない

MainWindow.xaml.csのMainWindowクラスにメンバ追加

MyGraphics gra; //MyGraphicsクラスを追加(@ver1.3)

(private KinectSensor sensor;の前あたり)

WindowLoaded()にオブジェクトの初期化を追加(DrawGroupがあったあたり)

gra = new MyGraphics();

this.Image.Source = gra.InitGraphics();

グラフィックス関係のクラス分け3/4

Page 7: Media Kinect2014 day7

MainWindow::SensorSkeletonFrameReady()に移植コードを呼ぶ

//using (DrawingContext dc = this.drawingGroup.Open())

gra.Update(this.sensor, skeletons);

これでクラス分割完了!

動作確認をしてコミットをかけよう!

(一発でビルド通ったらえらい)

git status (untracked files)

git add . (MyGrapchis.cs追加)

git commit –m “refactored..”

グラフィックス関係のクラス分け4/4

Page 8: Media Kinect2014 day7

Pull request & Merge!

Page 9: Media Kinect2014 day7

#region ~ #endregionでリージョンを切って見やすくする

Graphics初期化

Kinectセンサ初期化

Kinectセンサ終了

Kinectセンサ毎フレーム処理

着席モードの変更

SkeletonSaveボタン

セルフタイマー

インターバルタイマー

タイマーイベント処理 (TimerStopも移動してくくる)

PNG保存(すでにある)

リファクタリングが終わったら

Page 10: Media Kinect2014 day7

その他の処理

Kinectセンサ終了

着席モード

撮影関係

ずいぶんすっきりした!

ここで振り返り…

Graphics初期化

Kinect初期化

WindowLoaded()

SensorSkeletonFrameReady()1. Skeletons配列 skeletons2. Skeletonフレーム開く3. フレームがある場合、配列をskeletonsにコピー

4. グラフィックス更新gra.Update()

Page 11: Media Kinect2014 day7

“クラスダイアグラムで表示”

本日時点のクラス図

★そもそもクラスとは?

データ{Window, Kinect, Graphics}操作手順:MyGraphicsの場合…MyGraphics:コンストラクタInitGraphics:初期化Update():描画の毎フレーム更新処理DrawBone:ボーンを描くDrawBonesAndJoints:ボーンと関節両方描く

RenderClippedEdges:画面端の色線を描く

SkeletonPointToScreen:スクリーン座標への変換

↑あれ?

なんだろうこのクラスは…(次に続く)

Page 12: Media Kinect2014 day7

クラスダイアグラムでメソッド等をクリック、

「概要」に記述すると

関数の概要説明もカンタン!

ソースコードのコメントに適切なテキストが記述される!

タグについてMSDN「コードレポートの作成」も調べてみるとよい

Page 13: Media Kinect2014 day7

Console.WriteLine(“------”); を探してみよう(MyGraphics.cs)

「表示」メニューの「出力」で標準出力(stdout)が見れる

デバックしやすくする

Page 14: Media Kinect2014 day7

「出力」をよく観察してみよう

最大6名

Tracked/NotTracked

ID[0]は「認識されてない」ようだ

IDの添え字はどんどんふえていくぞ…

とはいえ、これは今までの人数ではなさそうだ…

右クリック「定義へ移動」でSDKのTrackingIDを調べてみよう

複数人検出状態を観察する

Page 15: Media Kinect2014 day7

冷静に考えてみよう、正しいのはどれか? Type A

GraphicsUpdate();

Hantei();

Type BHantei();

GraphicsUpdate();

Type CUpdate() {

Graphics1();

Hantei();

Graphics2();}

描画と認識処理を分ける!

Page 16: Media Kinect2014 day7

与えられた課題(1)~(4)を解決するコードを書きたい

現状のSkeletonBasicsはフレームごとに処理&描画

直近のフレームより前の状態を把握できそうでできない

同フレームにいる複数プレイヤーの状態を管理できない

Kinectの視界から抜けた/入ったを判定しない

もちろんアプリ内でad hoc(=限定目的)なコードを書くことも可(課題6+)

しかしせっかくなので

現在のプレイヤー認識状態を把握する「Skelutilクラス」を作成してみよう!

複数人検出状態を管理する

Page 17: Media Kinect2014 day7

Github/Kinect2014/ShiraiLab/ SkeletonBasics-Refactored から

Skelutil su; をMainWindowメンバに追加

「Kinectセンサ初期化」の直後に su = new Skelutil();

本当は、ここに初期化コードをいろいろ入れたいが今はとりあえず

Update(skeletons)をMyGraphicsから移動/分離

#region使って作業すると安全

Add()の実装

Dictionalyオブジェクトを使って実装

Skelutilクラスに分離

Page 18: Media Kinect2014 day7

SkelutilにSkeletonsを持たせる

MyGraphicsにはSkeletonsではなくsuを渡す

DateTime, TimeSpanを使って経過秒を表示

#if DEBUG ~ #endifをつかって標準出力を制御(Debug/Release)

Graphicsに値を渡す

Page 19: Media Kinect2014 day7

以下の機能をチームで実装①kinectの前を通過した人数(passed)をカウントするカウンター

Skel.TrackingIDが発行されたら passed++;

②5秒以上kinectの前にいた人数(watched)をカウントするカウンター

今回の演習でほぼできている。

・5秒たったら、 watched ++;

・Dictionaryを使って「いなくなった時刻」を記録できるとよい

③撮影された曜日・時間の可視化(グラフ)

「Save」ボタンにDictionaryオブジェクトのテキスト書き出しを実装済

Excelで見やすいCSVファイルにしてみよう→Excelでグラフ化

④身長と距離の関係をグラフで表す

ヒントはコードに書いてあります

完成品を、課題9として、11/24 19時までにGithub提出。

課題6に追加⇒課題9提出

Page 20: Media Kinect2014 day7

Position.YとPosition.Zの関係を記録する

Kinectから{1.5, 2.0, 2.5,..}mとZを変更していったとき、頭部のX,Yの値はどのように変化するか?

(=身長は変わらない、前後に移動しただけ)

<結果グラフの例>X = カメラに対して左をマイナス

④身長と距離の関係

Z[m]

Y[val]

1.5 2.0 2.5 3.0

X = +1.0mX = 0 mX = - 1.0m

Kinectの奥行特性