DlibDotNet icon indicating copy to clipboard operation
DlibDotNet copied to clipboard

ram exponencial consumption

Open danijerez opened this issue 5 years ago • 7 comments
trafficstars

I've been doing some benchmarks capturing rectangles of faces in a continuous loop and the RAM consumption seems exponential, is it possible that there is some memory leak somewhere? In EMGU it doesn't happen when I apply a shape.

danijerez avatar Sep 03 '20 17:09 danijerez

please attach source code.

takuya-takeuchi avatar Sep 04 '20 15:09 takuya-takeuchi

abjoint the test that I am doing in Unity, although it also happens to me with a similar code in windows forms

using DlibDotNet;
using System.IO;
using UnityEngine;

public class Camera : MonoBehaviour
{
    public static WebCamTexture backCam;
    public string filePath;
    private ShapePredictor sp;
    private Texture2D snap;

    void Start()
    {
        if (backCam == null)
            backCam = new WebCamTexture();

        filePath = Path.GetTempFileName();
        sp = ShapePredictor.Deserialize(Path.Combine(Application.dataPath, "Resources/shape_predictor_68_face_landmarks.dat"));

        if (!backCam.isPlaying)
            backCam.Play();

    }

    private void Update()
    {
        if (backCam != null && backCam.isPlaying)
        {
            snap = new Texture2D(backCam.width, backCam.height);
            snap.SetPixels(backCam.GetPixels());
            snap.Apply();

            File.WriteAllBytes(filePath, snap.EncodeToPNG());

            using (var fd = Dlib.GetFrontalFaceDetector())
            {
                var img = Dlib.LoadImage<RgbPixel>(filePath);
                var faces = fd.Operator(img);

                foreach (var face in faces)
                {
                    // find the landmark points for this face
                    var shape = sp.Detect(img, face);

                    // draw the landmark points on the image
                    for (var i = 0; i < shape.Parts; i++)
                    {
                        var point = shape.GetPart((uint)i);
                        var rect = new Rectangle(point);
                        Dlib.DrawRectangle(img, rect, color: new RgbPixel(255, 255, 255), thickness: 2);
                    }
                }

                if (faces.Length > 0)
                    Dlib.SavePng(img, filePath);

                var rawData = File.ReadAllBytes(filePath);
                var texture = new Texture2D(backCam.width, backCam.height);
                texture.LoadImage(rawData);
                
                GetComponent<Renderer>().material.mainTexture = texture;

            }
        }

    }
}

danijerez avatar Sep 04 '20 15:09 danijerez

@danijerez img, faces and shape are disposable object. You must dispose them.

takuya-takeuchi avatar Sep 04 '20 15:09 takuya-takeuchi

ok, i will try it, thanks!

How do you make a dispose of faces? (Rectagle [])

danijerez avatar Sep 04 '20 15:09 danijerez

I have added all the possible disposes and the ram continues to act the same, the consumption is exponential.

using DlibDotNet;
using System;
using System.IO;
using UnityEngine;

public class Camera : MonoBehaviour
{
    public static WebCamTexture backCam;
    public string filePath;
    private ShapePredictor sp;
    private Texture2D snap;

    void Start()
    {
        if (backCam == null)
            backCam = new WebCamTexture();

        filePath = Path.GetTempFileName();
        sp = ShapePredictor.Deserialize(Path.Combine(Application.dataPath, "Resources/shape_predictor_68_face_landmarks.dat"));

        if (!backCam.isPlaying)
            backCam.Play();

    }

    private void Update()
    {
        if (backCam != null && backCam.isPlaying)
        {
            snap = new Texture2D(backCam.width, backCam.height);
            snap.SetPixels(backCam.GetPixels());
            snap.Apply();

            File.WriteAllBytes(filePath, snap.EncodeToPNG());

            using (var fd = Dlib.GetFrontalFaceDetector())
            {
                var img = Dlib.LoadImage<RgbPixel>(filePath);
                var faces = fd.Operator(img);

                foreach (var face in faces)
                {
                    // find the landmark points for this face
                    var shape = sp.Detect(img, face);

                    // draw the landmark points on the image
                    for (var i = 0; i < shape.Parts; i++)
                    {
                        var point = shape.GetPart((uint)i);
                        var rect = new Rectangle(point);
                        Dlib.DrawRectangle(img, rect, color: new RgbPixel(255, 255, 255), thickness: 2);
                    }

                    shape.Dispose();
                }

                if (faces.Length > 0)
                    Dlib.SavePng(img, filePath);

                faces = null;
                img.Dispose();
                var rawData = File.ReadAllBytes(filePath);
                var texture = new Texture2D(backCam.width, backCam.height);
                texture.LoadImage(rawData);
                
                GetComponent<Renderer>().material.mainTexture = texture;
                GC.Collect();
            }
        }

    }
}

danijerez avatar Sep 05 '20 10:09 danijerez

@danijerez you create two Texture2D objects on every web camera frame, but I don't see a code that release/destroy those textures and frees a memory they consumed. GC.Collect() is not enough to release Unity objects. You need to use Unity specific calls to release Texture2D.

You can do a simple test to understand if the issue in DLib or Unity - just don't create new Texture2D but use a static bitmap in your sample which doesn't change on every frame and then check if memory leak is still there. If not - then it's Unity, not DLib.

Megadino avatar Sep 05 '20 10:09 Megadino

I have already discovered the problem, it is what you mentioned @Megadino had to use the Destroy of unity for the texture.

Thank you!

danijerez avatar Sep 05 '20 11:09 danijerez