I’ve been blogging recently about some of my experiments with the Kinect for Windows v2 developer preview. Most of my experiments have been based on the supplied samples, with a lot of copy and paste action. I’ve pulled some of the repeated code into some re-usable classes.
Here’s some code that I’ve moved out of the samples into a reusable component that measures frames-per-second and the amount of time taken per frame. The code provided here is based on the original samples, modified slightly. Free as in beer, though I doubt any of you will buy me beer so let’s just say “free”.
Example how to use:
public class MainWindow : Window, INotifyPropertyChanged { private FrameCounter _frameCounter; private KinectSensor _sensor; private DepthFrameReader _reader; public MainWindow() { InitializeComponent(); _frameCounter = new FrameCounter(); _frameCounter.PropertyChanged += (o,e) => StatusText = String.Format("FPS = {0:N1} / CPU = {1:N6}", _frameCounter.FramesPerSecond, _frameCounter.CpuTimePerFrame); _sensor = KinectSensor.Default; _sensor.Open(); _reader = sensor.DepthFrameSource.OpenReader(); _reader.FrameArrived += FrameArrived; this.DataContext = this; } private void FrameArrived(object sender, DepthFrameArrivedEventArgs e) { var reference = e.FrameReference; DepthFrame depthFrame = null; try { // increment the frame counter using (_frameCounter.Increment()) { depthFrame = reference.AcquireFrame(); // do work with depth data... } // disposing the frame counter will calculate CPU time for this block } catch { } finally { if (depthFrame != null) depthFrame.Dispose(); } } }
Expand the block below for code goodness.
public class FrameCounter : INotifyPropertyChanged { private Stopwatch _stopWatch; private uint _framesSinceUpdate = 0; private DateTime _nextStatusUpdate = DateTime.MinValue; private CpuCounter _cpuCounter; private double _fps; private double _cpuTime; public FrameCounter() { _stopWatch = new Stopwatch(); _cpuCounter = new CpuCounter(this); } public double FramesPerSecond { get { return _fps; } protected set { if (_fps != value) { _fps = value; NotifyPropertyChanged("FramesPerSecond"); } } } public double CpuTimePerFrame { get { return _cpuTime; } protected set { if (_cpuTime != value) { _cpuTime = value; NotifyPropertyChanged("CpuTimePerFrame"); } } } public event PropertyChangedEventHandler PropertyChanged; public void DeferFrameCount(TimeSpan timeToWait) { this._nextStatusUpdate = DateTime.Now + timeToWait; } public IDisposable Increment() { this._framesSinceUpdate++; if (DateTime.Now >= this._nextStatusUpdate) { double fps = 0.0; double cpuTime = 0.0; if (this._stopWatch.IsRunning) { this._stopWatch.Stop(); fps = this._framesSinceUpdate / this._stopWatch.Elapsed.TotalSeconds; cpuTime = this._cpuTime / fps; this._stopWatch.Reset(); } this._nextStatusUpdate = DateTime.Now + TimeSpan.FromSeconds(1); this.FramesPerSecond = fps; this.CpuTimePerFrame = cpuTime; } if (!this._stopWatch.IsRunning) { this._framesSinceUpdate = 0; this._cpuTime = 0; this._stopWatch.Start(); } _cpuCounter.Reset(); return _cpuCounter; } internal void IncrementCpuTime(double amount) { _cpuTime += amount; } public void Reset() { _nextStatusUpdate = DateTime.MinValue; _framesSinceUpdate = 0; FramesPerSecond = 0; CpuTimePerFrame = 0; } protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public class CpuCounter : IDisposable { FrameCounter _parent; Stopwatch _stopWatch; internal CpuCounter(FrameCounter parent) { _parent = parent; _stopWatch = new Stopwatch(); } public TimeSpan Elapsed { get { return _stopWatch.Elapsed; } } public void Reset() { _stopWatch.Reset(); if (!_stopWatch.IsRunning) { _stopWatch.Start(); } } public void Dispose() { _stopWatch.Stop(); _parent.IncrementCpuTime(_stopWatch.Elapsed.TotalMilliseconds); } } }
Happy coding.
No comments:
Post a Comment