public Form1()
{
InitializeComponent();
AcquireInputVideo();
Application.Idle += new EventHandler(Optical_Flow_Worker);
}
void Optical_Flow_Worker(object sender, EventArgs e)
{
// If there are still frames to process
//We position at the current frame
Input_Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES, ActualFrameNumber);
// We grab the current frame
ActualFrame = Input_Capture.QueryFrame().Flip(Emgu.CV.CvEnum.FLIP.HORIZONTAL);
ActualGrayFrame = ActualFrame.Convert<Gray, Byte>();
// the next frame
NextFrame = Input_Capture.QueryFrame().Flip(Emgu.CV.CvEnum.FLIP.HORIZONTAL); ;
NextGrayFrame = NextFrame.Convert<Gray, Byte>();
// We extract some features to be tracked to compute optical flow
ActualFeature = ActualGrayFrame.GoodFeaturesToTrack(300, 0.01d, 0.01d, 5);
// FindCornerSubPix performa a better keypoints localization, it's a little improvement over GoodFeaturesToTrack
ActualGrayFrame.FindCornerSubPix(ActualFeature, new System.Drawing.Size(10, 10), new System.Drawing.Size(-1, -1), new MCvTermCriteria(20, 0.3d));
// Compute optical flow using Lukas Kanade Method
OpticalFlow.PyrLK(ActualGrayFrame, NextGrayFrame, ActualFeature[0], new System.Drawing.Size(10, 10), 3, new MCvTermCriteria(20, 0.03d), out NextFeature, out Status, out TrackError);
OpticalFlowFrame = new Image<Bgr, Byte>(ActualFrame.Width, ActualFrame.Height);
OpticalFlowFrame = NextFrame.Copy();
// We draw some vectors to visualize optical flow result
for (int i = 0; i < ActualFeature[0].Length ; i++)
{
DrawFlowVectors(i);
}
ActualFrameNumber++;
// Frame binding to emguCV imageboxes
//imageBoxActualFrame.Image = ActualFrame.ToBitmap();
// imageBoxNextFrame.Image = NextFrame.ToBitmap();
imageBoxOpticalFlow.Image = OpticalFlowFrame.ToBitmap();
}
private void DrawFlowVectors(int i)
{
System.Drawing.Point p = new Point();
System.Drawing.Point q = new Point();
p.X = (int)ActualFeature[0][i].X;
p.Y = (int)ActualFeature[0][i].Y;
q.X = (int)NextFeature[i].X;
q.Y = (int)NextFeature[i].Y;
double angle;
angle = Math.Atan2((double)p.Y - q.Y, (double)p.X - q.X);
LineSegment2D line = new LineSegment2D(p, q);
OpticalFlowFrame.Draw(line, new Bgr(255, 255, 255), 1);
p.X = (int)(q.X + 20 * Math.Cos(angle + Math.PI / 4));
p.Y = (int)(q.Y + 20 * Math.Sin(angle + Math.PI / 4));
OpticalFlowFrame.Draw(new LineSegment2D(p, q), new Bgr(255, 255, 255), 1);
p.X = (int)(q.X + 20 * Math.Cos(angle - Math.PI / 4));
p.Y = (int)(q.Y + 20 * Math.Sin(angle - Math.PI / 4));
OpticalFlowFrame.Draw(new LineSegment2D(p, q), new Bgr(255, 255, 255), 1);
}
private void AcquireInputVideo()
{
Input_Capture = new Capture();
Input_Capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH,500);
Input_Capture.QueryFrame();
Input_height = Input_Capture.Height;
Input_width = Input_Capture.Width;
}