所以我用C#编写了Windows窗体应用程序,以打开视频,在pictureBox_display中显示视频,并允许用户在picturebox上定义(绘制)边框。唯一的事情是,我可以很容易地使程序引发System.AccessViolationException并通过以下方式崩溃: 1)打开视频(任何视频) 2)点击+在图片框上拖动鼠标几秒钟。
以下是一些代码:
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());
}
}
我知道这肯定与Invalidate()有关,因为我逐行注释了代码,并且只有在有Invalidate()时它才会崩溃。谁能告诉我可能是什么原因引起的问题?
如果有用的话,这里是堆栈跟踪:
在System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectI(HandleRef 图形,HandleRef图像,Int32 x,Int32 y,Int32宽度,Int32 高度)在System.Drawing.Graphics.DrawImage(Image image,Int32 x, Int32 y,Int32宽度,Int32高度)在 System.Drawing.Graphics.DrawImage(图像图像,矩形rect)位于 System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)位于 System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, System.Windows.Forms.Control.WmPaint(Message&m)中的Int16层)
在System.Windows.Forms.Control.WndProc(Message&m)在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg,IntPtr wparam,IntPtr lparam)
答案 0 :(得分:-1)
您需要克隆(深拷贝)位图,如下所示:
B.Clone(new Rectangle(0, 0, B.Width, B.Height), B.PixelFormat)