private void camshift(UnmanagedImage frame)
{
int width = frame.Width;
int height = frame.Height;
Rectangle area = new Rectangle(0, 0, width, height);
// Compute tracking object center
float objX = Math.Max(0, Math.Min(searchWindow.X + searchWindow.Width * 0.5f, width));
float objY = Math.Max(0, Math.Min(searchWindow.Y + searchWindow.Height * 0.5f, height));
float objAngle;
// Compute mean shift
CentralMoments moments = meanShift(frame);
SizeF objSize = moments.GetSizeAndOrientation(out objAngle);
if (Single.IsNaN(objSize.Width) || Single.IsNaN(objSize.Height) ||
Single.IsNaN(objAngle) || objSize.Width < 1 || objSize.Height < 1)
{
Reset();
return;
}
// Truncate to integer coordinates
IntPoint center = new IntPoint((int)objX, (int)objY);
Rectangle rec = new Rectangle((int)(objX - objSize.Width * 0.5f),
(int)(objY - objSize.Height * 0.5f),
(int)objSize.Width, (int)objSize.Height);
angleHistory.Push(objAngle);
// Create tracking object
IsSteady = checkSteadiness();
trackingObject.Rectangle = rec;
trackingObject.Center = center;
trackingObject.Angle = smooth ? (float)angleHistory.Mean : objAngle;
if (extract)
{
Rectangle inner = rec;
xHistory.Push(rec.X);
yHistory.Push(rec.Y);
widthHistory.Push(rec.Width);
heightHistory.Push(rec.Height);
inner.X = (int)xHistory.Mean;
inner.Y = (int)yHistory.Mean;
inner.Width = (int)widthHistory.Mean;
inner.Height = (int)heightHistory.Mean;
inner.Intersect(area);
Crop crop = new Crop(inner);
// TODO: Perform rotation of the extracted object
//RotateNearestNeighbor rotate = new RotateNearestNeighbor((objAngle - Math.PI / 2) * 180f / Math.PI, true);
//trackingObject.Image = rotate.Apply(crop.Apply(frame));
trackingObject.Image = crop.Apply(frame);
}
// Compute a new search window size
searchWindow.Width = (int)(1.1f * objSize.Width);
searchWindow.Height = (int)((aspectRatio != 0) ?
(aspectRatio * objSize.Width) : (1.1f * objSize.Height));
}