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.
0 comments:
Post a Comment