Сегодня мы собираемся создать RESTFUL API, который принимает изображение и делает прогнозы с использованием предварительно обученной модели TensorFlow M obileNet.

В TensorFlow.js есть множество предварительно обученных моделей, которые можно использовать в проектах из коробки. Это избавляет разработчиков от необходимости обучать модель с нуля. Здесь мы собираемся изучить предварительно обученную архитектуру MobileNet.

Разработка

Если вы еще не установили NodeJs на свой компьютер, перейдите по этой ссылке, чтобы загрузить и установить.

Откройте свой терминал и следуйте инструкциям ниже.

  1. Вставьте и запустите команду ниже, чтобы:
  • Создайте папку.
  • Перейдите в папку.
  • И инициализируйте новый проект, который создает файл package.json.
mkdir image-classifier-api && cd image-classifier-api && npm init --yes

2. Не выходя из терминала, выполните следующую команду для установки зависимостей:

npm i express logger @tensorflow-models/mobilenet @tensorflow/tfjs get-image-data multer morgan nodemon jimp cors --save

3. Откройте вновь созданную папку в любом редакторе кода по вашему выбору.

4. Создайте файл с именем app.js в корне папки и вставьте следующий код:

const express = require('express');
const logger = require('morgan');
const cors = require('cors');
const app = express();
const corsOptions = {
  origin: '*',
};
app.use(logger('dev'));
app.use(express.json());
app.use(cors(corsOptions));
app.use(express.urlencoded({ extended: false }));
app.get('/', (req, res) => {
  res.send('Image Classifier API')
});
PORT = process.env.PORT || 3000;
app.listen(PORT);
console.log(`Running server at http://localhost:${PORT}`);

Приведенный выше код создает новый сервер узла для запуска нашего приложения.

5. Откройте файл package.json и добавьте эту задачу в свойство script:

"start": "nodemon app.js"

Также измените основной скрипт на app.js.

Файл package.json должен выглядеть так:

6. На вашем терминале запустите npm start.. Это запустит сервер, вы должны увидеть сообщение консоли Запуск сервера по адресу« http: // localhost: 3000 .»

7. Создадим каталоги. Вернувшись в терминал в корне проекта, выполните следующие команды:

mkdir routes && mkdir controllers && mkdir images

8. Перейдите в папку контроллеры и создайте новый файл с именем pred.controller.js. Также перейдите в папку routes и создайте новый файл под названием pred.route.js.

9. В файл pred.route.js вставьте следующий код:

const express = require('express');
const multer = require('multer');
const controller = require('../controllers/predict.controller');
// configure multer
const storage = multer.diskStorage({
  destination: (req, file, callback) => {
    callback(null, 'images');
  },
  filename: (req, file, callback) => {
    callback(null, 'test-image.jpg');
  },
});
const imageFileFilter = (req, file, callback) => {
  if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
    return callback(new Error('You can upload only image files'), false);
  }
  callback(null, true);
};
const upload = multer({ storage, fileFilter: imageFileFilter });
const router = express.Router();
router.route('/').post(upload.single('file'), controller.makePredictions);
module.exports = router;

В приведенном выше коде мы настраиваем multer для обработки входного изображения и сохранения его в папке / image. Изображение переименовано в test-image.png для удобства чтения в нашем файле контроллера. Затем мы создаем экспресс-маршрутизатор, включающий многопользовательское промежуточное программное обеспечение, и вызываем функцию makePredictions, которую мы создадим дальше.

9. Теперь мы сделаем три вещи:

  • Загрузите модель MobileNet.
  • Прочтите файл необработанного изображения и преобразуйте его пиксельные данные в Tensor.
  • Удалите файл, чтобы освободить место.

Откройте файл pred.controller.js и вставьте следующий код:

const tf = require('@tensorflow/tfjs');
const mobilenet = require('@tensorflow-models/mobilenet');
const image = require('get-image-data');
const fs = require('fs');
exports.makePredictions = async (req, res, next) => {
  const imagePath = './images/test-image.jpg';
  try {
    const loadModel = async (img) => {
      const output = {};
      // laod model
      console.log('Loading.......')
      const model = await mobilenet.load();
      // classify
      output.predictions = await model.classify(img);
      console.log(output);
      res.statusCode = 200;
      res.json(output);
    };
    await image(imagePath, async (err, imageData) => {
      // pre-process image
      const numChannels = 3;
      const numPixels = imageData.width * imageData.height;
      const values = new Int32Array(numPixels * numChannels);
      const pixels = imageData.data;
      for (let i = 0; i < numPixels; i++) {
        for (let channel = 0; channel < numChannels; ++channel) {
          values[i * numChannels + channel] = pixels[i * 4 + channel];
        }
      }
      const outShape = [imageData.height, imageData.width, numChannels];
      const input = tf.tensor3d(values, outShape, 'int32');
      await loadModel(input);
// delete image file
      fs.unlinkSync(imagePath, (error) => {
        if (error) {
          console.error(error);
        }
      });
    });
  } catch (error) {
    console.log(error)
  }
};

Приведенный выше код сначала создает функцию makePrediction, которая включает функцию, которая загружает модель MobileNet и выводит прогнозы для параметра изображения. Затем мы читаем и декодируем данные изображения с помощью пакета get-image-data. Этот пакет декодирует ширину, высоту и двоичные данные изображения. После этого мы извлекаем значения пикселей изображения и преобразуем их в тензор. Затем мы вызываем функцию loadModel и передаем данные тензора изображения, чтобы сделать прогнозы. После этого удаляем файл изображения из памяти.

10. Наконец, давайте обновим файл app.js, добавив следующий код непосредственно над строкой PORT = process.env.PORT || 3000;

const predictRouter = require('./routes/predict.route')
app.use('/predict', predictRouter);

Здесь мы импортируем прогнозируемый маршрут и предоставляем его в конечной точке / прогнозируемой.

Для тестирования API воспользуемся почтальоном, скачать здесь. Убедитесь, что ваш сервер запущен, запустите npm start, чтобы запустить сервер.

Откройте почтальон и введите http: // localhost: 3000 / прогноз в разделе URL-адреса запроса, измените метод на POST, щелкните вкладку Body и выберите form-data . Нажмите кнопку раскрывающегося списка в разделе ключ и выберите Файл.

Введите значение «файл» в качестве ключа и нажмите «Выбрать файлы», чтобы загрузить файл изображения в качестве значения.

Нажмите кнопку Отправить. Через некоторое время вы должны увидеть следующее сообщение консоли:

Я выбрал изображение с гитарой, отсюда и результат.

ПРИМЕЧАНИЕ. Весь процесс занимает примерно 63 секунды и по умолчанию дает три лучших прогноза. Мы можем изменить это, передав параметр topk с числовым значением при вызове метода classify модели.

Также вы заметите сообщение в консоли, потому что я использовал пакет TensorFlow tfjs, у которого теперь есть альтернативный пакет для NodeJS здесь. К сожалению, он не поддерживает 32-битные машины, согласно T EnsorFlow.

Если вы работаете на 64-битной машине, вам нужно будет внести некоторые изменения, сначала при запуске терминала npm i @tensorflow/tfjs-node. , а затем в файле прогноз.controller.js обновите файл tf переменная в const tf = require('@tensorflow/tfjs-node').

Развертывание

Наш API готов к развертыванию! См. Полный проект на моем github здесь

Я буду развертывать проект на Heroku. Вы можете выполнить следующие действия.

  1. Если у вас нет учетной записи Heroku, зарегистрируйтесь здесь.
  2. Следуйте статье здесь, чтобы установить и настроить Heroku CLI.
  3. Клонируйте проект repo, потому что я добавил несколько изменений, таких как файл .gitignore и файл README.md, чтобы при постановке оставалась пустая папка / images.
  4. Откройте терминал и перейдите в папку клонированного проекта.
  5. Вставьте следующую команду и запустите.
git init && git add . && git commit -m “initial project commit” && heroku create && heroku apps:rename image-clf-api

Команда инициализирует пустой локальный репозиторий git, куда вы можете добавить все файлы проекта и выполнить фиксацию. Затем он создает новое приложение Heroku и переименовывает его в image-clf-api.

У вас должен быть результат, аналогичный изображенному ниже:

Наконец, давайте запустим следующую команду для развертывания на Heroku:

git push heroku master

Теперь протестируем наш живой API в почтальоне.

В предыдущем окне почтальона замените URL-адрес на https://image-clf-api.herokuapp.com/predict и нажмите Отправить. Теперь вы должны получать прогнозы за меньшее время. Примерно 17 секунд здесь.

Мы также можем протестировать это в веб-среде. Создайте файл index.html в любом каталоге и вставьте приведенный ниже код.

<!DOCTYPE html>
<html lang="en">
<body>
  <form name="myForm" method="post" enctype="multipart/form-data">
    Select Image: <input type='file' name='file' id='image-upload'>
    <button type='submit' id="submit-btn">Submit</button>
  </form>
  <div id="result"></div>
  <script>
    const button = document.querySelector('#submit-btn')
    button.addEventListener('click', async (e) => {
      e.preventDefault();
      const URL = 'https://image-clf-api.herokuapp.com/predict'
      const image = document.querySelector('#image-upload');
      const resultDiv = document.querySelector('#result')
      const formData = new FormData();
      formData.append("file", image.files[0]);
      const response = await fetch(URL, {
        method: 'POST',
        body: formData
      });
      const result = await response.json();
      resultDiv.innerHTML = JSON.stringify(result.predictions);
      console.log(result);
    });
  </script>
</body>
</html>

Откройте файл в любом браузере, загрузите изображение и нажмите Отправить.

Заключение

Я надеюсь, что эта статья послужила целью дать вам фору в понимании того, как реализовать модели Tensorflow.js в NodeJS. API можно настроить для использования в любых клиентских приложениях и для любых моделей концентраторов TensorFlow.

Свяжитесь со мной в Твиттере здесь

Примечание редактора. Heartbeat - это онлайн-издание и сообщество, созданное авторами и посвященное предоставлению первоклассных образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.

Независимо от редакции, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и группам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим участникам и не продаем рекламу.

Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее и лучше строить лучшие модели машинного обучения.