LoginSignup
4
4

【ハンズオン】ReactとGoogle Cloud Vision APIで画像認識アプリを作ろう【TypeScript】

Posted at

はじめに

Google Cloud Vision APIは、Googleが提供する機械学習を活用した画像解析サービスです。

このAPIを使用することで、開発者は画像に含まれる情報を自動的に抽出し、様々な解析を行うことができます。

今回、Reactを使ってGoogle Cloud Vision APIを使って簡単な画像認識アプリを作ってみました。

1. 環境構築

Node環境があることを前提にして行います。

templateはtypescriptを指定して、Google Cloud Vision APIをコールするためにaxiosをインストールしておきます。

npm startしてReactの初期画面が表示されれば成功です。

$ cd google-vision-app
$ npm i axios
$ npm start

2. Cloud Vision APIの設定

スクリーンショット 2024-05-25 17.03.45.png

Cloud Vision APIはGCPの管理画面の検索窓から「Cloud Vision API」を実行し、有効化されていない場合は「有効化」するを押します。

「このAPIを使用するには、認証情報が必要になる可能性があります」と表示された場合は、「認証情報」から「認証情報を作成」します。

作成後、APIキーが表示されるのでコピーしておきます。

3. 環境変数の設定

作成したAPIキーを.envファイルを作成し、環境変数を設定します。

creare-react-appで作ったプロジェクトはprocess.env.REACT_APP_から始まる変数を読み込みができるようになっています。

.env
REACT_APP_GOOGLE_CLOUD_VISION_API_KEY=xxxxxxxxxxxx

4. Cloud Vision APIを呼び出す

Cloud Vision APIのキーを設定できたら、実際にCloud Vision APIを呼び出して結果を表示するようにします。

流れとしては、画像をアップロードしたら、Cloud Vision APIを呼び出して、レスポンスを整形して画面に表示するといった感じです。

App.tsx

import React, { useState } from 'react';
import axios from 'axios';

interface LabelAnnotation {
  description: string;
  score: number;
}

const App: React.FC = () => {
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [labels, setLabels] = useState<LabelAnnotation[]>([]);

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (event.target.files && event.target.files.length > 0) {
      setSelectedFile(event.target.files[0]);
    }
  };

  const handleFileUpload = async () => {
    if (!selectedFile) return;

    const reader = new FileReader();
    reader.readAsDataURL(selectedFile);
    reader.onloadend = async () => {
      const base64String = reader.result?.toString().replace(/^data:image\/[a-z]+;base64,/, "");

      try {
        const apiKey = process.env.REACT_APP_GOOGLE_CLOUD_VISION_API_KEY;
        const response = await axios.post(
          `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`,
          {
            requests: [
              {
                image: {
                  content: base64String,
                },
                features: [
                  {
                    type: 'LABEL_DETECTION',
                    maxResults: 10,
                  },
                ],
              },
            ],
          }
        );

        const labelAnnotations = response.data.responses[0].labelAnnotations;
        const labels: LabelAnnotation[] = labelAnnotations.map((annotation: {description: string, score: string}) => ({
          description: annotation.description,
          score: annotation.score,
        }));

        setLabels(labels);
      } catch (error) {
        console.error('Error uploading file:', error);
      }
    };
  };

  return (
    <div className="App">
      <h1>Google Cloud Vision API Demo</h1>
      <input type="file" onChange={handleFileChange} />
      <button onClick={handleFileUpload}>アップロードして解析</button>
      {labels.length > 0 && (
        <div>
          <h2>解析結果:</h2>
          <table>
            <thead>
              <tr>
                <th>ラベル</th>
                <th>スコア</th>
              </tr>
            </thead>
            <tbody>
              {labels.map((label, index) => (
                <tr key={index}>
                  <td>{label.description}</td>
                  <td>{label.score.toFixed(2)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
};

export default App;

5. 画像認識アプリを動かす

takenoko.jpg

では実際に動かしてみます。適当に画像を用意して、実行してみます。

今回はたけのこの画像を用意して、アップロードして解析してみました。結果は以下の通りです。

スクリーンショット 2024-05-25 17.07.08.png

食べ物や植物に対して高いスコアが出ています。他も材料や自然な食べ物、主食などわりと的確にラベリングできていると思います。

6. スタイルを整える

最後にスタイルを整えます。特にこだわりがないようであれば、そのままコピペして使用して大丈夫です。

App.css
.App {
  text-align: center;
  font-family: 'Arial', sans-serif;
  margin: 20px;
}

h1 {
  color: #333;
  font-size: 2em;
  margin-bottom: 20px;
}

input[type="file"] {
  display: block;
  margin: 20px auto;
  padding: 10px;
  font-size: 1em;
}

button {
  background-color: #4CAF50;
  color: white;
  border: none;
  padding: 10px 20px;
  font-size: 1em;
  cursor: pointer;
  border-radius: 5px;
}

button:hover {
  background-color: #45a049;
}

table {
  margin: 20px auto;
  border-collapse: collapse;
  width: 80%;
  max-width: 600px;
}

table th, table td {
  border: 1px solid #ddd;
  padding: 8px;
}

table th {
  background-color: #f2f2f2;
  color: #333;
  text-align: left;
}

table tr:nth-child(even) {
  background-color: #f9f9f9;
}

table tr:hover {
  background-color: #ddd;
}

table th, table td {
  text-align: left;
}

CSSを書いたら、App.tsxに以下のimportを追加して完了です。

App.tsx
import './App.css';

今度はラーメンの画像で実行してみます。

ramen.jpg

スクリーンショット 2024-05-25 22.06.39.png

ローカルの画面を見ると、良い感じのデザインになりました。あとは画像のプレビューやラベルの日本語化などしても良いかもしれません。

おわりに

今回はCloud Vision APIを利用して簡単な画像認識アプリを実装しました。

画像認識してラベリングした結果をDBに保存するなどするとより実用的なアプリになるかと思います。

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう!
実践重視:即戦力を育てるアウトプット中心のプログラム。
モダンなスキル : Reactを中心としたモダンな技術を学べる。
キャリアアップ:スキルアップだけでなく、キャリアパスのサポートも充実。
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください!
▼▼▼
https://projisou.jp/

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4