顔検出のチュートリアル

目標

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

料金

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

  • Google Cloud Vision API

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

始める前に

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

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

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

    [リソースの管理] ページに移動

  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 のサポートページをご覧ください。