I have a bit strange problem, which I find hard to debug
Sometimes I can't close my program and it freezes when I try to close it.
I made a large program for video image recognition.
I made a special button to close the camera. This button works with this by calling a function below, and it indeed, it does work.
private void exitcamera()
{
FinalVideo.SignalToStop();
FinalVideo.WaitForStop();
FinalVideo = null;
}
Notice that the original video was started like this
private void buttonStartCamera_Click(object sender, EventArgs e)
{
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
FinalVideo.DesiredFrameRate = 90;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.ProvideSnapshots = true; //snapshots
FinalVideo.Start();
}
Now my problem seems (and this is a guess because I can't debug this moment)
That some thread is still active wanting to update the main form with data.
However it might not be able to do so since that one is closing.
I think something like that is going on so I wrote on the main application form
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// Thread.Sleep(1000); // not sure about these delays might help syncing threads
ExitCamera();
Thread.Sleep(1000);
}
However with that last code in place the program has even more trouble to exit.
I would like to send the subthreads an exit, but I dont know their names (if they have a name), I dont know how to list them or to instruct them to stop they are in another dll not my part of the code. From some dll's I dont have the code.
So are there ways of listing sub threads and then close them one by one, if one presses the uppercorner right cross to exit the application?
Well I managed to debug the program, and finally found what caused the problem.
It is a little bit strange since as a button I could stop the camera using the exitcamera function.
However, inside a _formclosing event the same routine didn't work although it worked after I had marked out the waitforstop function.
private void exitcamera()
{
FinalVideo.SignalToStop();
// FinalVideo.WaitForStop(); << marking out that one solved it
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame); // as sugested
FinalVideo = null;
}
I am still a bit confused about it, why this wont work in case a closing event. But it seems to be solved by this.
Maybe you have memory leaks problems caused by the event. You could try to unhook the event while exiting the programm :
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);
Maybe this will help.
This helped with another problem when I wanted to show a preview, click a "grab" button, change the resolution of the camera from low res to high res, grab an image, and then change back to low res for the preview. Here is what worked, even though I had to abandon it because stopping and starting the camera reset the auto exposure so the picture was awful on the grabbed image:
using AForge.Video;
using AForge.Video.DirectShow;
public partial class Form1 : Form
{
private int PreviewRefreshDelayMS = 40;
private FilterInfoCollection VideoCaptureDevices;
private VideoCaptureDevice CustomerWebcam;
private int CustomerWebcam_CapabilitiesIndexMin;
private int CustomerWebcam_CapabilitiesIndexMax;
private bool bCustomerWebcam_capture;
private Bitmap CustomerWebcam_bitmap;
private System.DateTime CustomerWebcam_nextframetime = DateTime.Now;
public Form1()
{
InitializeComponent();
}
// Some good info to make this more robust
// http://haryoktav.wordpress.com/2009/03/21/webcam-in-c-aforgenet/
//
private void button1_Click(object sender, EventArgs e)
{
CustomerWebcam = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
CustomerWebcam.NewFrame += new NewFrameEventHandler(CustomerWebcam_NewFrame);
int indexMin = -1;
int MinPixels = 0;
int indexMax = -1;
int MaxPixels = 0;
for (int i = 0; i < CustomerWebcam.VideoCapabilities.Length; i++)
{
int pixels = CustomerWebcam.VideoCapabilities[i].FrameSize.Height * CustomerWebcam.VideoCapabilities[i].FrameSize.Width;
if (indexMin == -1) { indexMin = i; MinPixels = pixels; }
if (indexMax == -1) { indexMax = i; MaxPixels = pixels; }
if (pixels < MinPixels) { indexMin = i; MinPixels = pixels; }
if (pixels > MaxPixels) { indexMax = i; MaxPixels = pixels; }
}
CustomerWebcam_CapabilitiesIndexMin = indexMin;
CustomerWebcam_CapabilitiesIndexMax = indexMax;
CustomerWebcam.VideoResolution = CustomerWebcam.VideoCapabilities[indexMin];
CustomerWebcam.DisplayPropertyPage(IntPtr.Zero);
CustomerWebcam.Start();
}
void CustomerWebcam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
if (CustomerWebcam_bitmap != null)
{
CustomerWebcam_bitmap.Dispose();
CustomerWebcam_bitmap = null;
}
if (bCustomerWebcam_capture)
{
CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone();
System.Random rnd = new Random();
CustomerWebcam_bitmap.Save("img" + Convert.ToString((int)(rnd.NextDouble() * 10000000)) + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
bCustomerWebcam_capture = false;
((Bitmap)eventArgs.Frame).Dispose();
}
else
if (DateTime.Now > CustomerWebcam_nextframetime)
{
CustomerWebcam_bitmap = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = CustomerWebcam_bitmap;
CustomerWebcam_nextframetime = DateTime.Now.AddMilliseconds(PreviewRefreshDelayMS);
((Bitmap)eventArgs.Frame).Dispose();
}
}
private void Form1_Load(object sender, EventArgs e)
{
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
{
comboBox1.Items.Add(VideoCaptureDevice.Name);
}
comboBox1.SelectedIndex = 0;
}
private void button2_Click(object sender, EventArgs e)
{
CustomerWebcam.SignalToStop();
CustomerWebcam = null;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (!(CustomerWebcam == null))
if (CustomerWebcam.IsRunning)
{
CustomerWebcam.SignalToStop();
CustomerWebcam = null;
}
}
private void button4_Click(object sender, EventArgs e)
{
bCustomerWebcam_capture = true;
}
}
One other thing to mention ... the AForge library was the most consistent way I was able to find for using a webcam to grab a still image and save as a JPEG without delving into the world of Windows 8 metro apps. I was hoping to use OpenCV.NET, or just the regular .NET API with DirectShow or WIA, but this was the most simple and it worked for me.
And here are some good samples that were hard to find but very useful: https://github.com/mdavid/aforge.net
I was dealing with this problem. Here is a simple way to stop the camera and close Win Form.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (FinalVideo != null)
{
if (FinalVideo.IsRunning)
{
FinalVideo.SignalToStop();
FinalVideo = null;
}
}
}
In my situation WaitForStop() was needed, but the code execution was deading inside the method.
I've replaced it right after the call to SignalToStop(), with:
while (m_Device.IsRunning) { }
This is the code involved on the AForge library:
public bool IsRunning
{
get
{
if (this.thread != null)
{
if (!this.thread.Join(0))
{
return true;
}
this.Free();
}
return false;
}
}
public void WaitForStop()
{
if (this.thread != null)
{
this.thread.Join();
this.Free();
}
}
Edit: this didn't fix the hang the 100% of times. Sometimes a call to a com object (mediaControl.Stop();) on the WorkerThread() method just took forever.
Avoid direct interaction with the form - hope to have a better solution than timer but solves problem. I
Static helper class
public static Bitmap StaticBitmap = new Bitmap(100,100);
Form
public void Cam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
lock (StaticHelper.StaticBitmap)
{
using (Bitmap b = (Bitmap)eventArgs.Frame)
{
StaticHelper.StaticBitmap = (Bitmap)b.Clone();
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
lock (StaticHelper.StaticBitmap)
{
pictureBox1.Image = (Bitmap)StaticHelper.StaticBitmap.Clone();
}
}
This will destroy your problem ( I have had this problem, i tried)
using System.Threading;
bool photo_was_taken = false;
private void buttonStartCamera_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(exitcamera));
thread.Start();
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[comboBox1.SelectedIndex].MonikerString);
FinalVideo.DesiredFrameSize = new System.Drawing.Size(640, 480);
FinalVideo.DesiredFrameRate = 90;
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.ProvideSnapshots = true; //snapshots
FinalVideo.Start();
}
private void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
// what you want to do ( your code is here )
photo_was_taken = true;
}
private void exitcamera()
{
while (!photo_was_taken)
{
Thread.Sleep(5); // you can change wait milliseconds
}
FinalVideo.SignalToStop();
FinalVideo.NewFrame -= new NewFrameEventHandler(FinalVideo_NewFrame);
//FinalVideo.WaitForStop();
while (FinalVideo.IsRunning)
{
FinalVideo.Stop();
// FinalVideo = null; >> // that is not condition
}
}
This is what you need, 100% working solutions:
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
Invoke((MethodInvoker) delegate
{
_videoSource.SignalToStop();
_videoSource.WaitForStop();
});
}
Please, let me add my working solution on closing a webcam with the wonderful library AForge.NET. It´s a pitty it development has been abandoned.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (videoCaptureSource != null)
{
while (videoCaptureSource.IsRunning) // Perhaps you need to limit the number of iterations
{
videoCaptureSource.SignalToStop();
videoCaptureSource.WaitForStop();
if (videoSourcePlayer != null)
{
videoSourcePlayer.SignalToStop();
videoSourcePlayer.WaitForStop();
//videoSourcePlayer.NewFrame -= new NewFrameEventHandler(videoSourcePlayer_NewFrame); // Uncomment this line if you have added an event handler
}
Thread.Sleep(3000);
}
videoCaptureSource = null;
videoDevices = null;
videoSourcePlayer = null;
}
}
When I only needed the frame attaching an event handler to the VideoCaptureDevice (not the VideoSourcePlayer) I couldn´t stop the video from the VideoCaptureDevice, instead I used an invisible VideoSourcePlayer and stopped it from there.
i tried some solution, but nothing work.
i partial solved adding a thread sleep after WaitForStop
if (FinalVideo != null)
{
if (FinalVideo.IsRunning)
{
FinalVideo.SignalToStop();
Thread.Sleep(1000);
}
}
if i try to call Stop application will be freeze
Related
I need to save an image to disk that came from a web-cam between 5 and 10 seconds ago from when the "save" command comes in via serial port.
To get there, I have the webcam going into a pictureBox.Image (using opencv4), and then 2 Bitmap variables. Every 5 seconds a timer ticks, and Stored_bitmap_2 = Stored_bitmap_1, then Stored_bitmap_1 = (bitmap) pictureBox.Image.
When the right serial command comes in, I try to
Stored_image_2.Save("C:\Users\GreenWorld\Desktop\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
and I get a run-time error of invalid parameter.
When I do the same thing in a stand-alone project with some buttons (inside the button-click event handler), it works every time.
When I do this inside the serialPort_DataReceived handler, I get all kinds of cross-thread errors. So, I moved the save attempt to its own subroutine, and that fixed that but now this.
I am by no means a professional programmer, I'm an engineer with a simple problem and I can usually write a little simplistic code to fix my immediate issue. Please go easy on me in the explanation :-)
Sample code:
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace Weld_picture
{
public partial class Form1 : Form
{
// Create class-level accessible variables
int Welding_camera_ID = 1;
VideoCapture capture;
Mat frame;
Bitmap image;
private Thread camera;
bool isCameraRunning = false;
string Serial_command = "";
Bitmap Stored_image_1;
Bitmap Stored_image_2;
bool Image_saved = false;
string Station_ID = "GWM-PWS-01";
string File_name = "";
private void CaptureCamera() // from someone else's sample code
{
camera = new Thread(new ThreadStart(CaptureCameraCallback));
camera.Start();
}
private void CaptureCameraCallback() // from someone else's sample code
{
frame = new Mat();
capture = new VideoCapture(Welding_camera_ID);
capture.Open(Welding_camera_ID);
if (capture.IsOpened())
{
while (isCameraRunning)
{
capture.Read(frame);
image = BitmapConverter.ToBitmap(frame);
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
pictureBox1.Image = image;
}
}
}
public Form1()
{
InitializeComponent();
SerialPort1.Open();
}
private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string dummy;
char CR = (char)0x0D;
while (SerialPort1.BytesToRead > 0)
{
Serial_command += (char)SerialPort1.ReadByte();
}
while (Serial_command.IndexOf(CR) > 0)
{
dummy = Serial_command.Substring(0, Serial_command.IndexOf(CR));
Serial_command = Serial_command.Substring(Serial_command.IndexOf(CR) + 1, (Serial_command.Length - (Serial_command.IndexOf(CR) + 1)));
Serial_command.Trim();
dummy.Trim();
proc_Process_serial_data(dummy);
}
}
//*************************************************************************************************************************************
/* the first timer is a 5-second interval. It's the "memory" function so that if/when the save-to-disk is triggered I can store the last-time-shutter-open image */
//*************************************************************************************************************************************
private void Timer_picture_interval_Tick(object sender, EventArgs e)
{
checkBox1.Checked = !checkBox1.Checked;
Timer_picture_interval.Stop();
Stored_image_2 = Stored_image_1;
Stored_image_1 = (Bitmap) pictureBox1.Image;
Timer_picture_interval.Start();
}
//*************************************************************************************************************************************
// the second timer is a 30-second interval. It's the way to turn capture off if the PLC/camera box somehow goes off-line
//*************************************************************************************************************************************
private void Timer_camera_powerdown_Tick(object sender, EventArgs e)
{
if (isCameraRunning)
capture.Release();
isCameraRunning = false;
Timer_picture_interval.Stop();
}
//*************************************************************************************************************************************
private void proc_Process_serial_data(string Serial_string)
{
if (Serial_string.IndexOf("Still here") > 0)
{
if (!isCameraRunning)
CaptureCamera();
isCameraRunning = true;
}
if (Serial_string.IndexOf("Sun's up") > 0)
{
Timer_picture_interval.Start();
Timer_camera_powerdown.Start();
}
if (Serial_string.IndexOf("It's dark") > 0)
{
if ((Stored_image_2 != null) && (!Image_saved)) // in case there's 2 subsequent requests to save the same thing (weld stutter)
{
File_name = "C:\\Users\\GreenWorld\\Desktop\\" + Station_ID + " D" + DateTime.Now.ToString("yyyy_MM_dd THH_mm_ss") + ".jpg";
Stored_image_2.Image.Save("C:\\Users\\GreenWorld\\Desktop\\test.bmp" , System.Drawing.Imaging.ImageFormat.Bmp );
Image_saved = true;
Timer_picture_interval.Stop();
}
Timer_camera_powerdown.Start();
}
}
}
}
You likely be able to fix the cros-threading error by simply calling your proc_Process_serial_data() method within an Invoke() call.
Change:
proc_Process_serial_data(dummy);
To:
this.Invoke((MethodInvoker)delegate ()
{
proc_Process_serial_data(dummy);
});
Also, these two lines aren't actually doing anything:
Serial_command.Trim();
dummy.Trim();
To Trim() the strings, you have capture the returned strings and re-assign them to the original variables:
Serial_command = Serial_command.Trim();
dummy = dummy.Trim();
How to make slideshow to automaticly changing pictures in picturebox? currently im using imagelist but it didnt seems to works. I want the timer to change the image every 3 seconds. this is the timer code I'm using. it works well before to click buttons every 3 seconds but not working with imagelist. I'm new with imagelist & slideshows so if have any suggestion about it please tell me. thanks.
private bool _timerEnabled;
private async Task StartTimer()
{
_timerEnabled = true;
int i = 0;
while (_timerEnabled)
{
i++;
if (i > 2) { i = 0; }
pictureBox2.Image = imageList1.Images[i];
bmp = new Bitmap(pictureBox2.Image, pictureBox2.Width, pictureBox2.Height);
pictureBox1.Refresh();
pictureBox2.Refresh();
await Task.Delay(3000);
}
}
private async void timerStartButton_Click(object sender, EventArgs e)
{
timerStopButton.Enabled = true;
timerStartButton.Enabled = false;
if (_timerEnabled)
return;
await StartTimer();
}
private void timerStopButton_Click(object sender, EventArgs e)
{
timerStopButton.Enabled = false;
timerStartButton.Enabled = true;
_timerEnabled = false;
}
the slideshow works fine now but the used image become blurry. How to fix this one?
Original Image
Blurry result
EDIT.
after checking it again the blurry result is from imagelist control that automaticly set the image size to 16,16. it seems cant get it any bigger than 320,320. know how to make it can use bigger resolution size?
Simply move int i out of the while loop.
private async Task StartTimer() {
_timerEnabled = true;
int i = 0; //Move this here
while (_timerEnabled) {
i++;
if (i > 2) { i = 0; }
pictureBox2.Image = imageList1.Images[i];
pictureBox1.Refresh();
pictureBox2.Refresh();
await Task.Delay(3000);
}
}
Or you can use the inbuilt timer control instead of reinventing the wheel.
Timer timer1;
int i = 0;
//Form's constructor
public Form1
{
timer1 = new Timer();
timer1.Interval = 3000;
timer1.Tick += new EventHandler(timer1_tick);
}
private void timer1_tick(object sender, EventArgs e)
{
i++;
if (i > 2) { i = 0; }
pictureBox2.Image = imageList1.Images[i];
pictureBox1.Refresh();
pictureBox2.Refresh();
}
private async void timerStartButton_Click(object sender, EventArgs e) {
timerStopButton.Enabled = true;
timerStartButton.Enabled = false;
if (timer1.Enabled) return;
timer1.Enabled = True;
}
private void timerStopButton_Click(object sender, EventArgs e) {
timerStopButton.Enabled = false;
timerStartButton.Enabled = true;
timer1.Enabled = false;
}
I'm trying to figure out if there's an elegant solution to the problem I've been faced with.
So basically, I designed a borderless loading splash screen which is completely movable via dragging. I find that this happens if the splash screen gets hidden via Hide(), then displays a window via ShowDialog() with the owner set to the splash screen. Things get extremely buggy, but only if you're in mid-drag (with left mouse button down). You become unable to click or move anything, even Visual Studio becomes unresponsive unless you explicitly alt-tab out of the application.
Considering I know when I'm going to spawn the window, I was thinking maybe there'd be a way to cancel the DragMove operation, but I'm having no luck. What I've figured out is that DragMove is synchronous, so I'd guess it'd have to be cancelled from a different thread or in an event callback.
Edit:
public partial class Window_Movable : Window
{
public Window_Movable()
{
InitializeComponent();
}
public Boolean CanMove { get; set; } = true;
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (CanMove == false)
return;
Task.Factory.StartNew(() => {
System.Threading.Thread.Sleep(1000);
Dispatcher.Invoke(() => {
Hide();
new Window_Movable() {
Title = "MOVABLE 2",
CanMove = false,
Owner = this
}.ShowDialog();
});
});
DragMove();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("DING");
}
}
I had the same problem and found out that DragMove() method is a problem.
https://groups.google.com/forum/#!topic/wpf-disciples/7OcuXrf2whc
To solve I decided to refuse from using it and implement moving logic.
I've combined some solutions from
https://www.codeproject.com/Questions/284995/DragMove-problem-help-pls
and
C# WPF Move the window
private bool _inDrag;
private Point _anchorPoint;
private bool _iscaptured;
private void AppWindowWindowOnMouseMove(object sender, MouseEventArgs e)
{
if (!_inDrag)
return;
if (!_iscaptured)
{
CaptureMouse();
_iscaptured = true;
}
var mousePosition = e.GetPosition(this);
var mousePositionAbs = new Point
{
X = Convert.ToInt16(_appWindowWindow.Left) + mousePosition.X,
Y = Convert.ToInt16(_appWindowWindow.Top) + mousePosition.Y
};
_appWindowWindow.Left = _appWindowWindow.Left + (mousePositionAbs.X - _anchorPoint.X);
_appWindowWindow.Top = _appWindowWindow.Top + (mousePositionAbs.Y - _anchorPoint.Y);
_anchorPoint = mousePositionAbs;
}
private void AppWindowWindowOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_inDrag)
{
_inDrag = false;
_iscaptured = false;
ReleaseMouseCapture();
}
}
private void AppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_anchorPoint = e.GetPosition(this);
_anchorPoint.Y = Convert.ToInt16(_appWindowWindow.Top) + _anchorPoint.Y;
_anchorPoint.X = Convert.ToInt16(_appWindowWindow.Left) + _anchorPoint.X;
_inDrag = true;
}
I've spend all yesterday evening and find a more hacky but more functional solution. Which support Maximized state and not require manual coordinate calculation.
private bool _mRestoreForDragMove;
private void OnAppWindowWindowOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
if (_appWindowWindow.ResizeMode != ResizeMode.CanResize &&
_appWindowWindow.ResizeMode != ResizeMode.CanResizeWithGrip)
{
return;
}
_appWindowWindow.WindowState = _appWindowWindow.WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
else
{
_mRestoreForDragMove = _appWindowWindow.WindowState == WindowState.Maximized;
SafeDragMoveCall(e);
}
}
private void SafeDragMoveCall(MouseEventArgs e)
{
Task.Delay(100).ContinueWith(_ =>
{
Dispatcher.BeginInvoke((Action)
delegate
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
_appWindowWindow.DragMove();
RaiseEvent(new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left)
{
RoutedEvent = MouseLeftButtonUpEvent
});
}
});
});
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (_mRestoreForDragMove)
{
_mRestoreForDragMove = false;
var point = PointToScreen(e.MouseDevice.GetPosition(this));
_appWindowWindow.Left = point.X - (_appWindowWindow.RestoreBounds.Width * 0.5);
_appWindowWindow.Top = point.Y;
_appWindowWindow.WindowState = WindowState.Normal;
_appWindowWindow.DragMove();
SafeDragMoveCall(e);
}
}
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_mRestoreForDragMove = false;
}
The thing is to send LeftMouseButtonUp event after a short delay to avoid blocking from DragMove()
Sources for last solve:
DragMove() and Maximize
C# WPF - DragMove and click
And one more completely different solution. To make a window movable you can use CaptionHeight of WindowChrome.
i.e.
var windowChrome =
WindowChrome.GetWindowChrome(appWindow.Window);
windowChrome.CaptionHeight = MainWindowToolbar.Height;
WindowChrome.SetWindowChrome(appWindow.Window, windowChrome);
but you should also set attached property WindowChrome.IsHitTestVisibleInChrome="True" for all controls in the window.
I have a small project whereby I capture images from a webcam and decode the qr.
The following code captures an image and stores it to a local file, but only when it is not in the while loop. The system.threading appears to make the captured image just black. If i don't use it(the loop), it captures far too many images a second.
So is there a way of changing the aforge.video framerate so that i can capture an image every x seconds without while loop?
public partial class WebForm1 : System.Web.UI.Page
{
public int FrameRate { get; set; }
private FilterInfoCollection VideoCaptureDevices;
private VideoCaptureDevice FinalVideo;
protected void Page_Load(object sender, EventArgs e)
{
inputDevices.Items.Clear();
VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
{
inputDevices.Items.Add(VideoCaptureDevice.Name);
}
inputDevices.SelectedIndex = 0;
}
public void Start_OnClick(object sender, EventArgs e)
{
FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[inputDevices.SelectedIndex].MonikerString);
FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
FinalVideo.Start();
}
void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
int i = 0;
while (i < 10)
{
Bitmap video = (Bitmap)eventArgs.Frame.Clone();
video.Save("C:\\Users\\Wayneio\\Desktop\\image\\test" + i + ".jpg");
i++;
System.Threading.Thread.Sleep(5000);
}
}
public void Stop_OnClick(object sender, EventArgs e)
{
this.FinalVideo.Stop();
}
}
Additionally I get this error when trying to stop the capture via the asp button:
Object reference not set to an instance of an object on this.FinalVideo.Stop();
Tried this to no avail:
((VideoCaptureDevice)FinalVideo).DesiredFrameRate = 10;
before you code start video set the framreate like this
FinalVideo.DesiredFrameRate = 10;
FinalVideo.Start();
Another option to skip frames that you save is to use a function that is not always true
if you have a global counter value myCounter
do a modulo calulation like below ix mycounter devided by 10 equals 1
myCounter++
if (m(ycounter %% 10))==1) { //code to save your bitmap }
I'd like to create a software that listens after claps thru microphone..
my first implementation will be to try to get the software to warn when i hears high volume sound.
but i was wondering if someone could help me in the right direction?
public partial class ClapperForm : Form
{
WaveIn waveInStream;
public ClapperForm()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
//start the streaming
waveInStream = new WaveIn();
waveInStream.DataAvailable += new EventHandler<WaveInEventArgs>(waveInStream_DataAvailable);
waveInStream.StartRecording();
}
void waveInStream_DataAvailable(object sender, WaveInEventArgs e)
{
//check out what volume it is
}
private void btnStop_Click(object sender, EventArgs e)
{
if (waveInStream != null)
{
//Stop streaming
waveInStream.StopRecording();
waveInStream.Dispose();
waveInStream = null;
}
}
}
Assuming you are recording 16 bit audio (which is the default), then the contents of e.Buffer can be interpreted like this:
for (int n = 0; n < e.BytesRecorded; n += 2)
{
short sampleValue = BitConverter.ToInt16(e.Buffer, n);
}
Then you can look for high values of Math.Abs(sampleValue).