How can I implement a simple motion-detection method using EMGUCV? I have searched for applicable examples, but the only solutions I found were too complicated to implement.
Is there a way I can implement a simple method to detect motion in order to trigger something in my application?
Convert a single frame to grayscale.
Convert a new frames from real time into grayscale.
Make abstractions between the first frame and new frame from real time.
The result of this is a third, new frame comprised of the differences between the first two. Use erosion and thresholding for that to get a frame with white representing the motioned section and black representing the rest of the space.
Here is a piece of code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.UI;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System.Diagnostics;
using System.IO;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using System.Drawing.Imaging;
namespace ptuxiakh___
{
public partial class Form1 : Form
{
Capture _capture = new Capture();
Capture capture2 = new Capture();
Image<Bgr, Byte> FirstImage = new Image<Bgr, Byte>(640, 480);
Image<Bgr, Byte> RealTimeImage = new Image<Bgr, Byte>(640, 480);
Image<Gray, Byte> des = new Image<Gray, Byte>(640, 480);
Image<Gray, Byte> thres = new Image<Gray, Byte>(640, 480);
Image<Gray, Byte> eroded = new Image<Gray, Byte>(640, 480);
bool baground = false;
private void Background()
{
try{
FirstImage = _capture.QueryFrame();
background = true;
}
catch(Exception e)
{
baground = false;
}
}
private void Tracking(object sender, EventArgs e)
{
if (baground == true)
{
RealTimeImage = capture2.QueryFrame();
CvInvoke.cvAbsDiff(FirstImage.Convert<Gray, Byte>(), RealTimeImage.Convert<Gray, Byte>(), des);
CvInvoke.cvThreshold(des, thres, 20, 255, THRESH.CV_THRESH_BINARY);
CvInvoke.cvErode(thres, eroded, IntPtr.Zero, 2);
}
else
{
Background(); // At first trying to get a static frame for
// abstraction with real time frame
}
}
private void StartButton_Click(object sender, EventArgs e)
{
Application.Idle += new EventHandler(Tracking);
}
private void Stopbutton_Click(object sender, EventArgs e)
{
Application.Idle -= new EventHandler(Tracking);
}
//eroded will be your relust
Related
After I connect to USB camera, and read a frame, and convert to bitmap,
it crashes after I write bitmap to PictureBox.
I'm developing a Visual Studio 2017 Pro C# Windows forms project.
Also, if I debug process_video_NewFrame() and step through it, then crash 'Parameter is not valid.' occurs at line in Program.cs:
Application.Run(new Control_Panel()).
Control_Panel.cs
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 System.Drawing;
using Accord.Video;
using Accord.Video.DirectShow;
namespace ACCORD_WindowsFormsApp9
{
public partial class Control_Panel : Form
{
VideoCaptureDevice videoSource;
Bitmap bitmap;
public Control_Panel()
{
InitializeComponent();
}
private void button_Start_Frame_Captcha_Click(object sender, EventArgs e)
{
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(process_video_NewFrame);
videoSource.Start();
}
// The video_NewFrame used in the example above could be defined as:
private void process_video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// get new frame
bitmap = eventArgs.Frame;
System.Windows.Forms.Application.DoEvents();
this.pictureBoxLatestCameraFrame.Image = bitmap;
}
private void button_Stop_Frame_Captcha_Click(object sender, EventArgs e)
{
videoSource.SignalToStop();
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ACCORD_WindowsFormsApp9
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Control_Panel());
}
}
}
Fixed! Thanks, Sriram. Keep that crystal ball polished... New to Bitmap, I mistakenly assumed it was an image, when actually it is an object, and so requires a new instance each iteration, ie...
private void process_video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// Ax previous Bitmap object:
if( loops > 0 )
{
camera_snapshot_bitmap.Dispose();
}
// get new frame
camera_snapshot_bitmap = new Bitmap( eventArgs.Frame );
//ax System.Windows.Forms.Application.DoEvents();
this.pictureBoxLatestCameraFrame.Image = camera_snapshot_bitmap;
++loops;
Console.WriteLine("Loops " + loops );
}
I am using EmguCV with C#, I am facing a problem when I want to grab frames from my web cam, red underline appears on statement:
imgOrg = capturecam.QueryFrame();
error: Cannot implicitly convert type 'Emgu.CV.Mat' to 'Emgu.CV.Image
how can I solve this problem?
my code:
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.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
namespace test2
{
public partial class Form1 : Form
{
Image<Bgr, Byte> imgOrg; //image type RGB (or Bgr as we say in Open CV)
private Capture capturecam;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
capturecam = new Capture();
}
catch (NullReferenceException exception)
{
MessageBox.Show(exception.Message);
return;
}
Application.Idle += new EventHandler(ProcessFunction);
}
private void ProcessFunction(object sender, EventArgs arg)
{
imgOrg = capturecam.QueryFrame(); // error line
imageBox1.Image = imgOrg;
}
}
}
This statement works:
Image<Bgr, Byte> img = mat.ToImage<Bgr, Byte>();
Try this:
imgOrg = capturecam.QueryFrame().ToImage<Bgr, Byte>();
Look here:
how to convert mat to image in (Emgu CV version 3) in c#?
Or change your Image variable to Mat:
Mat imgOrg = new Mat(); // instead of: Image<Bgr, Byte> imgOrg;
imgOrg = capture.QueryFrame();
imageBox1.Image = imgOrg;
imgOrg = new Image(capturecam.QueryFrame().Bitmap);
This Code Worked For me. I hope working for you too.
This is pretty straight forward. This works in Emgu CV 3.3++.
vidCap = new VideoCapture([filename or webcam device]);
Mat mat = new Mat();
vidCap.Read(mat); //This calls Grab() as grabbing a frame and then Retrieve();
imageBox1.Image = mat.Bitmap;
Image FRAME2= frame.ToImage();
Reference the example, the QueryFrame() not be used anymore at EmguCV 3.0. it be replaced by Retrieve() function.
Sample as shown below:
Mat frame = new Mat();
cap.Retrieve(frame, 0);
Mat grayFrame = new Mat();
CvInvoke.CvtColor(frame, grayFrame, ColorConversion.Bgr2Gray);
imageBox1.Image = frame;
imageBox2.Image = grayFrame;
I am showing a simple version of my project which i am trying to develop.I continuously getting error in haarCascade.cs that TypeIntilizationException was unhandled.This is my code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
using Emgu.CV.CvEnum;
using System.IO;
namespace Browseface
{
public partial class Form1 : Form
{
private HaarCascade haar;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
haar = new HaarCascade(#"C:\Users\Balram\Desktop\Frontal Face HaarCascades\Frontal Face HaarCascades\haarcascade_frontalface_alt_tree.xml");
}
catch (Exception ae)
{
}
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Image inputimg = Image.FromFile(#"C:\Users\Balram\Desktop\ad.jpg");
Image<Bgr, byte> imageframe = new Image<Bgr, byte>(new Bitmap(inputimg));
if (imageframe != null)
{
Image<Gray, byte> grayform = imageframe.Convert<Gray, byte>();
var faces =
grayform.DetectHaarCascade(haar, 1.4, 4, HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(25, 25))[0];
foreach (var face in faces)
{
imageframe.Draw(face.rect, new Bgr(Color.Green), 3);
}
pictureBox1.Image = imageframe.ToBitmap();
}
}
catch (Exception at)
{
}
}
}
}
In my HaarCascade.cs file in this following line i getting an error
protected override void DisposeObject()
{
CvInvoke.cvReleaseHaarClassifierCascade(ref _ptr);
}
That TypeIntilizationException was unhandled.
(I already add in references Emgu.CV ,Emgu.CV.UI and Emgu.util dll files
I'm developing a uniform fitting application, the program will take a picture of you and from that picture it will give you your polo/blouse size (Small, Medium, Large, X-Large)
My problem is how will I know if the user using the program has the size of Small? Medium? or Large?
here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.Util;
namespace fitting
{
public partial class Form1 : Form
{
HaarCascade UpperBody = new HaarCascade("haarcascade_mcs_upperbody.xml");
HaarCascade LowerBody = new HaarCascade("haarcascade_lowerbody.xml");
Capture camera;
bool captureProcess = false;
Image<Bgr, Byte> img;
public Form1()
{
InitializeComponent();
}
void viewImage(object sender, EventArgs e)
{
img = camera.QueryFrame();
if (img == null)
return;
CamImageBox.Image = img;
}
private void btnCapture_Click(object sender, EventArgs e)
{
if (captureProcess == true)
{
string data;
Application.Idle -= viewImage;
captureProcess = false;
SaveFileDialog dlg = new SaveFileDialog();
//dlg="Image|*.jpg;*png";
if (dlg.ShowDialog() == DialogResult.OK)
{
img.ToBitmap().Save(dlg.FileName + ".jpg", System.Drawing.Imaging.ImageFormat.Png);
data = dlg.FileName + ".jpg";
}
measureImage();
}
}
void measureImage()
{
OpenFileDialog dlg2 = new OpenFileDialog();
dlg2.Filter = "Image|*.jpg;*png";
if (dlg2.ShowDialog() == DialogResult.OK)
{
Image<Bgr, Byte> frame = new Image<Bgr, byte>(dlg2.FileName);
Image<Gray, Byte> Gray_Frame = frame.Convert<Gray, Byte>();
//1.985603925968
MCvAvgComp[][] LowerBodyDetect = Gray_Frame.DetectHaarCascade(
LowerBody,
1.985603925968,
0,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
new Size());
MCvAvgComp[][] UpperBodyDetect = Gray_Frame.DetectHaarCascade(
UpperBody,
1.3,
5,
Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
new Size());
//foreach (MCvAvgComp Upp_Body in UpperBodyDetect[0])
//{
// frame.Draw(Upp_Body.rect, new Bgr(Color.Red), 2);
// double width = (Upp_Body.rect.Width * 0.264583333);
// textBox1.Text = (Convert.ToString(width));
//}
try
{
frame.Draw(UpperBodyDetect[0][0].rect, new Bgr(Color.Red), 2);
double width = (UpperBodyDetect[0][0].rect.Width);
textBox1.Text = (Convert.ToString(width));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
//foreach (MCvAvgComp Low_Body in LowerBodyDetect[0])
//{
// frame.Draw(Low_Body.rect, new Bgr(Color.Green), 2);
//}
try
{
frame.Draw(LowerBodyDetect[0][0].rect, new Bgr(Color.Green), 2);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
CamImageBox.Image = frame;
}
}
private void Form1_Load(object sender, EventArgs e)
{
bool useCam = false;
if (!useCam)
measureImage();
else {
try
{
camera = new Capture();
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
return;
}
Application.Idle += viewImage;
captureProcess = true;
}
}
}
}
Your first problem is that your users can have various angle of views with different webcams.
Second problem is that you have to estimate the distance from user to his webcam because the more distant he is the smaller will be any dimension you measure.
I think you need to measure waist diameter etc... Is it ok or moral to ask user to take 2 photos? One directly facing the camera and one from profile. From this you could estimate the values...
So search for camera distance estimation algorithm.
After you have all sizes measured you can select proper size (small, medium...) from a table, see for example this
I am working on a project which involves extracting features from color and depth frames from Kinect Camera. The problem I am facing is that whenever I try displaying 2 Images, the UI hangs. When I tried debugging, the depthFrame and colorFrame were coming as null. If enable only the color steam then both colorImage and featureImage1 are displayed properly and if I enable only the depth stream, it works as it should. But when I enable them both, the UI hangs. I have no idea what is causing the problem. I have the following the following code for my Kinect Application. What is the cause of this problem and how can I fix it?
Config: Windows 8 Pro 64bit, 2Ghz Core2Duo, VisualStudio 2012 Ultimate, EmguCV 2.4.0.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using Emgu.CV;
using Emgu.CV.WPF;
using Emgu.CV.Structure;
using Emgu.Util;
namespace features
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private Image<Bgra, Byte> cvColorImage;
private Image<Gray, Int16> cvDepthImage;
private int colorWidth = 640;
private int colorHeight = 480;
private int depthWidth = 640;
private int depthHeight = 480;
private static readonly int Bgr32BytesPerPixel = (PixelFormats.Bgr32.BitsPerPixel + 7) / 8;
private byte[] colorPixels;
private byte[] depthPixels;
private short[] rawDepthData;
private bool first = true;
private bool firstDepth = true;
Image<Bgra, byte> image2;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
kinectSensorChooser.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser_KinectSensorChanged);
}
void kinectSensorChooser_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
{
KinectSensor oldSensor = (KinectSensor)e.OldValue;
KinectStop(oldSensor);
KinectSensor _sensor = (KinectSensor)e.NewValue;
_sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
_sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
_sensor.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(_sensor_DepthFrameReady);
_sensor.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(_sensor_ColorFrameReady);
_sensor.DepthStream.FrameHeight);
try
{
_sensor.Start();
}
catch
{
kinectSensorChooser.AppConflictOccurred();
}
}
void KinectStop(KinectSensor sensor)
{
if (sensor != null)
{
sensor.Stop();
}
}
private void Window_Closed(object sender, EventArgs e)
{
KinectStop(kinectSensorChooser.Kinect);
}
void _sensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null) return;
if (first)
{
this.colorPixels = new Byte[colorFrame.PixelDataLength];
first = false;
}
colorFrame.CopyPixelDataTo(this.colorPixels); //raw data in bgrx format
processColor();
}
}
void _sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame == null) return;
if (firstDepth)
{
this.rawDepthData = new short[depthFrame.PixelDataLength];
firstDepth = false;
}
depthFrame.CopyPixelDataTo(rawDepthData);
processDepth();
}
}
private void processColor(){...}
private void processDepth(){...}
}
}
The processDepth function is as follows. I am just making an Image from the RAW depth data.
private void processDepth() {
GCHandle pinnedArray = GCHandle.Alloc(this.rawDepthData, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
cvDepthImage = new Image<Gray, Int16>(depthWidth, depthHeight, depthWidth << 1, pointer);
pinnedArray.Free();
depthImage.Source = BitmapSourceConvert.ToBitmapSource(cvDepthImage.Not().Bitmap);
}
The processColor function is as follows. Here just for the sake of it, I am trying to display the cloned image instead of extracting features, just to check the lag. When both streams are enabled (color and depth) the following function displays the colorImage properly, but as soon as I uncomment the commented lines, the UI hangs.
private void processColor() {
GCHandle handle = GCHandle.Alloc(this.colorPixels, GCHandleType.Pinned);
Bitmap image = new Bitmap(colorWidth, colorHeight, colorWidth<<2, System.Drawing.Imaging.PixelFormat.Format32bppRgb, handle.AddrOfPinnedObject());
handle.Free();
cvColorImage = new Image<Bgra, byte>(image);
image.Dispose();
BitmapSource src = BitmapSourceConvert.ToBitmapSource(cvColorImage.Bitmap);
colorImage.Source = src;
//image2 = new Image<Bgra, byte>(cvColorImage.ToBitmap()); //uncomment and it hangs
//featureImage1.Source = BitmapSourceConvert.ToBitmapSource(image2.Bitmap); //uncomment and it hangs
}
I see code that do a lot of work in event handlers. I almost certain that handlers is called in GUI thread. I suggest you to extract your code to the background thread routine. Don't forget that updating of the Form's controls (depthImage and controlImage) should be done using BeginInvoke method of the parent form,