顔検出のチュートリアル

目標

このサンプルでは、Google Cloud Vision API を使用して画像の中の顔を検出します。顔が正しく検出されたことを証明するために、このデータを使用して顔のそれぞれを囲むボックスを描画します。

料金

このチュートリアルでは、以下を含む、Cloud Platform の課金対象となるコンポーネントを使用しています。

  • Google Cloud Vision API

料金計算ツールを使用すると、想定される利用方法に基づいて費用の見積もりを作成できます。 Cloud Platform を初めて使用する方は、無料トライアルをご利用いただける場合があります。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP プロジェクトを選択または作成します。

    プロジェクト セレクタのページに移動

  3. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。

  4. Google Cloud Vision API を有効にします。

    APIを有効にする

  5. アプリケーションのデフォルト認証情報を使用するための環境を設定します。
  6. 言語固有のタスクとツールを設定します。

    C#

    Node.js

    • Google クライアント ライブラリをインストールします。
    • node.js をインストールします。
    • API リファレンス
    • npmnode-canvas をインストールします。サンプルコードには package.json が含まれており、すべての依存関係をコマンド npm install でインストールできます。node-canvas には、この他にもインストールが必要な依存関係が存在することがあります。詳しくは、node-canvas のインストール ドキュメントをご覧ください。

      {
        "name": "nodejs-docs-samples-vision",
        "version": "0.0.1",
        "private": true,
        "license": "Apache-2.0",
        "author": "Google Inc.",  //NOTYPO
        "repository": "googleapis/nodejs-vision",
        "engines": {
          "node": ">=8"
        },
        "scripts": {
          "test": "ava -T 1m --verbose system-test/*.test.js"
        },
        "dependencies": {
      
          "@google-cloud/automl": "^0.1.1",
          "@google-cloud/vision": "^0.22.0",
          "async": "^2.6.1",
          "mathjs": "^5.0.4",
          "natural": "^0.6.1",
          "redis": "^2.8.0",
          "yargs": "^12.0.0"
        },
        "devDependencies": {
          "@google-cloud/nodejs-repo-tools": "^2.3.0",
          "@google-cloud/storage": "^2.0.0",
          "ava": "^0.25.0",
          "proxyquire": "^2.0.1",
          "sinon": "^6.0.1",
          "uuid": "^3.2.1"
        },
        "optionalDependencies": {
          "canvas": "^1.6.11"
        }
      }
      

    PHP

    Python

    Ruby

サービス オブジェクトを作成する

Google の API に公式クライアント SDK を使用してアクセスするには、その API のディスカバリ ドキュメントに基づいてサービス オブジェクトを作成します。このドキュメントは、SDK に対する API を記述するものです。デベロッパーは、自分の認証情報を使用してこのドキュメントを Vision API のディスカバリ サービスから取得する必要があります。

C#

using Google.Cloud.Vision.V1;
using System;
using System.Linq;
var client = ImageAnnotatorClient.Create();

Node.js

// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GCLOUD_PROJECT environment variable. See
// https://googlecloudplatform.github.io/gcloud-node/#/docs/google-cloud/latest/guides/authentication
const vision = require('@google-cloud/vision');
// Creates a client
const client = new vision.ImageAnnotatorClient();

const fs = require('fs');

PHP

use Google\Cloud\Vision\V1\ImageAnnotatorClient;
$imageAnnotator = new ImageAnnotatorClient();

Python

from google.cloud import vision
from google.cloud.vision import types
from PIL import Image, ImageDraw
client = vision.ImageAnnotatorClient()

Ruby

require "google/cloud/vision"
vision = Google::Cloud::Vision.new project: project_id

顔検出リクエストを送信する

Vision API へのリクエストを作成するには、最初に API のドキュメントを調べます。この例では、images リソースを使用して画像への annotate を行います。この API へのリクエストは、requests リストを持つオブジェクトの形を取ります。このリスト内のアイテムのそれぞれに、次の 2 つの情報が格納されます。

  • base64 エンコード済みの画像データ
  • その画像についてアノテーションを付けたい機能のリスト

この例では、1 つの画像の FACE_DETECTION アノテーションをリクエストし、該当する画像部分のレスポンスを返します。

C#

var response = client.DetectFaces(Image.FromFile(args[0]));

Node.js

function detectFaces(inputFile, callback) {
  // Make a call to the Vision API to detect the faces
  const request = {image: {source: {filename: inputFile}}};
  client
    .faceDetection(request)
    .then(results => {
      const faces = results[0].faceAnnotations;
      const numFaces = faces.length;
      console.log('Found ' + numFaces + (numFaces === 1 ? ' face' : ' faces'));
      callback(null, faces);
    })
    .catch(err => {
      console.error('ERROR:', err);
      callback(err);
    });
}

PHP

# annotate the image
// $path = 'path/to/your/image.jpg'
$image = file_get_contents($path);
$response = $imageAnnotator->faceDetection($image);
$faces = $response->getFaceAnnotations();

Python

def detect_face(face_file, max_results=4):
    """Uses the Vision API to detect faces in the given file.

    Args:
        face_file: A file-like object containing an image with faces.

    Returns:
        An array of Face objects with information about the picture.
    """
    client = vision.ImageAnnotatorClient()

    content = face_file.read()
    image = types.Image(content=content)

    return client.face_detection(image=image).face_annotations

Ruby

image = vision.image path_to_image_file
faces = image.faces

レスポンスを処理する

画像の中の顔が検出されました。顔アノテーション リクエストに対するレスポンスの中には、検出された顔についての多数のメタデータが含まれています。このメタデータの中には、その顔を囲むポリゴンの座標があります。ただし、この時点では、これは単なる数字のリストです。これを使って、画像の中の顔が確かに検出されたことを確認しましょう。Vision API から返された座標を使用して、画像のコピーの上にポリゴンを描画します。

C#

using (var image = System.Drawing.Image.FromFile(args[0]))
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(image))
{
    var cyanPen = new System.Drawing.Pen(System.Drawing.Color.Cyan, 3);
    foreach (var annotation in response)
    {
        g.DrawPolygon(cyanPen, annotation.BoundingPoly.Vertices.Select(
            (vertex) => new System.Drawing.Point(vertex.X, vertex.Y)).ToArray());
        // ...
    }
    // ...
}

Node.js

node-canvas ライブラリを使用して画像の上に描画します。

function highlightFaces(inputFile, faces, outputFile, Canvas, callback) {
  fs.readFile(inputFile, (err, image) => {
    if (err) {
      return callback(err);
    }

    const Image = Canvas.Image;
    // Open the original image into a canvas
    const img = new Image();
    img.src = image;
    const canvas = new Canvas(img.width, img.height);
    const context = canvas.getContext('2d');
    context.drawImage(img, 0, 0, img.width, img.height);

    // Now draw boxes around all the faces
    context.strokeStyle = 'rgba(0,255,0,0.8)';
    context.lineWidth = '5';

    faces.forEach(face => {
      context.beginPath();
      let origX = 0;
      let origY = 0;
      face.boundingPoly.vertices.forEach((bounds, i) => {
        if (i === 0) {
          origX = bounds.x;
          origY = bounds.y;
        }
        context.lineTo(bounds.x, bounds.y);
      });
      context.lineTo(origX, origY);
      context.stroke();
    });

    // Write the result to a file
    console.log('Writing to file ' + outputFile);
    const writeStream = fs.createWriteStream(outputFile);
    const pngStream = canvas.pngStream();

    pngStream.on('data', chunk => {
      writeStream.write(chunk);
    });
    pngStream.on('error', console.log);
    pngStream.on('end', callback);
  });
}

PHP

GD 拡張機能を使用して画像の上に描画します。

# draw box around faces
if ($faces && $outFile) {
    $imageCreateFunc = [
        'png' => 'imagecreatefrompng',
        'gd' => 'imagecreatefromgd',
        'gif' => 'imagecreatefromgif',
        'jpg' => 'imagecreatefromjpeg',
        'jpeg' => 'imagecreatefromjpeg',
    ];
    $imageWriteFunc = [
        'png' => 'imagepng',
        'gd' => 'imagegd',
        'gif' => 'imagegif',
        'jpg' => 'imagejpeg',
        'jpeg' => 'imagejpeg',
    ];

    copy($path, $outFile);
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
    if (!array_key_exists($ext, $imageCreateFunc)) {
        throw new \Exception('Unsupported image extension');
    }
    $outputImage = call_user_func($imageCreateFunc[$ext], $outFile);

    foreach ($faces as $face) {
        $vertices = $face->getBoundingPoly()->getVertices();
        if ($vertices) {
            $x1 = $vertices[0]->getX();
            $y1 = $vertices[0]->getY();
            $x2 = $vertices[2]->getX();
            $y2 = $vertices[2]->getY();
            imagerectangle($outputImage, $x1, $y1, $x2, $y2, 0x00ff00);
        }
    }

Python

def highlight_faces(image, faces, output_filename):
    """Draws a polygon around the faces, then saves to output_filename.

    Args:
      image: a file containing the image with the faces.
      faces: a list of faces found in the file. This should be in the format
          returned by the Vision API.
      output_filename: the name of the image file to be created, where the
          faces have polygons drawn around them.
    """
    im = Image.open(image)
    draw = ImageDraw.Draw(im)

    for face in faces:
        box = [(vertex.x, vertex.y)
               for vertex in face.bounding_poly.vertices]
        draw.line(box + [box[0]], width=5, fill='#00ff00')

    im.save(output_filename)

Ruby

rmagick gem を使用して画像の上に描写します。

require "rmagick"
  image = Magick::Image.read(path_to_image_file).first

  faces.each do |face|
    puts "Face bounds:"
    face.bounds.face.each do |vector|
      puts "(#{vector.x}, #{vector.y})"
    end

    draw = Magick::Draw.new
    draw.stroke = "green"
    draw.stroke_width 5
    draw.fill_opacity 0

    x1 = face.bounds.face[0].x.to_i
    y1 = face.bounds.face[0].y.to_i
    x2 = face.bounds.face[2].x.to_i
    y2 = face.bounds.face[2].y.to_i

    draw.rectangle x1, y1, x2, y2
    draw.draw image
  end

  image.write path_to_output_file

  puts "Output file: #{path_to_output_file}"

すべてをまとめる

C#

static readonly string s_usage = @"dotnet run image-file

Use the Google Cloud Vision API to detect faces in the image.
Writes an output file called image-file.faces.
";
public static void Main(string[] args)
{
    if (args.Length < 1)
    {
        Console.WriteLine(s_usage);
        return;
    }

    var client = ImageAnnotatorClient.Create();
    var response = client.DetectFaces(Image.FromFile(args[0]));

    int numberOfFacesFound = 0;
    using (var image = System.Drawing.Image.FromFile(args[0]))
    using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(image))
    {
        var cyanPen = new System.Drawing.Pen(System.Drawing.Color.Cyan, 3);
        foreach (var annotation in response)
        {
            g.DrawPolygon(cyanPen, annotation.BoundingPoly.Vertices.Select(
                (vertex) => new System.Drawing.Point(vertex.X, vertex.Y)).ToArray());
            // ...
        }
        // ...
    }
    // ...
}

サンプルをビルドするには、ソリューション ファイル dotnet-doc-samples/vision/api/Vision.sln を Visual Studio で開いて、ソリューションをビルドします。

サンプルの実行方法:

C:\...\> cd dotnet-docs-samples\vision\api\DetectFaces\bin\Debug
C:\...\bin\Debug> DetectFaces ..\..\..\VisionTest\data\face.png

Node.js

function main(inputFile, outputFile, Canvas, callback) {
  outputFile = outputFile || 'out.png';
  detectFaces(inputFile, (err, faces) => {
    if (err) {
      return callback(err);
    }

    console.log('Highlighting...');
    highlightFaces(inputFile, faces, outputFile, Canvas, err => {
      if (err) {
        return callback(err);
      }
      console.log('Finished!');
      callback(null, faces);
    });
  });
}

サンプルを実行するには、次のコマンドをサンプルコードのディレクトリから実行します。

node faceDetection face.png

PHP

call_user_func($imageWriteFunc[$ext], $outputImage, $outFile);
printf('Output image written to %s' . PHP_EOL, $outFile);

サンプルを実行するには、次のコマンドをサンプルコードのディレクトリから実行します。

composer install
php vision.php face images/face.png output-image.png

Python

def main(input_filename, output_filename, max_results):
    with open(input_filename, 'rb') as image:
        faces = detect_face(image, max_results)
        print('Found {} face{}'.format(
            len(faces), '' if len(faces) == 1 else 's'))

        print('Writing to file {}'.format(output_filename))
        # Reset the file pointer, so we can read the file again
        image.seek(0)
        highlight_faces(image, faces, output_filename)

Ruby

if __FILE__ == $PROGRAM_NAME
  project_id = ENV["GOOGLE_CLOUD_PROJECT"]

  if ARGV.size == 2
    draw_box_around_faces path_to_image_file:  ARGV.shift,
                          path_to_output_file: ARGV.shift,
                          project_id:          project_id
  else
    puts <<-usage
Usage: ruby draw_box_around_faces.rb [input-file] [output-file]

Example:
  ruby draw_box_around_faces.rb images/face.png output-image.png
    usage
  end
end

サンプルを実行するには、次のコマンドをサンプルコードのディレクトリから実行します。

bundle install
bundle exec ruby draw_box_around_faces.rb images/face.png output-image.png

入力画像 出力画像

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。
このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Cloud Vision API ドキュメント
ご不明な点がありましたら、Google のサポートページをご覧ください。