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

Watson Visual Recognitionで画像認識してみた!

More than 1 year has passed since last update.

概要

WatsonAPIが面白そうなので、試してみました!
中でも一番そそられたのは「Visual Recognition」です。
https://www.ibm.com/watson/jp-ja/developercloud/visual-recognition.html

Visual RecognitionはWatsonの画像認識機能です。すぐにお使いいただけるようにWatsonが既に学習をしており、画像・映像フレームに写った複数のものや、情景を分析・認識することができます。また、機械学習によりWatsonに独自の学習をさせることもできます。すでに、自社製品の認識・分類や、製造ラインにおける欠陥検出といった多種多様なお客様の業務で、高い精度の画像認識を少ない画像枚数による短時間の機械学習で実現しています。さらに、日本語・英語を含む多数の言語で認識結果を返すことができます。

ということで、画像から「意味」を見出すという・・・ワクワクが止まらねぇ~~~

IBM Cloudアカウント登録

1. IBM Cloudのライトアカウントを登録

こちらにアクセスし、
https://www.ibm.com/watson/jp-ja/developercloud/visual-recognition.html
無料で使用できるライトアカウントがありますので、「IBM Cloudのライトアカウントを登録」してください。
pic1.png

2. 検索欄で「Visual Recognition」を検索します。

pic2.png

3. サービスを作成します。

pic3.png

4. アカウント情報を入力し、登録

pic4.png

API接続情報を確認

左上ハンバーガーメニューから「ダッシュボード」を開くと、登録したサービス一覧が表示されます。
そこから先ほど登録したVisualRecognitionのサービスを開くと、資格情報が表示されます。
pic6.png

資格情報は後ほど使います。

プログラム作成

今回はNode.jsでVisualRecognitionAPIを使用しました。

1. Expressアプリの作成

DOS
express myFirstVR
cd myFirstVR
npm install

2. watson-developer-cloudのインストール

DOS
npm i --save watson-developer-cloud

3. APIへの接続・呼び出し

API接続を管理するクラスを作成します。
ルートフォルダにapiフォルダを作成し、その中にVisualRecognition.jsファイルを作成します。

{API鍵}には前段で取得したAPI鍵を入力してください。

api/VisualRecognition.js
const VisualRecognitionV3 = require('watson-developer-cloud/visual-recognition/v3');
const fs = require('fs');

const visualRecognition = new VisualRecognitionV3({
    version: '2018-03-19',
    'iam_apikey': '{API 鍵}',
    'url': 'https://gateway.watsonplatform.net/visual-recognition/api',
});

module.exports = class VisualRecognition {
    constructor(imagePath) {
        this.image = fs.createReadStream(imagePath);
        this.params = {
            images_file: this.image,
            accept_language: 'ja'
        };
    }

    analyze() {
        return new Promise((resolve, reject) => {
            visualRecognition.classify(this.params, (err, response) => {
                if (err) {
                    reject(err);
                };
                resolve(response);
            });
        });
    }
}

4. Routerの作成

ブラウザからのHTTPリクエストに応答するRouterを作成します。

画像のアップロードにMulterを使用するので、npm installしておきます。

DOS
npm i --save multer
routes/visualrecofnition.js
var express = require('express');
var router = express.Router();

// 画像アップロードに必要
const multer = require('multer');

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        // 保存したいパス
        cb(null, './public/images')
    },
    filename: function (req, file, cb) {
        // アップロードしたときのファイル名で保存
        cb(null, file.originalname)
    }
})

const upload = multer({
    storage: storage
})

// VisualRecognitionクラスを読み込み
const VisualRecognition = require('../api/VisualRecognition');
const fs = require('fs');

// 入力フォームへのルーティング
router.get('/', function (req, res, next) {
    res.render('VisualRecognition/index', {
        title: "VisualRecognition API Test"
    });
});

// 入力フォームからのPOST待ち付け
router.post('/', upload.single('thumbnail'), function (req, res, next) {
    console.log(JSON.stringify(req.file, null, 2));
    var filePath = './' + req.file.path;

    var vr = new VisualRecognition(filePath);

   // 分析実行
    vr.analyze().then((resJson) => {
        var image = resJson.images[0].image;
        var datas = resJson.images[0].classifiers[0].classes;

        res.render('VisualRecognition/result', {
            title: "VisualRecognition API Test",
            name: image,
            path: "/images/" + image,
            datas: datas
        });
    }).catch((error) => {
        console.log(error);
        res.send(error);
    });
});

module.exports = router;

5. Routerの読み込み

先ほど作成したRouterをアプリで使用するため、app.jsに下記2行を追加しています。
var vrRouter = require('./routes/visualrecognition');
app.use('/vr', vrRouter);

app/js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var vrRouter = require('./routes/visualrecognition'); // 追加

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/vr', vrRouter); // 追加

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

6. layoutファイルの編集

よーし画面まで作るぞ!ってことでBootstrapを使っていきます。

共通アイテムはlayout.jadeに書くことができますので、活用していきます。

layout.jade
doctype html
html
    head
        title= title
        link(rel='stylesheet', href='/stylesheets/style.css')
        link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css', integrity='sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm', crossorigin='anonymous')
        meta(charset='utf-8')
        meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
        meta(name='description', content='')
        meta(name='author', content='')
        link(rel='icon', href='../../../../favicon.ico')
    body
        nav.navbar.navbar-expand-md.navbar-dark.bg-dark.fixed-top
            a.navbar-brand(href='#') #{title}
            | 
            button.navbar-toggler(type='button', data-toggle='collapse', data-target='#navbarsExampleDefault', aria-controls='navbarsExampleDefault', aria-expanded='false', aria-label='Toggle navigation')
                span.navbar-toggler-icon
            | 
            #navbarsExampleDefault.collapse.navbar-collapse
                ul.navbar-nav.mr-auto
                    li.nav-item.active
                        a.nav-link(href='/')
                            | Home 
                            span.sr-only (current)
        main.container(role='main', style="margin-top:20px;")
            block content
        script(src='https://code.jquery.com/jquery-3.2.1.slim.min.js', integrity='sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN', crossorigin='anonymous')
        script(src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js', integrity='sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q', crossorigin='anonymous')
        script(src='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js', integrity='sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl', crossorigin='anonymous')

ナビゲーションバーを配置し、BootstrapのCDNを指定しました。
各コンテンツはblock contentにincludeされます。

7. 画像アップロードフォームの作成

viewsフォルダにVisualRecognitionというフォルダを作成し、index.jadeファイルを作成します。

views/VisualRecognition/index.jade
extends ../layout

block content
    form(method="POST", enctype="multipart/form-data", action="./vr")
        .form-group
            input.form-control(type="file", name="thumbnail")
        .form-group
            button.form-control.btn.btn-primary(type="submit") 送信

アップロード画面ができたので、一度確認してみましょう。

DOS
npm start

でアプリを起動し、http://localhost:3000/vr にアクセスすると見れると思います。

pic7.png

ただのファイルアップロードフォームと送信ボタンです。

8. 結果確認画面の作成

それでは、結果を確認する画面を作成していきます。
views/VisualRecognitionフォルダの中にresult.jadeファイルを作成します。

views/VisualRecognition/index.jade
extends ../layout

block content
    h1= name

    img.img-fluid(src="#{path}")
    table.table
        thead
            th class
            th score
        tbody
            for data in datas
                tr
                    td #{data.class}
                    td #{data.score}

再度動作させてみます。
適当な画像をアップロードし、送信!!

pic15.png

「ホテル建築」や「ホテル・カジノ」といった印象だそうです。夜とか、キラキラ感からそうなるのでしょうか・・・?
本当にホテルなのかは知りません()が、そう言われればそう見えます。
また、「時計台」という判断は完璧ですね!!

別の画像も試してみます。
pic16.png

かなりの精度ですね!!すご!!!おもしろ!!!!

感想

めっちゃおもしろいので一日中遊べますが、APIの利用回数制限が厳しいので、サービスにするにはライトアカウントじゃちょっときついですかね!!

参考

tsumasakky
自社WebアプリケーションのSE(開発、販売、営業) -> Webアプリケーション受託開発のPG ※ 記事の内容は個人の見解であり所属する組織の公式見解ではありません。(当然ながら)
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