kinectのfacetrackを使って瞬きを検出したいのですが
kinectのfacetrackを使ってまばたきを検出したいのですが、前処理として画像のトリミング(目の周辺部分)を行わなければならないと思うのですが、トリミング処理がうまく行きませんがうまくいきません。良い方法はありますでしょうか?使っている言語はC#です。どうかよろしくお願いします。
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Kinect.Toolkit.FaceTracking;
namespace FaceTrackingCamera
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
// 解像度・フレームレート
private ColorImageFormat rgbFormat = ColorImageFormat.RgbResolution640x480Fps30;
private const DepthImageFormat depthFormat = DepthImageFormat.Resolution320x240Fps30;
// KinectSensorChooser
private KinectSensorChooser kinectChooser = new KinectSensorChooser();
// FaceTrackerオブジェクト
FaceTracker faceTracker = null;
// Kinectセンサーからの画像情報を受け取るバッファ
private byte[] pixelBuffer = null;
// Kinectセンサーからの深度情報を受け取るバッファ
private short[] depthBuffer = null;
// Kinectセンサーからの骨格情報を受け取るバッファ
private Skeleton[] skeletonBuffer = null;
// 画面に表示するビットマップ
private RenderTargetBitmap bmpBuffer = null;
// ビットマップへの描画用DrawingVisual
private DrawingVisual drawVisual = new DrawingVisual();
private WriteableBitmap bgImg2 = null;
private Int32Rect rectimg;
public MainWindow()
{
InitializeComponent();
}
// 初期化処理(Kinectセンサーやバッファ類の初期化)
private void WindowLoaded(object sender, RoutedEventArgs e)
{
kinectChooser.KinectChanged += KinectChanged;
kinectChooser.Start();
}
// 終了処理
private void WindowClosed(object sender, EventArgs e)
{
kinectChooser.Stop();
}
// Kinectセンサーの挿抜イベントに対し、初期化/終了処理を呼び出す
private void KinectChanged(object sender, KinectChangedEventArgs args)
{
if (args.OldSensor != null)
UninitKinectSensor(args.OldSensor);
if (args.NewSensor != null)
InitKinectSensor(args.NewSensor);
}
// Kinectセンサーの初期化
private void InitKinectSensor(KinectSensor kinect)
{
// ストリームの有効化
ColorImageStream clrStream = kinect.ColorStream;
clrStream.Enable(rgbFormat);
DepthImageStream depthStream = kinect.DepthStream;
depthStream.Enable(depthFormat);
SkeletonStream skelStream = kinect.SkeletonStream;
kinect.DepthStream.Range = DepthRange.Near;
skelStream.EnableTrackingInNearRange = true;
skelStream.TrackingMode = SkeletonTrackingMode.Seated;
skelStream.Enable();
// バッファの初期化
pixelBuffer = new byte[clrStream.FramePixelDataLength];
depthBuffer = new short[depthStream.FramePixelDataLength];
skeletonBuffer = new Skeleton[skelStream.FrameSkeletonArrayLength];
// 画面に表示するビットマップの初期化
bmpBuffer = new RenderTargetBitmap(clrStream.FrameWidth,clrStream.FrameHeight,96, 96, PixelFormats.Default);
bgImg2 = new WriteableBitmap(clrStream.FrameWidth, clrStream.FrameHeight, 96, 96, PixelFormats.Bgr32, null);
// イベントハンドラの登録
kinect.AllFramesReady += AllFramesReady;
faceTracker = new FaceTracker(kinect);
rectimg = new Int32Rect(0, 0, clrStream.FrameWidth, clrStream.FrameHeight);
}
// Kinectセンサーの終了処理
private void UninitKinectSensor(KinectSensor kinect)
{
if (faceTracker != null)
{
faceTracker.Dispose();
faceTracker = null;
}
kinect.AllFramesReady -= AllFramesReady;
}
// FrameReady イベントのハンドラ
// (Kinectセンサーの情報をもとにFaceTrackingを行い、
// 認識した顔の各点に赤い点を描画)
private void AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
KinectSensor kinect = sender as KinectSensor;
using (ColorImageFrame colorImageFrame = e.OpenColorImageFrame())
using (DepthImageFrame depthImageFrame = e.OpenDepthImageFrame())
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (colorImageFrame == null || depthImageFrame == null || skeletonFrame == null)
return;
// 顔の各点の座標を保持するバッファ
EnumIndexableCollection<FeaturePoint, Microsoft.Kinect.Toolkit.FaceTracking.PointF> facePoints = null;
EnumIndexableCollection<FeaturePoint, Vector3DF> facePoints3D = null;
colorImageFrame.CopyPixelDataTo(pixelBuffer);
depthImageFrame.CopyPixelDataTo(depthBuffer);
skeletonFrame.CopySkeletonDataTo(skeletonBuffer);
//描画の準備(左画面)
var drawContext1 = drawVisual.RenderOpen();
int frmWidth = colorImageFrame.Width;
int frmHeight = colorImageFrame.Height;
rgbImage.Source = bmpBuffer;
IPLImage.Source = bgImg2;
// カメラの画像情報から原画像のビットマップを作成し描画(左)
var bgImg1 = new WriteableBitmap(frmWidth, frmHeight, 96, 96, PixelFormats.Bgr32, null);
bgImg1.WritePixels(new Int32Rect(0, 0, frmWidth, frmHeight), pixelBuffer, frmWidth * 4, 0);
//右画面の原画像を追加
bgImg2.WritePixels(rectimg, pixelBuffer, frmWidth * 4, 0);
var rect1 = new System.Windows.Rect(0, 0, frmWidth, frmHeight);
drawContext1.DrawImage(bgImg1, rect1);
//System.Drawing.Pen pen = Pens.White;
foreach (Skeleton skeleton in skeletonBuffer)
{
// トラックできている骨格だけを対象とする
if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
{ // 今回のフレームにFaceTrackingを適用
FaceTrackFrame frame = faceTracker.Track(rgbFormat, pixelBuffer, depthFormat, depthBuffer, skeleton);
//顔情報が認識できなかった場合は0を書き出す
//1フレーム毎に顔情報情報を取得する
facePoints3D = frame.Get3DShape();
facePoints = frame.GetProjected3DShape();
var rect2 = new System.Windows.Rect(facePoints[15].X, facePoints[15].Y, 100, 50);
if (frame.TrackSuccessful)
{
//原画像の上から新たに描写
drawContext1.DrawRectangle(System.Windows.Media.Brushes.Red, null, rect2);
foreach (var facePt in facePoints)
{
// 取得した顔の各点に赤い点を描画(左)
var pt = new System.Windows.Point(facePt.X, facePt.Y);
drawContext1.DrawEllipse(System.Windows.Media.Brushes.Red, null, pt, 1, 1);
}
}
}
//if (facePoints != null) { }
}
// 画面に表示するビットマップに描画(左)
drawContext1.Close();
bmpBuffer.Render(drawVisual);
}
}
}
}