alexjet73
@alexjet73

Как реализовать ленивую загрузку TFJS и Face Landmarks Detection?

Собственно сабж. Есть необходимость подгружать tfjs и fld по необходимости. Сделал простую функцию
loadScript код

const loadedScripts = new Set();
function loadScript(url, callback) {
    if (loadedScripts.has(url)) {
        if (callback) callback(null);
        return;
    }
    const script = document.createElement('script');
    script.src = url;
    script.onload = () => {
        loadedScripts.add(url);
        if (callback) callback(null);
    };
    script.onerror = () => {
        if (callback) callback(new Error(`Ошибка загрузки скрипта: ${url}`));
    };
    document.head.appendChild(script);
}


И подгружаю их соответственно из публичных cdn jsdelivr или unpkg. И тут возникает ошибка TypeError: s.loadGraphModel is not a function
Ошибка в консоли

671252bc6091e202707178.png

Если подгружать стандартно через тег script в html, всё ок. Может кто подскажет, в чем тут загвоздка?
  • Вопрос задан
  • 40 просмотров
Решения вопроса 1
@GrigoryMorozov
Ваша конкретная ошибка состоит в том, что вы не подключаете все необходимые зависимости или загружаете их в неправильном порядке.

Более вероятно второе: не забывайте, что динамически добавляемые скрипты по-умолчанию являются асинхронными (то есть первым выполнится тот скрипт, который загрузится раньше других). В данном случае это некорректное поведение, которое нужно исправить:

script.async = false;

Также разумно использовать промисы вместо коллбэков, чтобы не росла вложенность кода. Полный пример:

// Functions

const loadedScripts = new Set();

async function loadScript(url) {
  if (loadedScripts.has(url)) return;
  
  const script = document.createElement('script');

  script.src = url;
  script.async = false;

  document.head.append(script);

  return new Promise((resolve, reject) => {
    script.addEventListener('load', () => {
      loadedScripts.add(url); resolve();
    });
  
    script.addEventListener('error', () => reject(
      new Error(`Error loading script: ${url}`)
    ));
  });
}

async function loadImage(url) {
  const image = new Image();

  image.src = url;
  image.crossOrigin = 'anonymous';

  return new Promise((resolve, reject) => {
    image.addEventListener('load', () => {
      resolve(image);
    });
  
    image.addEventListener('error', () => reject(
      new Error(`Error loading image: ${url}`)
    ));
  });
}

// Example

const image = loadImage('https://habrastorage.org/r/w1560/getpro/habr/upload_files/799/62f/375/79962f375d90db7f7d926ff40d623456.png');

await Promise.all([
  loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core'),
  loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter'),
  loadScript('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl'),
  loadScript('https://cdn.jsdelivr.net/npm/@tensorflow-models/face-landmarks-detection@1.0.6/dist/face-landmarks-detection.min.js')
]);

const model = faceLandmarksDetection.SupportedModels.MediaPipeFaceMesh;

const detectorConfig = {
  runtime: 'tfjs', 
  solutionPath: 'https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh'
};

const detector = await faceLandmarksDetection.createDetector(model, detectorConfig);
const faces = await detector.estimateFaces(await image);

console.log(faces);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы