フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

wasmでマルチバーコードスキャナを高速化した件

こんにちは。研究開発室の岡田です。(所属変わりました。)

前回は、TeamsやZoomで自分をアニメ絵にする方法をご紹介しました。

cloud.flect.co.jp

業務から少し離れていましたがキャッチーな内容なので結構評判が良かったみたいです。 今回は、FLECTの業務に関連する内容をご紹介したいと思います。

FLECTは、ユーザ体験の向上を重視したサービス、プロダクトの提案をさせていただいています。 その中で重要な考え方の一つとして、「特別なソフトウェアをインストールせずに利用できるサービスを提供する」があります。 具体的にはスマートフォンのブラウザ上で動くソフトウェアを開発し、提供することになります。

一方で、一般的に、ブラウザ上で動くソフトウェアはネイティブアプリと比較すると応答性能が劣化する、という問題があります。 応答性能の劣化は直接ユーザ体験にも影響しますので、場合によってはブラウザ上で動かすことによるメリットよりデメリットが勝ってしまうことも考えられます。 このような問題を回避する手段として、ブラウザ上で動くソフトウェアを高速化するWebAssembly(wasm)という技術*1を使うことがあります。

今回は、FLECTが開発しているスマートフォンのブラウザ上で動くマルチバーコードスキャナをwasmを用いて高速化した話をご紹介します。

結果、こんな感じで結構高速で動くようになりました。

f:id:Wok:20200501062054g:plain

*1:仕様と言われたり、言語と言われたりもします。ここが詳しい

続きを読む

GitHubでJacocoのカバレッジレポートを表示するまで(CircleCI+Codecov+gradle)

こんにちは。クラウドインテグレーション事業部の上原です。

研究開発系の先端的な内容が多いFLECTブログですが、
今回は開発の方面から、ちょっとしたTipsを共有してみようと思います。

対象アプリケーション

今回の記事で取り扱うのは、Spring Boot製のバックエンドAPIアプリケーションです。

CIツールにはCircleCIを採用し、GitHubへのpushをトリガーにテスト(JUnit)およびビルド・デプロイを自動実行しています。

circleci.com

「レビューのときにカバレッジが見たい」

CircleCIを導入するにあたり、とりあえず自動テストの実行と、テスト結果をGitHubのプルリクエスト画面に連携する所までを設定。
しかし、コードカバレッジについてはHTMLレポートを出力して保存するタスクを作っただけでした。

.circleci/config.yml

      - run:
          # カバレッジレポートの生成
          name: Generate coverage report
          command: ./gradlew jacocoTestReport
          when: always
      - run:
          # HTMLレポートを移動
          name: Save coverage report
          command: |
            mkdir -p ~/test-results/jacoco/
            find . -type f -regex ".*/build/reports/jacoco/test/.*xml" -exec cp {} ~/test-results/jacoco/ \;
            cp -r ./build/reports/jacoco/test/html ~/test-results/jacoco/html
          when: always
      - store_artifacts:
          # アーティファクトとして保存
          path: ~/test-results/jacoco


f:id:flect-uehara:20200420113416p:plain
実行結果画面のARTIFACTSタグから、レポートを見に行けます

最初はこれで問題なかったのですが、開発が進むにつれ、毎回CircleCIの画面に遷移してレポートを開いて該当部分のカバレッジを探して…というのが手間になってきました。

できればカバレッジもプルリクエスト画面で見えるようにしたいな…欲を言えば、修正分の差分が測定できたり、カバレッジが不十分だったらマージできないようにできたらいいな…
でもそんな都合の良いサービスなんて…………ありました。

CodecovというWebサービスです。

codecov.io

GitHub連携でプルリクエストにカバレッジレポートを表示可。差分測定に対応。UIやグラフも綺麗。いいですね!


f:id:flect-uehara:20200420112248p:plain

利用方法もとても簡単。

  1. Githubアカウントでユーザ登録
  2. Codecovの管理画面からリポジトリを選択GitHub組織の管理者がインテグレーションを許可する必要があります)
  3. アップロードトークンが払い出されるので、設定ファイル(codecov.yml)を作成してトークンを書き込む。(※ 環境変数でも可)
  4. GitHubにpushすると自動でCodecovにカバレッジ情報がアップロードされ、レポートが見えるようになる

あとはCircleCIとCodecovを連携して、自動テストのタイミングでカバレッジを収集するよう設定すればOK!
連携方法は公式のドキュメントとブログに記載されています。

circleci.comGenerating Code Coverage Metrics - CircleCI circleci.comMaking code coverage easy to see with the Codecov CircleCI orb - CircleCI






f:id:flect-uehara:20200420025325p:plain

英語やん…(2020年4月現在)



そう、CodeCovやCircleCIの一部ドキュメントは英語。いろいろ探したのですが、この件に関する日本語の記事は見つかりませんでした。
また、検索の腕が悪いのか「CircleCI+Codecov+Jacoco+gradle」のピンポイントな情報も見つからず…

ということで、英語と格闘して試行錯誤しながら何とか動かせるところまで持っていきました。というのがメインのお話です。

本題(設定ファイル)

結論から言うと、設定ファイルは以下のようになりました。
(注:重要なところだけ抜き出しているので、これだけだと動きません)

build.gradle

apply plugin: 'jacoco'

jacoco {
    toolVersion = '0.8.4'
}

jacocoTestReport {
    reports {
        xml.enabled = true
    }
}

.circleci/config.yaml

orbs:
  codecov: codecov/codecov@1.0.5

jobs:
  run-junit-test:
    steps:
      - (テストの実行などのstep)
      - run:
          # カバレッジレポートの生成
          name: Generate coverage report
          command: ./gradlew jacocoTestReport
          when: always
      - codecov/upload:
          # Orb
          file: ./build/reports/jacoco/test/jacocoTestReport.xml
          when: always

必要な設定は以下の通りです。

  • CircleCIの環境変数に「CODECOV_TOKEN」を追加し、値にアップロードトークンを設定しておく
  • build.gradleの設定で、JaCoCoがXMLレポートを出力するように設定する
  • CircleCIの設定ファイルで、CodeCovのOrb(CircleCIにおけるサードパーティライブラリ的なもの)を読み込ませる
  • CircleCIのstepでレポート出力を実行する
  • CircleCIのstepで、XMLファイルのパスを指定してOrbの「upload」コマンドを実行する

どのファイルをアップロードすればよいのか?認証方法の設定は?など色々ハマったところはあったのですが、まとめるとこんな感じです。
Slackへの通知についても色々調べたのですが、GitHubからの通知に差分等が出てくるようになったので、結局使っていません。

f:id:flect-uehara:20200420111549p:plain
GitHubからのSlack通知に表示されるようになりました

なお、合格とするカバレッジ閾値などは設定ファイルで細かく制御可能です。
細かい設定を追いきれていないので詳しくはCodeCovのドキュメントをご覧ください。

CodeCovのOrbのドキュメントはこちら。

https://circleci.com/orbs/registry/orb/codecov/codecov

おわりに

カバレッジをひと目で確認できるようになり、レビューが格段にやりやすくなりました。開発のスピードや品質を確保するには、仕組み作りが必要不可欠ですね。
CircleCIは機能がとても豊富なので、あとは設定ファイルの例がもっと増えてくれると嬉しいです… (あとOrbの説明ページにも設定ファイルの記述例を…どうか………)

ここからテストの並列実行に取り組んだ話などもあるのですが、それは別の記事でお話できればと思います。 少しでもお役に立てたなら幸いです。それでは!

Semantic Segmentation on AWS SageMaker

技術開発室の馮 志聖(マイク)です。

Introduction

I work in some project and it use Semantic Segmentation on AWS SageMaker.

At first we need to know about the popular machine learning method of image classification.

1.Image Classification

This method classify only one and the biggest target of images.

2.Object Detection

This method can find all the possible targets in the images.

f:id:fengchihsheng:20200406125132j:plain
image classification vs object detection

https://www.datacamp.com/community/tutorials/object-detection-guide

3.Semantic Segmentation

This method is upgrade version from image classification. It can detect the area of target.

4.Instance Segmentation

This method is upgrade version from object detection. It can detect the area of all targets in images.

f:id:fengchihsheng:20200403095856p:plain
Semantic Segmentation vs Instance Segmentation
image source : http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture11.pdf

Why we choose Semantic Segmentation not other method?

Because In this case we need to know about area of target.

Image classification only can classify the images.

Object detection have limitation.

When get the predict result from object detection.

Just only get 4 points of rectangle.

It can not get more detail of object area.

Like this image.

f:id:fengchihsheng:20200406122357j:plain
object detection

Instance Segmentation can identify for each target.

This project only have single class and output area of targets.

And not need to exceed.

So Semantic Segmentation will be better solution.

We only have single class just use Semantic Segmentation is enough.

In this project we only need Classification + Localization.

Task

In this case it have 200 images and resolution is 4K.

Issue

1.Image size is too large to use for training.
2.Detect area is a part of image.

f:id:fengchihsheng:20200406152519j:plain
example detect area

https://www.reporternewspapers.net/2019/08/30/sandy-springs-explores-options-for-street-connectivity-following-residents-concern/

3.Every images is get from video. For each frame distance is too close to cover same target.

For example image stitching have same target.

f:id:fengchihsheng:20200406151658j:plain
image stitching

4.Camera angle and distorted targets.

Like this images.

f:id:fengchihsheng:20200406155013p:plain
camera angle and distorted targets

Solution

Crop image base on 512*512.

Use label object detection way base on human eyes. Focus on special area and throw the empty images.

Split all images to train and validation folder.

Before remove the empty images.

Train images have more than 2000 images.

Validation images have more than 600 images.

After remove the empty images.

Train images have 676 images.

Validation images have 241 images.

Flow Chart

f:id:fengchihsheng:20200331121256p:plain
flow chart

Labeling

https://github.com/wkentaro/labelme

Use labelme to label the images.

f:id:fengchihsheng:20200331172157j:plain
label the data

And after labeling convert data to VOC-format Dataset.

It already have the script for convert.

https://github.com/wkentaro/labelme/tree/master/examples/semantic_segmentation

Prepare for Training

PNG file mode P

In AWS sagemaker only can use Mask file in PNG mode P.

I use python library to convert it.

https://pypi.org/project/Pillow/2.2.2/

Training

Create the new notebook from amazon sagemaker.

And use amazon sample notebook for semantic segmentation pascalvoc.

github.com

Follow the default folder structure.

f:id:fengchihsheng:20200331132032p:plain
structure

Upload dataset to notebook.

Instance type

Default Amazon SageMaker Notebook instances is ml.t2.medium and 5GB Volume Size.

5GB is not enough for training dataset.

In this case I change 5GB => 1024GB.

And Notebook instances is also slow when trying to prediction or do some other processing.

In this case I change ml.t2.medium => ml.t3.xlarge.

Default amazon sample notebook for semantic segmentation pascalvoc training instances is ml.p3.2xlarge.

When try to training it will have memory issue in this case.

So I change ml.p3.2xlarge => ml.p3.8xlarge.

Amazon SageMaker ML Instance Types :

https://aws.amazon.com/sagemaker/pricing/instance-types/

First Try

We can not use this project images because of NDA.

So I use the sample dataset present.

Use amazon sample notebook for semantic segmentation pascalvoc.

Algorithm : FCN

Backbone : resnet-50

Epoch : 10

Training time

Sample case

This is example training time.

FCN, 10 epochs, renet-50, crop size 240, use 1137 seconds (nearby 21 minutes).

Real case

This is the project training time.

PSP, 160 epochs, renet-50, crop size 512, use 5212 seconds (nearby 1 hour).

FCN, 160 epochs, renet-50, crop size 512, use 4680 seconds (nearby 1 hour).

Deeplab, 160 epochs, renet-50, crop size 512, use 7663 seconds (nearby 1 hour).

Prediction

This is one part after training.

import matplotlib.pyplot as plt
import PIL
from PIL import Image
import numpy as np
import io

im = PIL.Image.open(filename)

ss_predictor.content_type = 'image/jpeg'
ss_predictor.accept = 'image/png'

img = None
with open(str(file_list[i]), 'rb') as image:
    img = image.read()
    img = bytearray(img)
        
return_img = ss_predictor.predict(img)
 
##fix the class number when you use in training.
num_classes = 14
mask = np.array(Image.open(io.BytesIO(return_img)))
img = plt.imshow(mask, vmin=0, vmax=num_classes-1)
img.set_cmap('jet')
plt.axis('off')
plt.savefig(local_output_folder + '/' + basename + '.png', bbox_inches='tight')

After plt.savefig upload to AWS S3 and download to local machine do other process.

Fix the color and size to fit the test images.

Result :

f:id:fengchihsheng:20200331172246p:plain
prediction result

Analysis and Report

After Prediction I download the result and merge the mask with original test images.

And use IoU and FP for Analysis.

This is for one prediction result.

Color base on light

Green = correct mask

Red = prediction mask

f:id:fengchihsheng:20200331171925p:plain
prediction with correct result

Amazon SageMaker Semantic Segmentation Hyperparameters

All the Hyperparameters you can find in this URL.

https://docs.aws.amazon.com/sagemaker/latest/dg/segmentation-hyperparameters.html

Algorithm

Amazon SageMaker only support FCN, PSP, Deeplab.

Default Algorithm is FCN.

f:id:fengchihsheng:20200403103432p:plain
FCN Structure

image source :

http://cvlab.postech.ac.kr/research/deconvnet/

PSP :

f:id:fengchihsheng:20200403103801j:plain
PSPnet Structure

image source :

https://blog.negativemind.com/2019/03/19/semantic-segmentation-by-pyramid-scene-parsing-network/

https://arxiv.org/abs/1612.01105

Deeplab :

f:id:fengchihsheng:20200403124445p:plain
Deeplab Structure

image source : https://developers-jp.googleblog.com/2018/04/semantic-image-segmentation-with.html

Backbone

ResNet

What is ResNet?

ResNets solve is the famous known vanishing gradient.

Vanishing Gradient Problem occurs when we try to train a Neural Network model using Gradient based optimization techniques.

As more layers using certain activation functions are added to neural networks, the gradients of the loss function approaches zero, making the network hard to train.

f:id:fengchihsheng:20200406174334p:plain
Certain activation functions

source : https://isaacchanghau.github.io/img/deeplearning/activationfunction/sigmoid.png

Image is the sigmoid function and its derivative. Note how when the inputs of the sigmoid function becomes larger or smaller (when |x| becomes bigger), the derivative becomes close to zero.

If you want to know more detail please check these page and video.

Vanishing Gradient Problem Reference

https://towardsdatascience.com/the-vanishing-gradient-problem-69bf08b15484

https://medium.com/@anishsingh20/the-vanishing-gradient-problem-48ae7f501257

youtu.be

With ResNets, the gradients can flow directly through the skip connections backwards from later layers to initial filters.

If you want to know more detail you can check this page.

ResNet Reference

https://towardsdatascience.com/understanding-and-visualizing-resnets-442284831be8

Amazon SageMaker only support ResNet-50, ResNet-101.

Use ResNet will get short training time and higher accuracy.

Resnet Layer Structure :

f:id:fengchihsheng:20200403110132p:plain
ResNet Structure

image source :

https://neurohive.io/en/popular-networks/resnet/

And what is 50 and 101 mean?

It mean 50-layer and 101-layer.

This is error score table. (more smaller is better)

f:id:fengchihsheng:20200406180823p:plain
Error rates (%) of single-model results on the ImageNet validation set

image source :

https://neurohive.io/en/popular-networks/resnet/

Epoch

f:id:fengchihsheng:20200403120015p:plain
Epoch

image source :

https://www.st-hakky-blog.com/entry/2017/01/17/165137

Final

This is the chance let me learn about semantic segmentation on AWS sagemaker.

And use AWS sagemaker example is faster way to understand how it work.

The result from AWS sagemaker is good for this project.

Reference

labelme
labelme convert to VOC-format Dataset
AWS SageMaker

Build the map for corona virus

技術開発室の馮 志聖(マイク)です。

corona virus is terrible.

And we need to understand how terrible it is.

The most easy way is use the map and take a look how many person get sick.

Almost corona virus data is base on country.

Like this map :

https://google.com/covid19-map/?hl=en

Issue

For each Country have huge area.

It is not easy to handle distribution of details.

I think it have a lot of person want to know about degree of diffusion.

For example I live in Yokohama city.

Yokohama city in Kanagawa Prefecture and Kanagawa Prefecture in Japan.

In the map base on Country I only can get the info from Japan.

I have no idea in my City how degree of diffusion is.

It have few data base on City or Prefecture.

Solution

This is information for corona virus.

It have many website show the information and many data analysis.

https://github.com/pomber/covid19

I find an API can list all city ,GPS ,person count.

Let's try to build the map for corona virus base on city.

Use free and fast way to build it.

Structure

f:id:fengchihsheng:20200403202033p:plain
Structure

It is small project.

And not need any strong server.

So I choose Heroku free plan to be a server.

Map

It have two popular free resource map tools.

1.Google map

2.Mapbox

And I choose mapbox to be map.

mapbox is powerful and lighter for all device.

Why I choose mapbox not google map?

The good points of google map.

1.The best information.

Thanks to Google’s satellites, Street View vehicles, and user-generated corrections, Google’s geographical coverage is considered the best.

2.Multiple style options.

The JSON-like syntax used by Google Maps is immediately loaded along with a map. You can manage the visibility, color, and opacity of all map elements.

3.Street View.

Street View is a feature that provides interactive panoramas from different positions along lots of streets around the world. This feature can visualize Keyhole Markup Language (KML) and GeoRSS data on the map.

4.Extensive language support.

Google Maps supports many languages.

5.Information support.

You can count on a large community and multiple developers providing support.

The bad points of google map.

1.Browser limitations.

The Google Maps JavaScript API doesn’t support all web browsers.

2.Tricky pricing.

The Google Maps pricing model is not easy to sort out. And this is the biggest catch.

3.First call.

Autocomplete makes a call for all letters typed in the search bar.

4.Second call.

Another API call is made when a location is selected.

5.Third call.

Directions are added to the nearest location.

6.Usage limitations.

The free plan for Google Maps is limited to 10 queries per second.

The good points of Mapbox.

1.Unique customization options.

Mapbox is more customizable than Google Maps.

2.Open-source SDKs.

Mapbox Maps SDKs are open-source. Mapbox shares their code on GitHub so it can always be seen, analyzed, and improved.

3.Integration with PubNub.

Mapbox partners with PubNub, which offers infrastructure-as-a-service for live data streaming, builds dynamic map visualizations from real-time data, and incorporates functionality like asset tracking, geocoding, and heatmaps.

4.Mapbox AR.

The Mapbox Maps SDK for Unity allows for building location-based experiences using points of interest (POIs) all over the world. You can add locations using drag-and-drop maps and POIs, 3D buildings and terrain, place-based AR, and more.

5.Offline maps.

There’s no offline mode with the Google Maps API. More precisely, offline mode is available in the branded Google Maps app.

The bad points of Mapbox.

1.Relatively weak coverage.

There are many places where Google has better coverage than OSM based services.

Reference

In this blog have detail info about google map vs mapbox.

https://yalantis.com/blog/mapbox-maps-ready-mobile-apps/

Data API

Data API is come from trackcorona.

https://www.trackcorona.live/api

They already have map and data analysis.

But I want simple and customize.

Task

First I try to analysis the API response and find out the key and data format.

f:id:fengchihsheng:20200403203007p:plain
API

https://www.trackcorona.live/api

Second I try to read mapbox document and use example to customize.

I choose this example to be map UI.

https://docs.mapbox.com/mapbox-gl-js/example/cluster-html/

In this example circle only have one number.

But data have other data need to show it.

So I choose popup on click example to show the info.

https://docs.mapbox.com/mapbox-gl-js/example/popup-on-click/

Third when I use mapbox it need geojson format datasource.

I use this library to convert it.

GitHub - caseycesari/GeoJSON.js: Turn your geo data into GeoJSON. For Node.js and the browser.

Fourth I try to add chart in the popup but it not show all the area.

Then I use this example for fix this issue.

https://docs.mapbox.com/mapbox-gl-js/example/center-on-symbol/

Fifth use the most sample way to show the chart.

I use SVG and regist new element and create it.

Sixth it have update time need to compare.

I use moment.js to compare the UTC date and time.

https://momentjs.com/

Seventh I try to deploy it to Heroku.

I use the most sample php buildpack to build it.

https://devcenter.heroku.com/categories/php-support

At last when load the website on heroku website it will have issue.

Because of document.registerElement is not a function.

I use this library to solve the issue.

https://github.com/WebReflection/document-register-element

Final

I success build the corona virus map base on city.

This website is build by myself.

https://test-web-gyo.herokuapp.com/corona_virus/map.html

In this case I learning how to put the data on the map and show it.

mapbox have many API and many function can use.

And mapbox is light map for all device.

TeamsやZoomでカメラ画像を加工する方法 その3 アニメ風画像に変換するの巻

みなさんこんにちは。技術開発室の岡田です。

前回と前々回の投稿では、TeamsやZoomでカメラ画像を加工する方法をご紹介しました。これらの投稿では、笑顔や感情(表情)を検出してニコニコマークを表示するデモをご紹介しています。

cloud.flect.co.jp

今回、もう少し拡張して、画像をアニメ風に変換して表示する実験をしてみたので、ご紹介します。最初にネタバレしておくと、リアルタイムでアニメ風画像に変換するにはCPUだとちょっとラグが大きすぎて使いづらいかなと思います。(GPUだとマシになるのかは試してない。)

f:id:Wok:20200402051722p:plain

それでは早速ご紹介いたします。

アニメ風画像変換

半年ほど前にニュースメディアにも取り上げられていたようなので、ご存知の方も多いかと思いますが、写真をアニメ風に変換する手法が下記のページで公開されています。

github.com

このUGATITでは、単純なimage2imageのスタイル変換とは違い、GeneratorとDiscriminatorを用いるいわゆるGANの技術をベースに、独自のAdaLINという機能を追加することで形状の変化にも対応ができるようになったようです。

In our work, we propose an Adaptive Layer-Instance Normalization (AdaLIN) function to adaptively select a proper ratio between IN and LN. Through the AdaLIN, our attention-guided model can flexibly control the amount of change in shape and texture.

詳細は、本論文*1や解説記事*2を見ていただくとして、上記ページに公開されているトレーニング済みのモデルを使って、実際に変換してみるとこんな感じになります。

f:id:Wok:20200402042837p:plain

被写体が遠いとあまりうまく変換してくれないようです。また、おじさんはあまりうまく対応できていないみたいです。トレーニングで用いられたデータセットも上記ページで公開されていますが、若い女性に偏っているようなので、これが原因かと思われます。(私はまだおじさんではない、、、というのは無理があるか。)

実装の概要

上記のとおり、被写体(人物の顔)に近い画像(≒顔が画面の大部分を占める)にする必要がありそうです。今回は、前々回までにご紹介した顔検出機能により顔の場所を特定し、その場所を切り出してUGATITで変換をかけるという手順でやってみました。

f:id:Wok:20200402045508p:plain

実装の詳細は、下記で言及するリポジトリをご参照ください。*3

環境構築

前回までの記事を参考に、v4l2loopbackや、顔認識のモデルなどを準備しておいてください。

また、前回までと同様に、下記のリポジトリからスクリプトをcloneして、必要なモジュールをインストールしてください。

$ git clone https://github.com/dannadori/WebCamHooker.git
$ cd WebCamHooker/
$ pip3 install -r requirements.txt

UGATITのトレーニング済みモデルの配置

UGATITの公式ではTensorflow版とPyTorch版のソースコードが提供されていますが、トレーニング済みのモデルはTensorflow版しかないようです。これを取得して展開してください。なお、WindowsLinuxの通常のzip展開ツールだと展開に失敗するようです。Windowsを用いる場合は7zipだとうまく行くという報告がissueに上がっています。また、Macだと問題は発生しないようです。なお、Linuxは解決策は不明です・・・。*4

一応、正常に動くモデルのハッシュ値(md5sum)を記載しておきます。(多分ここが一番のつまずきポイントなので。)

$ find . -type f |xargs -I{} md5sum {}
43a47eb34ad056427457b1f8452e3f79  ./UGATIT.model-1000000.data-00000-of-00001
388e18fe2d6cedab8b1dbaefdddab4da  ./UGATIT.model-1000000.meta
a08353525ecf78c4b6b33b0b2ab2b75c  ./UGATIT.model-1000000.index
f8c38782b22e3c4c61d4937316cd3493  ./checkpoint

これらのファイルを上記git からcloneしたフォルダの、UGATIT/checkpointに格納します。このような感じになっていればOKです。

$ ls UGATIT/checkpoint/ -1
UGATIT.model-1000000.data-00000-of-00001
UGATIT.model-1000000.index
UGATIT.model-1000000.meta
checkpoint

ビデオ会議をしてみよう!

実行は次のように行います。オプションが一つ追加されてます。

  • input_video_num には実際のウェブカメラのデバイス番号を入れてください。/dev/video0なら末尾の0を入力します。
  • output_video_dev には仮想ウェブカメラデバイスのデバイスファイルを指定してください。
  • anime_mode はTrueにしてください。

なお、終了のさせ方はctrl+cでお願いします。

$ python3 webcamhooker.py --input_video_num 0 --output_video_dev /dev/video2 --anime_mode True

上のコマンドを実行するとffmpegが動き、仮想カメラデバイスに映像が配信されはじめます。

前回と同様に、ビデオ会議をするときにビデオデバイスの一覧にdummy〜〜というものが現れると思うのでそれを選択してください。 これはTeamsの例です。画面上右上にワイプで変換元の画像も表示しています。思ったよりちゃんとアニメ風に変換されて配信されますね。ただし、とても重く、ちょっと古めのPCだと1秒1コマとかそういうレベルです。*5 普通に運用するには厳しいかもしれません。いまのところは出落ち要員かな。いずれGPUでも試してみたいと思います。

f:id:Wok:20200402051909g:plain

最後に

在宅勤務が長引き、気軽なコミュニケーションがなかなか難しいかもしれませんが、こういった遊び心をビデオ会議に持ち込んで、会話を活性化させるのもいいのではないかと思っています。 もっといろいろできると思いますので、みなさんもいろいろ試してみてください。

*1:https://arxiv.org/abs/1907.10830

*2:【論文紹介】U-GAT-IT ざくっと理解するにはこのスライドが良さそう。

*3:2020/4/2現在、注ぎ足しつぎ足しで作っているので、ソースコードが汚い。どこかでリファクタリングします

*4:いずれも2020/4/2現在

*5:Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz, 32G RAM

TeamsやZoomでカメラ画像を加工する方法 その2 Tensorflowで感情分析の巻

みなさんこんにちは。技術開発室の岡田です。

前回はTeamsやZoomでカメラ画像を加工する方法をご紹介し、 笑顔を検出してニコニコマークを表示するデモをご紹介いたしました。

cloud.flect.co.jp

今回は、これを少し拡張して、AI(Tensorflow)でリアルタイムに感情分析することに挑戦しましたので、ご紹介いたします。 具体的には、次のように、画像に写った人物の表情から悲しみや怒りと言った感情を読み取り、それに合わせた画像を画面に表示します。これでビデオ会議で言葉を発しなくても感情を伝えることができそうですね。(いや待て、、)

f:id:Wok:20200401172359g:plain

前提

前回の記事を参考に、v4l2loopbackなどを設定しておいてください。

Webカメラのフックの拡張

今回は、カメラで取られた人物の感情を分析して、対応する画像をビデオストリーム上の映像に表示します。 感情分析にはTensorflowを用いますが、次のサイトでトレーニング済みのモデルがMITライセンスで提供されているので、これを利用させてもらいましょう。

github.com

まず、最初に前回と同様に下記のリポジトリから、スクリプトをcloneして、必要なモジュールをインストールしてください。

$ git clone https://github.com/dannadori/WebCamHooker.git
$ cd WebCamHooker/
$ pip3 install -r requirements.txt

次に、先程のサイトから感情分析用のトレーニング済みのモデルを取得します。 なお、今回は、適切な画像を表示するために、性別判断も同時に行おうと思います。

$ wget https://github.com/oarriaga/face_classification/raw/master/trained_models/emotion_models/fer2013_mini_XCEPTION.110-0.65.hdf5 -P models # 感情分析用のモデル
$ wget https://github.com/oarriaga/face_classification/raw/master/trained_models/gender_models/simple_CNN.81-0.96.hdf5 -P models/ # 性別判定用のモデル

また、画像を再びいらすとやさんからお借りしましょう。

$ wget https://4.bp.blogspot.com/-8DirG_alwXo/V5Xc1SMykvI/AAAAAAAA8u4/krI2n_SWimUBGEyMWCw5kZZ-HzoUKrY8ACLcB/s800/pose_sugoi_okoru_woman.png -P images/
$ wget https://4.bp.blogspot.com/-EBpxVigkCCY/V5Xc1CHSeEI/AAAAAAAA8u0/9XIAzDJaQNU3HIiXi4PCPK3aMip3aoGyACLcB/s800/pose_sugoi_okoru_man.png -P images/

$ wget https://4.bp.blogspot.com/-HJ0FUQz67AA/XAnvUxSRsLI/AAAAAAABQnM/3XzIWzvW6L80aGB-geaHvAQETlJTAwkYQCLcBGAs/s800/business_woman2_4_think.png -P images/
$ wget https://3.bp.blogspot.com/-S7iQQCOgfWY/XAnvQWwBGtI/AAAAAAABQmc/z7yIqGjIQr88Brc_QNdOGsrJRLvqY1hcQCLcBGAs/s800/business_man2_4_think.png -P images/

$ wget https://4.bp.blogspot.com/-PQQV4wfGlNI/XAnvQBMeneI/AAAAAAABQmU/lN7zIROor9oi3q-JZOBJiKKzfklzPE1hwCLcBGAs/s800/business_man2_2_shock.png] -P images/
$ wget https://3.bp.blogspot.com/-QcDbWqQ448I/XAnvUT4TMDI/AAAAAAABQnE/_H4XzC4E93AEU2Y7fHMDBjri1drdyuAPQCLcBGAs/s800/business_woman2_2_shock.png -P images/

$ wget https://3.bp.blogspot.com/-dSPRqYvIhNk/XAnvPdvjBFI/AAAAAAABQmM/izfRBSt1U5o7eYAjdGR8NtoP4Wa1_Zn8ACLcBGAs/s800/business_man1_4_laugh.png -P images/
$ wget https://1.bp.blogspot.com/-T6AOerbFQiE/XAnvTlQvobI/AAAAAAABQm8/TYVdIfxQ5tItWgUMl5Y0w8Og_AZAJgAewCLcBGAs/s800/business_woman1_4_laugh.png -P images/

$ wget https://4.bp.blogspot.com/-Kk_Mt1gDKXI/XAnvS6AjqyI/AAAAAAABQm4/LQteQO7TFTQ-KPahPcAqXYannEArMmYfgCLcBGAs/s800/business_woman1_3_cry.png -P images/
$ wget https://4.bp.blogspot.com/-3IPT6QIOtpk/XAnvPCPuThI/AAAAAAABQmI/pIea028SBzwhwqysO49pk4NAvoqms3zxgCLcBGAs/s800/business_man1_3_cry.png -P images/

$ wget https://3.bp.blogspot.com/-FrgNPMUG0TQ/XAnvUmb85VI/AAAAAAABQnI/Y06kkP278eADiqvXH5VC0uuNxq2nnr34ACLcBGAs/s800/business_woman2_3_surprise.png -P images/
$ wget https://2.bp.blogspot.com/-i7OL88NmOW8/XAnvQacGWuI/AAAAAAABQmY/LTzN4pcnSmYLke3OSPME4cUFRrLIrPsYACLcBGAs/s800/business_man2_3_surprise.png -P images/

$ cp images/lN7zIROor9oi3q-JZOBJiKKzfklzPE1hwCLcBGAs/s800/business_man2_2_shock.png]  images/lN7zIROor9oi3q-JZOBJiKKzfklzPE1hwCLcBGAs/s800/business_man2_2_shock.png

上記のうち、最後のコマンドは、ファイル名にゴミ(末尾のカギカッコ)がついているので取り除いているだけです。

実行は次のように行います。オプションが一つ追加されてます。

  • input_video_num には実際のウェブカメラのデバイス番号を入れてください。/dev/video0なら末尾の0を入力します。
  • output_video_dev には仮想ウェブカメラデバイスのデバイスファイルを指定してください。
  • emotion_mode はTrueにしてください。

なお、終了のさせ方はctrl+cでお願いします。

$ python3 webcamhooker.py --input_video_num 0 --output_video_dev /dev/video2 --emotion_mode True

上のコマンドを実行するとffmpegが動き、仮想カメラデバイスに映像が配信されはじめます。

ビデオ会議をしてみよう!

前回と同様に、ビデオ会議をするときにビデオデバイスの一覧にdummy〜〜というものが現れると思うのでそれを選択してください。 これはTeamsの例です。表情に合わせて画面上部の文字列が変化し、合わせて対応する画像が表示されますね。大成功です。

f:id:Wok:20200401172359g:plain

最後に

在宅勤務が長引き、気軽なコミュニケーションがなかなか難しいかもしれませんが、こういった遊び心をビデオ会議に持ち込んで、会話を活性化させるのもいいのではないかと思っています。 もっといろいろできると思いますので、みなさんもいろいろ試してみてください。

参考

Tensorflowによる感情分析については次のサイトを参考にさせていただきました。 (このサイトではtensorflowjsでの紹介をされております)

book.mynavi.jp

TeamsやZoomでカメラ画像を加工する方法

みなさんこんにちは。技術開発室の岡田です。

現在FLECTでは、東京都知事の要請を受け、新型コロナウイルス感染予防対策および拡散防止のため原則在宅勤務となっております。 同じような対応を取られている企業様も多く、様々な困難があるかと思いますが、ぜひ力を合わせてこの難局を乗り越えていきたいと考えています。

さて、原則在宅勤務が長引いてくると、日頃行われていた何気ない会話ができないなど、ストレスも溜まってくることも考えられます。 そんな状況で一つでもクスっと笑えて息抜きができる状況が作れればよいなという思いで、一つ小ネタをご紹介します。

内容は、マイクロソフトのTeamsやZoomなどのビデオ会議において、ウェブカメラをフックして加工して配信する方法です。 私がLinux使いのため、今回はLinuxでのご紹介となります。他のプラットフォームも何れ何処かで紹介されると思います。

なお、「一つでもクスっと笑えて息抜きができる状況」を作るのも時と場合を選びますので、そこは自己責任でお願いします(^_^)/。

f:id:Wok:20200331140931g:plain

前提

大抵のLinuxシステムで問題なく動くと思いますが、私が作業した環境はDebianのBusterです。

$ cat /etc/debian_version
10.3

また、python3が入っていないようでしたら、導入しておいてください。

$ python3 --version
Python 3.7.3

関連ソフトウェアのインストール

仮想ウェブカメラデバイス

今回はv4l2loopbackという仮想ウェブカメラデバイスを用います。 github.com

仮想ウェブカメラデバイスと、実際のウェブカメラを識別する必要があるので、まずは実際のウェブカメラのデバイスファイルを確認しておきます。 下記の例だと、video0とvideo1が実際のウェブカメラに割り当てられているようです。

$ ls /dev/video*
/dev/video0  /dev/video1

それでは、v4l2loopbackを導入しましょう。 まずはgit cloneしてmakeしてインストールしてください。

$ git clone https://github.com/umlaeute/v4l2loopback.git
$ cd v4l2loopback
$ make
$ sudo make install

次に、モジュールをロードします。このとき、特にchromeで認識させるためには、exclusive_caps=1をつけてあげる必要があるようです。https://github.com/umlaeute/v4l2loopback/issues/78

sudo modprobe v4l2loopback exclusive_caps=1

これでモジュールがロードされたと思いますので、デバイスファイルを確認しておきましょう。下記の例だとvideo2が追加されていますね。

$ ls /dev/video*
/dev/video0  /dev/video1  /dev/video2
ffmpeg

仮想ウェブカメラデバイスにデータを送り込むにはffmpegを用いるのが一番簡単です。 apt-getなどでさくっと導入しておいてください。

Webカメラのフックと映像の配信

今回は、笑顔を検出したら画像加工を施してみようと思います。 笑顔を検出したら、映像上に笑顔マークを表示します。

まず、次のリポジトリのファイルをcloneしてモジュールをインストールしてください。

$ git clone https://github.com/dannadori/WebCamHooker.git
$ cd WebCamHooker/
$ pip3 install -r requirements.txt

ここからcascadeファイルを入手します。cascadeファイルの詳細はopencvの公式でご確認ください。 https://github.com/opencv/opencv/tree/master/data/haarcascades

$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml -P models/
$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_smile.xml -P models/

笑顔マークをいらすとやさんからお借りしましょう。

$ wget https://4.bp.blogspot.com/-QeM2lPMumuo/UNQrby-TEPI/AAAAAAAAI7E/cZIpq3TTyas/s160/mark_face_laugh.png  -P images/

こんな感じのフォルダ構成になってるといいです。

$ ls -1
haarcascade_frontalface_default.xml
haarcascade_smile.xml
mark_face_laugh.png
webcamhooker.py

実行は次のように行います。 --input_video_num には実際のウェブカメラのデバイス番号を入れてください。/dev/video0なら末尾の0を入力します。 --output_video_dev には仮想ウェブカメラデバイスのデバイスファイルを指定してください。 なお、終了のさせ方はctrl+cでお願いします。

$ python3 webcamhooker.py --input_video_num 0 --output_video_dev /dev/video2

上のコマンドを実行するとffmpegが動き、仮想カメラデバイスに映像が配信されはじめます。

ビデオチャットをしてみよう!

ビデオチャットをするときにビデオデバイスの一覧にdummy〜〜というものが現れると思うのでそれを選択してください。 これはTeamsの例。左右がそれぞれの参加者の画面だと思ってください。 左側が今回の仮想カメラデバイスを使っているユーザです。右側が受信側です。 ニッコリすると笑顔マークが出ますね。大成功(^_^)/。

f:id:Wok:20200331140931g:plain

最後に

対面のコミュニケーションが難しい今、ビデオチャットを使ってもっと楽しめたらいいですね。 今回は笑顔を検出して画像を加工する例で示しましたが、opencvやその他のツールを使って工夫次第でいろんな加工ができると思います。 ぜひいろいろ試してみてください!

参考

opencvでの笑顔検出はこちらを参考にさせていただきました。

qiita.com

opencvでの画像貼り付けはこちらを参考にさせていただきました。

qiita.com