does not work Emgu.CV.Capture ()
public Form1() {
InitializeComponent();
grabber = new Emgu.CV.Capture();
grabber.QueryFrame();
Application.Idle += new EventHandler(FrameGrabber);
}
void FrameGrabber(object sender, EventArgs e){
currentFrame = grabber.QueryFrame();
if (currentFrame != null){
currentFrameCopy = currentFrame.Copy();
imageBoxFrameGrabber.Image = currentFrame;
}
}
can not get a picture .. tell me what I'm doing wrong
When you start up your camera capture you need to actually tell it what camera to use.
This line:
grabber = new Emgu.CV.Capture();
Requires you to tell it which camera, I would suggest changing it to this:
grabber = new Emgu.CV.Capture(0);
In theory it should open the deafult camera but it is worth being specific. On top of that
Related
I am new to DirectX and Direct3D/2D etc and just currently running an experiment on whether to pursue making a cad viewer for a machine we have.
I am using the control from here Direct2dOnWPF to enable me to display Direct2D onto WPF window using SharpDX.
At the moment I have the control working and its loads a file and displays a drawing.
I have now created a camera and I have implemented zooming (to a degree) but my issue is with panning. The issue is that when panning I expect the drawing to move with the mouse but it doesn't. Small movements it kind of does but bigger movements cause the drawing to move beyond the mouse movement. Almost like the further I move the mouse in a single movement, the faster it moves.
Ok some code, the Direct2DControl is based on an Image control so I have access to mouse events etc. Here is the some of code on the control with mouse events and a timer. I tried a timer to detect when the mouse stopped as I found the panning would not stop when the mouse did.
// Timer to detect mouse stop
private Timer tmr;
public Direct2dControl()
{
//
// .... Init stuff
//
// Mouse panning
// get mouse position
MouseOrigin = CurrentMousePosition = new Point(0, 0);
tmr = new Timer { Interval = 50 };
tmr.Elapsed += Tmr_Elapsed;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (!DragIsOn)
{
DragIsOn = true;
}
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (DragIsOn)
{
DragIsOn = false;
DragStarted = false;
MouseOrigin = CurrentMousePosition = e.GetPosition(this);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (!DragIsOn) return;
MouseMoved = true;
if (!DragStarted)
{
DragStarted = true;
MouseOrigin = CurrentMousePosition = e.GetPosition(this);
tmr.Start();
}
else
{
CurrentMousePosition = e.GetPosition(this);
var x = (float)(MouseOrigin.X - CurrentMousePosition.X);
var y = (float) (MouseOrigin.Y - CurrentMousePosition.Y);
cam.MoveCamera(cam.ScreenToWorld(new Vector2(x, y)));
tmr.Stop();
tmr.Start();
}
}
private void Tmr_Elapsed(object sender, ElapsedEventArgs e)
{
MouseOrigin = CurrentMousePosition;
tmr.Stop();
MouseMoved = false;
}
and the panning in camera class by moving the position.
public void MoveCamera(Vector2 cameraMovement)
{
Vector2 newPosition = Position + cameraMovement;
Position = newPosition;
}
public Matrix3x2 GetTransform3x2()
{
return TransformMatrix3x2;
}
private Matrix3x2 TransformMatrix3x2
{
get
{
return
Matrix3x2.Translation(new Vector2(-Position.X, -Position.Y)) *
Matrix3x2.Rotation(Rotation) *
Matrix3x2.Scaling(Zoom) *
Matrix3x2.Translation(new Vector2(Bounds.Width * 0.5f, Bounds.Height * 0.5f));
}
}
and finally at the start of the begin rendering I update the RenderTarget Transform
target.Transform = cam.GetTransform3x2();
I believe you're calculating the coordinates wrong. First, you need to set the MouseOrigin variable in OnLeftMouseButtonDown and don't modify it in any other method:
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (!DragIsOn)
{
DragIsOn = true;
MouseOrigin = e.GetPosition(this);
// I don't know the type of your cam variable so the following is pseudo code
MouseOrigin.x -= cam.CurrentPosition.x;
MouseOrigin.y -= cam.CurrentPosition.y;
}
}
And modify OnMouseMove like this:
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (!DragIsOn) return;
MouseMoved = true;
var x = (float)(e.GetPosition(this).x - MouseOrigin.X);
var y = (float) (e.GetPosition(this).y - MouseOrigin.Y);
cam.MoveCamera(cam.ScreenToWorld(new Vector2(x, y)));
tmr.Stop();
tmr.Start();
}
The DragStarted and CurrentMousePosition variables are not needed.
Let me know if it works.
I want to show a frame of a gif image. I searched and found that the following code should work, but it doesn't work. it detects the number of frames correctly but it shows the whole frames of gif instead of the specified frame. thanks everybody.
Image[] frames = new Image[36];
Image GG = Image.FromFile(#"C:\Users\Administrator\TEST C#\TEST2frame2\chef.gif");
FrameDimension dimension = new FrameDimension(GG.FrameDimensionsList[0]);
// Number of frames
int frameCount = GG.GetFrameCount(dimension);
label1.Text = frameCount.ToString();
// Return an Image at a certain index
GG.SelectActiveFrame(dimension, 1);
frames[1] = ((Image)GG.Clone());
pictureBox1.Image = frames[1];
Use your own code up until the call of SelectActiveFrame() and after that change to this lines:
frames[0] = new Bitmap(GG);
pictureBox1.Image = frame[0];
This should do the trick. Please do not forget do dispose the created Images.
Oh it works, but not as you expect it to.
When you set an active frame of a gif image it actually restarts its animation from that frame. You have to stop it when you change a frame, by setting the pictureBox.IsEnabled to false, for instance. Try the following code
private Image img;
public Form1()
{
InitializeComponent();
img = Image.FromFile(#"C:\Users\Administrator\TEST C#\TEST2frame2\chef.gif");
pictureBox1.Image = img;
}
private void button1_Click(object sender, EventArgs e)
{
var dim = new FrameDimension(img.FrameDimensionsList[0]);
img.SelectActiveFrame(dim, 1);
pictureBox1.Enabled = false;
}
Try pressing the button in different moments and you will see that the active image frame will change.
I am creating a program that can dump individual frames from a video feed for a drones competition. I am having a problem where by the wireless video stream coming form the drone is flickering and flying all over the place.
I am using this code to capture the video stream:
Capture _capture;
Emgu.CV.Image<Emgu.CV.Structure.Bgr,byte> frame;
void StartCamera()
{
_capture = null;
_capture = new Capture((int)nudCamera.Value);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS, FrameRate);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, FrameHeight);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, FrameWidth);
webcam_frm_cnt = 0;
cam = 1;
Video_seek = 0;
System.Windows.Forms.Application.Idle += ProcessFrame;
}
private void ProcessFrame(object sender, EventArgs arg)
{
try
{
Framesno = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
frame = _capture.QueryFrame();
if (frame != null)
{
pictureBox1.Image = frame.ToBitmap();
if (cam == 0)
{
Video_seek = (int)(Framesno);
double time_index = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_MSEC);
//Time_Label.Text = "Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8);
double framenumber = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
//Frame_lbl.Text = "Frame: " + framenumber.ToString();
Thread.Sleep((int)(1000.0 / FrameRate));
}
if (cam == 1)
{
//Frame_lbl.Text = "Frame: " + (webcam_frm_cnt++).ToString();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
Is there a setting somewhere that I am missing?
This video stream flickering seems to happen in other programs too however it fixes itself when you fiddle with the video setting (NTSC/PAL settings)
Edit: So I need to be able to put the video stream into NTSC /M mode, is this possible with EmguCV? If so how do I do it?
Edit 2: All documents that I have read point towards it being completely and utterly impossible to change the video type and that there is no documentation on this topic. I would love to be proved wrong :)
Thanks in advanced
This sourceforge link tells you how to set the video mode.
I'm trying to add a button so that it will appear on top of a screen that I'm drawing, in an XNA/Silverlight Windows phone game.
Currently the map is drawing over it, so the button appears invisible. Does anyone know how I could fix this?
The Button switchScreen is created, but not initialized, earlier in the code.
Here is the code where I'm adding the button:
private void OnDraw(object sender, GameTimerEventArgs e)
{
#region CommonStuff
SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);
#endregion CommonStuff
if (is3D)
{
OnDraw3D(sender, e);
}
else
{
OnDraw2D(sender, e);
}
switchScreen = new Button();
switchScreen.Height = 20.0;
switchScreen.Width = 100.0;
switchScreen.Content = "Switch to Shooting Screen";
switchScreen.Margin = new Thickness(phoneScreen.Height - switchScreen.Width -
20.0, 20.0, 20.0, phoneScreen.Width - switchScreen.Height - 20.0);
switchScreen.Visibility = System.Windows.Visibility.Visible;
}
I'm only testing the OnDraw2D so here's the code for that:
private void OnDraw2D(object sender, GameTimerEventArgs e)
{
spriteBatch.Begin();
// TODO: Add your drawing code here
map.Draw(e.ElapsedTime, e.TotalTime);
// npc.Draw(gameTime);
}
and the map.Draw is here
public override void Draw(TimeSpan elapsedTime, TimeSpan totalTime)
{
// Draw the Sky
gamePage.getSpriteBatch().Draw(background, Position, Color.White);
foreach (Person person in people)
{
person.Draw(elapsedTime, totalTime);
}
base.Draw(elapsedTime, totalTime);
}
background is a Texture.2D and Position is a Vector2.
I think, since you're creating the button manually, you may need to use this code instead (I am assuming that you're using the Windows Forms Button control):
switchScreen.Location = new System.Drawing.Point(xLocation, yLocation);
switchScreen.Name = name;
switchScreen.Size = new System.Drawing.Size(xSize, ySize);
switchScreen.TabIndex = 0;
switchScreen.Text = text;
switchScreen.UseVisualStyleBackColor = true;
Controls.Add(switchScreen);
How are you implementing a Windows Form? As far as I know, you can't add a Button without an underlying form for it to be on.
i am able to put a video in my windows form.
my question is how do i make it when it finishes playing the video,it starts to play another video? meaning like in a sequence. after it finishes, play another video.
so far i have manage to play a video and it just loops the video.
any ideas?
this is my code so far:
public partial class Form1 : Form
{
Video video;
public Form1()
{
InitializeComponent();
Initializevid1();
}
public void Initializevid1()
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video("C:\\Users\\Dave\\Desktop\\WaterDay1.wmv");
// set the panel as the video object’s owner
video.Owner = viewport;
// stop the video
video.Play();
video.Ending +=new EventHandler(BackLoop);
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
}
private void BackLoop(object sender, EventArgs e)
{
//video.CurrentPosition = 0;
}
When playing video sequences in AudioVideoPlayback:
Create a list of videos to be displayed (using file paths), preferably in a listbox.
Use an integer to get file path from the listbox.items index.
Ensure video is disposed before loading next video.
Increment integer every time a video is played.
Use an if statement to see if it is the end of the sequence.
As a personal preference (not sure how much difference it makes) I would resize video before playing
So from your code: (haven't tested this, but in theory, I think it should work)
public partial class Form1 : Form
{
Video video;
Int SeqNo = 0;
public Form1()
{
InitializeComponent();
Initializevid1();
}
public void Initializevid1()
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video(listbox1.Items[SeqNo].Text);
// set the panel as the video object’s owner
video.Owner = viewport;
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
// stop the video
video.Play();
// start next video
video.Ending +=new EventHandler(BackLoop);
}
private void BackLoop(object sender, EventArgs e)
{
// increment sequence number
SeqNo += 1; //or '++SeqNo;'
//check video state
if (!video.Disposed)
{
video.Dispose();
}
//check SeqNo against listbox1.Items.Count -1 (-1 due to SeqNo is a 0 based index)
if (SeqNo <= listbox1.Items.Count -1)
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video(listbox1.Items[SeqNo].Text);
// set the panel as the video object’s owner
video.Owner = viewport;
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
// stop the video
video.Play();
// start next video
video.Ending +=new EventHandler(BackLoop);
}
}
You can use the same video object created earlier to open the second video file in the BackLoop() function.
So, the code should look like something this:
private void BackLoop(object sender, EventArgs e)
{
video.Open("C:\\Users\\Dave\\Desktop\\WaterDay2.wmv", true);
}
I used this post to adapt it to my needs and this was my solution:
Video _SegaVideo;
Video _IntroVideo;
public _FrmMain()
{
InitializeComponent();
_SegaVideo = new Video(#"video\SEGA.AVI");
_SegaVideo.Owner = _VideoPanel;
_SegaVideo.Play();
_SegaVideo.Ending += new EventHandler(_SegaVideoEnding);
}
private void _SegaVideoEnding(object sender, EventArgs e)
{
_IntroVideo = new Video(#"video\INTRO.AVI");
_IntroVideo.Owner = _VideoPanel;
_IntroVideo.Play();
}