Help us understand the problem. What is going on with this article?

ブラウザでの画像オブジェクトの検出

はじめに

こんにちは streampack チームのメディです。
https://cloudpack.jp/service/option/streampack.html

Copyrights of photos ・ 写真の著作権

https://www.pexels.com/photo/woman-sitting-on-top-of-volkswagen-2845631/
https://www.pexels.com/photo/photography-of-three-dogs-looking-up-850602/
https://www.pexels.com/photo/woman-in-blue-denim-jacket-holding-brushing-her-siberian-husky-4148879/

What is tensorflowjs.js ・ tensorflowjsとは

tensorflow.js is a machine learning library that can be used directly in the browser.
tensorflow.jsは、ブラウザで直接使用できる機械学習ライブラリーです。

This demo is using tensorflow.js with the coco-ssd model.
このデモでは、coco-ssdモデルでtensorflow.jsを使用しています。

Screen Shot 2020-04-24 at 11.00.17.pngScreen Shot 2020-04-24 at 10.56.25.png
Screen Shot 2020-04-24 at 10.55.31.png

Objective ・ 目的

Learning how to use tensorflow.js via a simple example.
簡単な例でtensorflow.jsの使用方法を学びます。

Implementation

For every photo, if there are detections, there is a callback with the following information:

  • Object type
  • Detection reliability (between 0 and 1)
  • Bounding box

すべての写真について、検出があると、次の情報を含むコールバックがあります。

  • オブジェクトタイプ
  • 検出の信頼性(0から1の間)
  • 境界ボックス

The bounding boxes are drawn on a canvas over the original picture.
境界ボックスは、元の画像の上にキャンバスに描画されます。

<!DOCTYPE html>
<html>

<head>

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous" playsinline>

  <!-- jQuery & Bootstrap JS -->
  <script src="//code.jquery.com/jquery-3.3.1.slim.min.js" crossorigin="anonymous"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script>
  <script src="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script>

  <!-- Load TensorFlow.js -->
  <script src="//cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.7.2/dist/tf.min.js"></script>
  <!-- Load the coco-ssd model. -->
  <script src="//cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd@2.0.2/dist/coco-ssd.js"></script>

  <style>
    body {
      text-align: left;
    }

    .img {
      position: absolute;
      z-index: 1;
      max-width: 100%;
      height: auto;
    }

    #main_container {
      display: inline-block;
      margin: 0 auto;
      position: relative;
    }

    #cv1 {
      position: relative;
      z-index: 20;
    }

    #top_div {
      padding: 1em;
    }

    #loader_div {
      display: inline-block;
    }

    #spinner_div {
      display: inline-block;
    }
  </style>
</head>

<body>
  <div>

    <div id="top_div">
      <H2>Coco SSD + tensorflowjs</H2>
      <div id="loader_div">
        <p id="loader_info">Loading model...
          <p />
      </div>

      <div id="spinner_div" class="spinner-border" role="status">
        <span class="sr-only"></span>
      </div>
      <br></br>
      <input id="input_btn" type='file' />
    </div>
    <br></br>
    <div class="container" id="main_container">
      <img class="img" id="img" width="640" width="360">
      <canvas class="canvas" id="cv1"></canvas>
    </div>
  </div>
  <script type="text/javascript">
    var img;
    var c = document.getElementById("cv1");
    var ctx = c.getContext("2d");


    var img = document.getElementById('img');
    var isModelLoaded = false;
    var globalModel = null;

    //Load the model.
    cocoSsd.load().then(model => {
      isModelLoaded = true;
      updateTitle();
      if (document.getElementById("img").src != "") {
        startPredictions(model, img);
      }
    });

    function startPredictions(model, img) {
      model.detect(img).then(predictions => {
        predictions.map((item, index) => {
          console.log(item);
          let borderColor = getColorByIndex(index);
          draw(item, borderColor);
        });
      });
    }

    function resizeCanvas(element) {
      var w = element.offsetWidth;
      var h = element.offsetHeight;
      var cv = document.getElementById("cv1");
      cv.width = w;
      cv.height = h;
    }

    function draw(item, boderColor) {
      let scorePercentage = (parseFloat(item.score) * 100).toFixed(2);
      let fontBase = 1000;
      let fontSize = 12;
      let textColor = "#FF0000";
      let backgroundColor = "rgba(255, 255, 255, 0.7)"; //"#fff";

      ctx.beginPath();
      ctx.rect(item.bbox[0], item.bbox[1], item.bbox[2], fontSize + 5);
      ctx.fillStyle = backgroundColor;
      ctx.fill();
      ctx.font = `bold ${fontSize}px sans-serif`;
      ctx.fillStyle = textColor;
      ctx.fillText("  " + item.class + "  " + scorePercentage + "%", item.bbox[0], item.bbox[1] + fontSize);
      ctx.rect(item.bbox[0], item.bbox[1], item.bbox[2], item.bbox[3]);
      ctx.strokeStyle = boderColor;
      ctx.lineWidth = 3;
      ctx.stroke();
    }

    function getColorByIndex(index) {
      var color = "#FF0000";
      var colors = ["#FF0000", "#fff000", "#ff7100", "#8fff00", "#7100ff", "#f000ff", "#00fff0"];
      try {
        if (index < colors.length - 1) {
          color = colors[index];
        } else {
          let random = Math.floor(Math.random() * ((colors.length - 1) + 1));
          color = colors[random];
        }
      } catch (e) {
        console.log(e);
      }
      return color;
    }

    //Image loading 
    window.addEventListener('load', function() {
      document.querySelector('input[type="file"]').addEventListener('change', function() {
        if (this.files && this.files[0]) {
          var img = document.querySelector('img');
          img.src = URL.createObjectURL(this.files[0]);
          img.onload = imageIsLoaded;
        }
      });
    });

    function imageIsLoaded() {
      resizeCanvas(img);
      cocoSsd.load().then(model => {
        if (isModelLoaded) {
          startPredictions(model, img);
        }
      });
    }

    function updateTitle() {
      var title = document.getElementById("loader_info");
      title.textContent = "Model loaded successfully";
      var element = document.getElementById("spinner_div");
      element.classList.remove("spinner-border");
    }

    function getFont(canvas, fontSize, fontBase) {
      var ratio = fontSize / fontBase;
      var size = canvas.width * ratio;
      return (size | 0) + 'px bold sans-serif';
    }
  </script>
</body>

</html>

DEMO ・ デモ

https://codepen.io/mr1985/pen/LYpWVyo

Information sources ・ 情報元

https://www.tensorflow.org/
https://www.pexels.com/

mehdi
cloudpack
Amazon Web Services (AWS) の導入設計、環境構築、運用・保守をサポートするマネジドホスティングサービス
https://cloudpack.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした