Emgucv_Motion_Detection_MotionHistory_Human_Activity_in_video
This topic introduces you to the function MotionHistory of emgucv .
The motion history image (MHI) is a static image template helps in understanding the motion location and path as it progresses.
In MHI, the temporal motion information is collapsed into a single image template where intensity is a function of recency of motion.
The MHI pixel intensity is a function of the motion history at that location, where brighter values correspond to a more recent motion.
Using MHI, moving parts of a video sequence can be engraved with a single image, from where one can predict the motion flow as well as the moving parts of the video action.
Video Effect
Algorithm1
=========================================================
for each time t
Bt := absolute_difference(It, It-1) > threshold
end for
=========================================================
Algorithm2
=========================================================
for each time t
for each pixel (x,y)
if Bt(x,y) = 1
MHIt(x,y) := τ
else if MHIt-1 ≠ 0
MHIt(x,y) := MHIt-1(x,y) - 1
else
MHIt(x,y) := 0
end if
end for
=========================================================
If you want to know more information about
motion history
you can see this video
Video1
Video2_Image Moments
Video3_MHI
Code
/** Copyright (c) 2016 Samuel <dryjoker007@gmail.com>** BSD Simplified License.* For information on usage and redistribution, and for a DISCLAIMER OF ALL**/using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using Emgu.CV;using Emgu.CV.Util;using Emgu.CV.Structure;using Emgu.CV.VideoSurveillance;using Emgu.CV.CvEnum;namespace emgucv2._4._2_ex{public partial class Form1 : Form{private Capture _capture = new Capture();private MotionHistory _motionHistory;private IBGFGDetector<Bgr> _forgroundDetector;public Form1(){InitializeComponent();//try to create the captureif (_capture == null){try{_capture = new Capture();}catch (NullReferenceException excpt){ //show errors if there is anyMessageBox.Show(excpt.Message);}}if (_capture != null) //if camera capture has been successfully created{_motionHistory = new MotionHistory(1.0, //in second, the duration of motion history you wants to keep0.05, //in second, maxDelta for cvCalcMotionGradient0.5); //in second, minDelta for cvCalcMotionGradient_capture.ImageGrabbed += ProcessFrame;_capture.Start();}}private void ProcessFrame(object sender, EventArgs e){using (Image<Bgr, Byte> image = _capture.RetrieveBgrFrame())using (MemStorage storage = new MemStorage()) //create storage for motion components{if (_forgroundDetector == null){//_forgroundDetector = new BGCodeBookModel<Bgr>();//_forgroundDetector = new FGDetector<Bgr>(Emgu.CV.CvEnum.FORGROUND_DETECTOR_TYPE.MOG);_forgroundDetector = new BGStatModel<Bgr>(image, Emgu.CV.CvEnum.BG_STAT_TYPE.FGD_STAT_MODEL);}_forgroundDetector.Update(image);capturedImageBox.Image = image.Bitmap;//update the motion history_motionHistory.Update(_forgroundDetector.ForgroundMask);//forgroundImageBox.Image = _forgroundDetector.ForgroundMask.Bitmap;#region get a copy of the motion mask and enhance its colordouble[] minValues, maxValues;Point[] minLoc, maxLoc;_motionHistory.Mask.MinMax(out minValues, out maxValues, out minLoc, out maxLoc);Image<Gray, Byte> motionMask = _motionHistory.Mask.Mul(255.0 / maxValues[0]);#endregion//create the motion imageImage<Bgr, Byte> motionImage = new Image<Bgr, byte>(motionMask.Size);//display the motion pixels in blue (first channel)motionImage[2] = motionMask;//Threshold to define a motion area, reduce the value to detect smaller motiondouble minArea = 150;storage.Clear(); //clear the storageSeq<MCvConnectedComp> motionComponents = _motionHistory.GetMotionComponents(storage);//iterate through each of the motion componentforeach (MCvConnectedComp comp in motionComponents){//reject the components that have small area;if (comp.area < minArea) continue;// find the angle and motion pixel count of the specific areadouble angle, motionPixelCount;_motionHistory.MotionInfo(comp.rect, out angle, out motionPixelCount);//reject the area that contains too few motionif (motionPixelCount < comp.area * 0.05) continue;//Draw each individual motion in red//DrawMotion(motionImage, comp.rect, angle, new Bgr(Color.Red));}// find and draw the overall motion angledouble overallAngle, overallMotionPixelCount;_motionHistory.MotionInfo(motionMask.ROI, out overallAngle, out overallMotionPixelCount);//DrawMotion(motionImage, motionMask.ROI, overallAngle, new Bgr(Color.Tomato));//Display the amount of motions found on the current imageUpdateText(String.Format("Total Motions found: {0}; Motion Pixel count: {1}", motionComponents.Total, overallMotionPixelCount));//Display the image of the motionmotionImageBox.Image = motionImage.Bitmap;}}private void UpdateText(String text){if (InvokeRequired && !IsDisposed){Invoke((Action<String>)UpdateText, text);}else{label1.Text = text;}}private static void DrawMotion(Image<Bgr, Byte> image, Rectangle motionRegion, double angle, Bgr color){float circleRadius = (motionRegion.Width + motionRegion.Height) >> 2;Point center = new Point(motionRegion.X + motionRegion.Width >> 1, motionRegion.Y + motionRegion.Height >> 1);CircleF circle = new CircleF(center,circleRadius);int xDirection = (int)(Math.Cos(angle * (Math.PI / 180.0)) * circleRadius);int yDirection = (int)(Math.Sin(angle * (Math.PI / 180.0)) * circleRadius);Point pointOnCircle = new Point(center.X + xDirection,center.Y - yDirection);LineSegment2D line = new LineSegment2D(center, pointOnCircle);image.Draw(circle, color, 1);image.Draw(line, color, 2);}private void Form1_FormClosed(object sender, FormClosedEventArgs e){_capture.Stop();}}}


留言
張貼留言