Я инициирую загрузку кадра изображения с USB-камеры в приложение C # для Windows: (Использует VideoCaptureDevice (например, AForge) Accord)
// Automatically start inputing each frame from camera:
var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
// Select physical USB camera: http://accord-framework.net/docs/html/T_Accord_Video_DirectShow_VideoCaptureDevice.htm
videoSource = new VideoCaptureDevice( videoDevices[0].MonikerString, pixelFormat_for_ExhaustiveTemplateMatching);
// Select event handlers:
videoSource.NewFrame += new NewFrameEventHandler( EVENT_camera_frame ); //http://accord-framework.net/docs/html/T_Accord_Video_NewFrameEventArgs.htm
// Start slurpin up them camera frames:
videoSource.Start();
Затем я обрабатываю каждое событие, которое содержит следующий кадр изображения с камеры:
private static void EVENT_camera_frame(object sender, NewFrameEventArgs camera_frame_event)
{
if( latest_frame_buffer_Bitmap != null )
{
latest_frame_buffer_Bitmap.Dispose();
}
// Allocate camera Bitmap buffer:
camera_buffer_Bitmap = new Bitmap(
// ..rotate and copy raw camera frame image bitmap from camera_frame_Bitmap to camera_buffer_Bitmap:
image_rotator_RotateBilinear.Apply( camera_frame_Bitmap )); /////////// 2ND BITMAP BUFFER /////////////
// Init a Bitmap for size of frame from camera and for conversion from camera native pixel format to comparison compatible format Format24bppRgb:
latest_frame_buffer_Bitmap = new Bitmap( camera_frame_Bitmap.Width,
camera_frame_Bitmap.Height,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// From rotated, camera format image bitmap in camera_frame_Bitmap, convert to Format24bppRgb and copy to latest_frame_buffer_Bitmap:
using (Graphics gr = Graphics.FromImage( latest_frame_buffer_Bitmap))
{
gr.DrawImage( camera_buffer_Bitmap, new Rectangle(0, 0,
latest_frame_buffer_Bitmap.Width,
latest_frame_buffer_Bitmap.Height));
camera_buffer_Bitmap.Dispose();
// Draw crop rectangle in Live Camera View:
using( Graphics live_image_Graphics = Graphics.FromImage( latest_frame_buffer_Bitmap ) )
{
live_image_Graphics.DrawRectangle( crop_pen, crop_display_rectangle ); ///////////// DRAW CROPPING RECTANGLE /////////////
}
// Show crop rectangle in PictureBox of Live Camera View:
control_panel.show_camera_crosshairs();
}
camera_frame_Bitmap.Dispose(); // I just tried this, but didn't fix the leak.
}
Затем я делаю .BeginInvoke, чтобы «запланировать» поток пользовательского интерфейса для обновления PictureBox:
public void show_camera_crosshairs()
{
// Show crosshairs, if requested in camera view:
// Create pen.
Pen crosshairs_pen = new Pen(Color.White, 1 );
int width = Computer_Vision_API.latest_frame_buffer_Bitmap.Width;
int height = Computer_Vision_API.latest_frame_buffer_Bitmap.Height;
int top_y = height - 1;
int bottom_y = 0;
int left_x = 0;
int right_x = width - 1;
// Create points that define line.
Point crosshair_point_top = new Point( width / 2, top_y );
Point crosshair_point_bottom = new Point( width / 2, bottom_y );
Point crosshair_point_left = new Point( 0, height / 2 );
Point crosshair_point_right = new Point( width-1, height / 2 );
float[] dashValues = { 4, 2 };
crosshairs_pen.DashPattern = dashValues;
// Verticle crosshair:
Graphics live_image_Graphics = Graphics.FromImage( Computer_Vision_API.latest_frame_buffer_Bitmap );
live_image_Graphics.DrawLine( crosshairs_pen, crosshair_point_top, crosshair_point_bottom );
// Horizontal crosshair:
live_image_Graphics.DrawLine( crosshairs_pen, crosshair_point_left, crosshair_point_right );
live_image_Graphics.Dispose();
// Display latest frame from camera:
Common.dbg("","","BeginInvoke: update_PictureBox");
PictureBox_live_camera.BeginInvoke( new update_PictureBox_Delegate( update_PictureBox ));
}
И, наконец, у меня есть обновление потока пользовательского интерфейса PictureBox ...
public delegate void update_PictureBox_Delegate( );
public void update_PictureBox()
{
Common.dbg("","","");
Computer_Vision_API.computer_vision_resource.WaitOne();
Common.dbg("","","computer_vision_resource");
PictureBox_live_camera.Image = Computer_Vision_API.latest_frame_buffer_Bitmap;
PictureBox_live_camera.BackgroundImage = Computer_Vision_API.latest_frame_buffer_Bitmap;
Computer_Vision_API.computer_vision_resource.ReleaseMutex(); // release use of computer vision Bitmap buffers, etc.
}
Вот посмотрите на утечку памяти ...
ОБНОВЛЕНИЕ: Я сузил причину утечки памяти до этой строки:
image_rotator_RotateBilinear.Apply( camera_frame_Bitmap )); /////////// 2ND BITMAP BUFFER /////////////
Комментарий ниже говорит о том, что пилообразная схема вовсе не означает утечку памяти - только мое ошибочное предположение.Вот последняя модель памяти ...