so I wrote a Windows Form Application in C# to open a video, display the video in pictureBox_display, and allow users to define (draw) bounding boxes on the picturebox. Only thing is, I can very predictably cause the program to throw a System.AccessViolationException and crash by simply: 1) opening the video (any video) 2) click + dragging my mouse on the picturebox for a few seconds.
Here's some code:
VideoCapture VC;
bool IsMouseDown = false;
bool MouseMoved = false;
string VideoFileName;
private void OpenFileButton_Click(object sender, EventArgs e) {
OpenFileDialog OFD = new OpenFileDialog();
if (OFD.ShowDialog() == DialogResult.OK) {
FrameNumber = 0;
VideoFileName = OFD.FileName;
VC = new VideoCapture(VideoFileName);
if (VC.Width<=0 || VC.Height<=0) {
System.Windows.Forms.MessageBox.Show("ERROR: Please load a valid video file");
return;
}
// Initialize picturebox dimensions according to image
double W_H_ratio = Convert.ToDouble(VC.Width) / VC.Height;
if (W_H_ratio >= (double)(5 / 4)) {
pictureBox_display.Width = Math.Min(VC.Width, 800);
pictureBox_display.Height = Math.Min(VC.Height, (int)((1 / W_H_ratio )* 800));
}
else {
pictureBox_display.Height = Math.Min(VC.Height, 640);
pictureBox_display.Width = Math.Min(VC.Width, (int)(W_H_ratio * 640));
}
Mat tempimg = GetMat(FrameNumber);
Console.WriteLine("Size of tempimg: " + tempimg.Size);
pictureBox_display.Image = tempimg.Bitmap;
}
}
private Mat GetMat(int someFrameNumber) {
try {
Mat m = new Mat();
VC.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames, someFrameNumber);
VC.Read(m);
Mat resized = new Mat();
CvInvoke.ResizeForFrame(m, resized, pictureBox_display.Size);
m.Dispose();
return resized;
}
catch {
Mat m = new Mat();
System.Windows.Forms.MessageBox.Show("ERROR: Cannot read video frame");
return m;
}
}
private void pictureBox_display_MouseDown(object sender, MouseEventArgs e) {
if (VideoFileName != null && checkBox1.Checked == false && VideoPlaying == false) {
IsMouseDown = true;
MouseMoved = false;
ThereIsNewSelection = true;
StartLocation = e.Location;
Console.WriteLine(StartLocation);
}
}
// Constantly alter the end location of the mouse to provide the coordinates for the rectangle
private void pictureBox_display_MouseMove(object sender, MouseEventArgs e) {
if (IsMouseDown == true) {
MouseMoved = true;
EndLocation = e.Location;
pictureBox_display.Invalidate();
}
}
private void pictureBox_display_Paint(object sender, PaintEventArgs e) {
if (!VideoPlaying && ThereIsNewSelection) {
e.Graphics.DrawRectangle(Pens.Red, GetRectangle());
}
}
I know it's definitely to do with Invalidate() as I've commented code out line by line, and it only crashes when there is Invalidate(). Can anyone tell me what might be causing the problem?
Here is the stack trace if it's useful:
at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI(HandleRef graphics, HandleRef image, Int32 x, Int32 y, Int32 width, Int32 height) at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height) at System.Drawing.Graphics.DrawImage(Image image, Rectangle rect) at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe) at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer) at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
pictureBox_display.Image = tempimg.Bitmap;
and also spamming WinForms withpictureBox_display.Invalidate();
on every mouse move, so my guess will be, thattempimg.Bitmap
was disposed in the middle of GDI+GdipDrawImageRectI
operation (or maybe right before), so you have anAccessViolationException
. - vasily.sibMat CurrentFrameMat
and in the functionOpenFileButton_Click(...)
, assigned Frame 0 toCurrentFrameMat
and did apictureBox_display.Image = CurrentFrameMat.Bitmap
just before Invalidate() in the MouseMove function. Thanks a lot! - Ryan T. J.tempimg
variable out of the method so it becomes a field of the form class. That way the garbage collector always sees a reference to it and prevents it from getting garbage-collected. - Hans Passant