Утечка памяти в C # после ввода и поворота растрового изображения с USB-камеры - PullRequest
0 голосов
/ 09 мая 2018

Я инициирую загрузку кадра изображения с 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.
}

Вот посмотрите на утечку памяти ... enter image description here

ОБНОВЛЕНИЕ: Я сузил причину утечки памяти до этой строки:

image_rotator_RotateBilinear.Apply(   camera_frame_Bitmap ));       ///////////  2ND BITMAP BUFFER   /////////////

Комментарий ниже говорит о том, что пилообразная схема вовсе не означает утечку памяти - только мое ошибочное предположение.Вот последняя модель памяти ... enter image description here

1 Ответ

0 голосов
/ 10 мая 2018

Проблема не была в коде. Это было мое недопонимание паттерна памяти, показанного Diag Tool (диаграмма выше). Хотя использование памяти увеличивается в течение нескольких обратных вызовов событий, интеллектуальный сборщик мусора автоматически не удаляет каждый обратный вызов.

Благодаря яркому комментарию xxbbcc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...