LoginSignup
0
0

More than 1 year has passed since last update.

Angular×Spring Boot×AWS Rekognitionで笑顔認識アプリ作り

Last updated at Posted at 2021-05-05

前回までのあらすじ

上から順番になっております。
https://qiita.com/NoOne/items/c7b5b2bd84fa9ca317d5

https://qiita.com/NoOne/items/9019baf366aaeb000e68


ソースコード

https://github.com/yukihiro-maeda0731/AngularDetectFace/tree/master (Angular)
https://github.com/yukihiro-maeda0731/SpringDetectFace/tree/master (Spring Boot)

Angularで撮影した画像をSpringに送る

HTMLのvideoで撮影しCanvasに描写した画像データをSpringにHttp通信で送るため.toDataURL()でBase64形式に変換しております。

app.component.ts
import { Component } from '@angular/core';
import { ImgService } from './img.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent  { 
  constructor(private service: ImgService) { }
  private video: any;
  // Springから返ってくる笑顔の判定メッセージを格納
  result: String = ""; 

  //撮影フォーム設定
  ngOnInit(): void {
    this.video = document.querySelector('video')!;

    const options = {
      video: true
    }
    navigator.mediaDevices.getUserMedia(options)
    .then(stream => {
      this.video.srcObject = stream;
    })
    .catch((error) =>{
      console.log(error);
    })
  }

  //撮影ボタン押下時の処理
  captureImg(){
    let canvas = document.getElementById('canvas') as HTMLCanvasElement;
    const context = canvas.getContext('2d');
    context?.drawImage(this.video, 0, 0, canvas.width, canvas.height);
    let base64CapturedImg : ConstrainDOMString = canvas.toDataURL("image/png");
    this.service.transferImg(base64CapturedImg).subscribe(
      data => this.result = data,
      error => console.log(error)
    );
  ;
  }
}



Http通信を行うためのserviceを作成します。現段階ではローカルのみでの動作となるのでurlはspringのlocalhostです。
img.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ImgService {

  constructor(private http: HttpClient) { }

  private destinationUrl = 'http://localhost:8080';


  transferImg(base64CapturedImg: String): Observable<any> {
    return this.http.post(this.destinationUrl, base64CapturedImg,{
      headers: {
        "Content-Type": "text/plain; charset=UTF-8",
        //CORS対策
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Origin": "*"
      },
      //jsonではなく文字列で結果が欲しいので追記(なくても落ちはしないが余分なエラーメッセージ出る)
      'responseType': 'text'
    })
  }
}

Springで画像情報を受け取り、AWS Rekognitionに提供する

Angularからのhttpリクエストを受け取るSpringのコントローラーです。先ほどBase64形式になったdataの余分な部分「data:image/jpg;base64」を外し、デコードしデバイスのhomeディレクトリにpng形式で撮影画像を保存します。これで後はAWS Rekognitionにそのディレクトリを教えてあげれば基本的にはAWS docサンプルのAWS SDK固有の処理を流用で問題なく動きます。今回は笑顔ですが、face.smile().value()のsmileのところをBeardに変えるとあごひげ判定などもできたりと他にも色々できます。

ImgController.java
package suita.tarumi.SpringDetectFace.Controller;

import org.springframework.web.bind.annotation.*;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.rekognition.RekognitionClient;
import software.amazon.awssdk.services.rekognition.model.*;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;

@CrossOrigin(origins = "http://localhost:4200")
@RestController

public class ImgController {

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String transferImg(@RequestBody String base64CapturedImg) throws IOException {
        //Base64のデコードをする前にdataから「data:image/jpg;base64」を削除する必要があるためデータと分ける
        String[] base64CapturedImgForDecode = base64CapturedImg.split(",");
        //デコード・base64CapturedImgForDecode[1]はデータを指す、[0]は「data:image/jpg;base64」
        byte[] decodedCapturedImg = Base64.getDecoder().decode(base64CapturedImgForDecode[1].getBytes(StandardCharsets.UTF_8));

        //撮影画像の置き場をOSに依存しないように作成
        System.out.println("User homeは" + System.getProperty("user.home")+File.separator);
        Path destinationFile = Paths.get(System.getProperty("user.home")+File.separator, "detectedFace.png");

        //撮影画像をpngファイルとして作成
        Files.write(destinationFile, decodedCapturedImg);

        //ここからAWS Rekognition
        String sourceImage = destinationFile.toString();
        Region region = Region.AP_NORTHEAST_1;
        RekognitionClient rekClient = RekognitionClient.builder()
                .region(region)
                .build();

        String result = detectFaceImage(rekClient, sourceImage );
        rekClient.close();

        return result;

    }


    public static String detectFaceImage(RekognitionClient rekClient,String sourceImage ) {
        String result = "";

        try {
            InputStream sourceStream = new FileInputStream(new File(sourceImage));
            SdkBytes sourceBytes = SdkBytes.fromInputStream(sourceStream);

            Image souImage = Image.builder()
                    .bytes(sourceBytes)
                    .build();

            DetectFacesRequest facesRequest = DetectFacesRequest.builder()
                    .attributes(Attribute.ALL)
                    .image(souImage)
                    .build();

            DetectFacesResponse facesResponse = rekClient.detectFaces(facesRequest);
            List<FaceDetail> faceDetails = facesResponse.faceDetails();

            for (FaceDetail face : faceDetails) {
                System.out.println("笑顔判定 : "+ face.smile().value().toString());
                if(face.smile().value().toString() == "true"){
                    result = "いってらっしゃい!";
                } else {
                    result = "笑顔でもう一度!";
                }
            }

        } catch (RekognitionException | FileNotFoundException e) {
            System.out.println(e.getMessage());
            System.exit(1);
        } finally {
            return result;
        }
    }

}

感想など

ひとまず大まかなコーディングはこれで完了です。
機械学習の知見が全くなくとも顔認識が実装でき、とても感動しました。
画像関連の処理の復習もでき、いい題材を見つけたなとしみじみ思います。
もし読者の方で実装してみて上手くいかない・もしくはこういうのできますか?
などご意見いただければ非常にありがたいです。

今後の課題

・WEB上で動くようにする(S3?EC2?Elastic Bean Stalk?)
・デザインをましにする
・携帯アプリちっくにする(PWA)
・テストコード
挙げてみれば課題が山ほどありますね(笑)。

参考

AWS SDK For Java2.0 Rekognitionのサンプルコード
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/example_code/rekognition/src/main/java/com/example/rekognition

Rekognitionのモデル群
https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/rekognition/model/package-summary.html

0
0
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
0
0