Утечка памяти с изменением размера в drawImage - PullRequest
0 голосов
/ 18 июня 2019

Ссылка с моего плагина: https://github.com/luisdemarchi/cordova-plugin-facedetection-lite

Ссылка из моего кода наконец: https://github.com/luisdemarchi/example-cordova-facedetection/blob/master/www/index.html

Проблема: Я запускаю JavaScript в приложении для iOS (Cordova), когда я обрезаю Canvas с большим количеством пикселей, сокращая его до нужного размера, можно не отставать от увеличения памяти до ее предела и закрытия приложения.

Что я делаю: Я создаю свой первый публичный репозиторий, который будет компонентом распознавания лиц для Cordova. Есть скрипт "pico" на C и перевод на JavaScript, я использовал эти библиотеки для своего плагина и в браузере все идеально, однако в iOS (где я создал lib из библиотеки C) у меня утечка памяти это происходит через несколько шагов после вызова метода в C. Проблема, по-видимому, в примере кода, а не в библиотеке.

Поток кода IOS:

  • Плагин открывает родную камеру iOS и преобразует кадры в HTML Canvas;
  • У меня есть функция цикла в установленное время ожидания 20 миллисекунд:
  • , который копирует изображение этого холста и создает другой, с предельным размером 90 пикселей по высоте и ширине;
  • Отправить уменьшенное изображение в плагин, который возвращает координаты обнаруженных лиц;
  • Параллельно, пока первый холст обновляет кадры, используйте последнюю скоординированную грань, чтобы снова вырезать этот холст и надеть третий холст;

enter image description here

Что я пробовал:

  • Я удалил изменение размера кадра requestAnimationFrame ();
  • В контексте я добавляю beginPath ();
  • установить переменные на ноль;
  • вызов "функции" удалить
  • если ждать 1 секунду, чтобы вызвать метод, который сокращает лицо, это предотвращает утечку памяти;

Код

var updateFacePreview = function () {
    var loop = function () {
        if (faceBox.x > 0) {
            var facePreview = document.getElementById("facePreview");
            var facePreviewCtx = facePreview.getContext("2d", { alpha: false });
            facePreviewCtx.beginPath();
            facePreviewCtx.clearRect(0, 0, 400, 400);
            // console.log("x: " + parseInt(faceBox.x / scale) + " y: " + parseInt(faceBox.y / scale) + " size: " + parseInt(faceBox.size / scale));
            facePreviewCtx.drawImage(
                isIosApp ? cameraIosPreview : cameraPreview,
                parseInt(faceBox.x / scale),
                parseInt(faceBox.y / scale),
                parseInt(faceBox.size / scale),
                parseInt(faceBox.size / scale),
                0,
                0,
                400,
                400
            );
            delete facePreviewCtx;
            delete facePreview;
            delete cameraIosPreviewTemp;
            cameraIosPreviewTemp = null;
            facePreviewCtx = null;
            facePreview = null;
        }

        requestAnimationFrame(loop);
    }
    requestAnimationFrame(loop);
    // window.setTimeout(function () {
    //     updateFacePreview();
    // }, 100);
}

UPDATE:

Я обнаружил, что если я не изменю размер изображения, то во время вырезки утечка памяти отсутствует. Однако, если сделать разрез на 1 пиксель больше или меньше, произойдет утечка.

Вот фрагмент кода, который работает:

facePreviewCtx.drawImage(
    isIosApp ? cameraIosPreview : cameraPreview,
    10, 10, 300, 300,
    0, 0, 300, 300
);

Пример утечки памяти (только запуск JS в UIWebView на iOS):

facePreviewCtx.drawImage(
    isIosApp ? cameraIosPreview : cameraPreview,
    10, 10, 300, 300,
    0, 0, 150, 150
);

1 Ответ

0 голосов
/ 18 июня 2019

Решение, которое сработало:

Я создаю временный холст HTML, который захватывает лицо в исходном размере, не уменьшая его, а затем делаю вырез для другого холста HTML, просто уменьшая размер.

Это решение не элегантное, но позволяет избежать утечки памяти. Следующий исходный код:

var updateFacePreview = function () {
    var loop = function () {
        if (faceBox.x > 0) {
            var faceSizeOriginal = document.createElement('canvas');
            faceSizeOriginal.width = parseInt(faceBox.size / scale);
            faceSizeOriginal.height = parseInt(faceBox.size / scale);
            var faceSizeOriginalCtx = faceSizeOriginal.getContext("2d", { alpha: false });
            faceSizeOriginalCtx.drawImage(
                isIosApp ? cameraIosPreview : cameraPreview,
                parseInt(faceBox.x / scale),
                parseInt(faceBox.y / scale),
                parseInt(faceBox.size / scale),
                parseInt(faceBox.size / scale),
                0,
                0,
                parseInt(faceBox.size / scale),
                parseInt(faceBox.size / scale),
            );

            facePreviewCtx.drawImage(
                faceSizeOriginal,
                0, 0, faceSizeOriginal.width, faceSizeOriginal.height,
                0, 0, 400, 400
            );

            cameraIosPreviewTemp = null;
            faceSizeOriginal = null;
            faceSizeOriginalCtx = null;
            facePreview = null;
            delete faceSizeOriginalCtx;
            delete faceSizeOriginal;
            delete facePreview;
            delete cameraIosPreviewTemp;
        }

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