Briswell Tech Blog

ブリスウェルのテックブログです

DockerでnginxとAPIを動かす

どうも、こんにちは。としと申します。
いかがお過ごしでしょうか。

真夏のピークが去りましたね。
若者の全てが染みるこの頃です。(下書き期間が長すぎて、ちょっと今じゃない感は無視してください(´Д`;))

さて、今までElastic Beanstalk の記事を数本書かせていただきました。
その後、ローカルでDockerを動かすことが出てきたので、Dockerの設定と、どうせローカルで使うならまずはElasticBeanstalk on Docker を使ってみようじゃないか! と思い、色々調べながらやってみております。

(以下、Docker Desktop がインストールされている前提です。)
まずはDockerfile...

# ベースイメージを指定
FROM node:latest

# 作業ディレクトリ作成して設定します
WORKDIR /usr/share/nginx/html/

# 必要な環境変数をここに記載します
ENV JWT_SECRET=""
ENV JWT_EXPIRATION=""
ENV MYSQL_DATABASE=""
ENV MYSQL_READ_HOST=""
ENV MYSQL_READ_PASSWORD=""
ENV MYSQL_READ_PORT=""
ENV MYSQL_READ_USERNAME=""

# package.jsonをこぴります
COPY package*.json ./

RUN npm i

# アプリケーションのソースをバンドルします
COPY . .

# PORT
EXPOSE 8081

CMD ["node", "dst/server.js"]

とりあえずこれで

docker build -t userName/api .

↑build

docker run --name api -p 8081:8081 -d userName/api

↑これで起動

で動いてくれました。

docker ps

↑これで動いている一覧がみれます。

docker ps -a

↑ -a をつけると停止しているものもみえます。

docker stop api

↑一回止めましょう。

続いて docker-compose を使っていきます。 先ほどのDockerfileはアプリケーションのDockerfileなので、ファイル名をDockerfile-appに変更します。

新しくDockerfile-web を作ります。

# ベースイメージを指定
FROM nginx:latest

# default.conf 書き換え
COPY ./default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

default.conf

server {
    listen       80;
    server_name  localhost;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://api:8081/;
    }
}

続いて docker-compose.yml を作ります。

version: '3'
services:
  web:
    build:
      context: docker      # Dockerfile保存場所
      dockerfile: Dockerfile-web    # Dockerfileファイル名
    image: nginx      # docker image name
    container_name: nginx       # docker container name
    expose:
      - 80
    ports:
      - 80:80

  app:
    build:
      context: ./      # Dockerfile保存場所
      dockerfile: Dockerfile-app   # Dockerfileファイル名
    image: api                  # イメージ名
    container_name: api         # コンテナ名
    expose:
      - 8081
    ports:                          # ポート接続
      - 8081:8081
    volumes:                        # mount workdir
      - .:/usr/share/nginx/html/
    command: ["node", "dst/server.js"]

今回のフォルダ構成
PJ/Dockerfile-app
PJ/docker-compose.yml
PJ/docker/Dockerfile-web
PJ/docker/default.conf

その後

docker-compose up --build

↑を実行すると動いてくれます。

f:id:Toshi_bw:20200630122310p:plain

このような感じになれば成功です!

調べながらなので、中々時間がかかりました...

次回はAWS ECR にDocker imageをあげてみるとこら編を記載しようかなと思います。



「業務のアイカタであり続けたい」
中小企業様向けERPソリューション

ai-cata.com

Airtableを試していたらGoogleからTablesも発表された

kintoneの類似サービスのAirtableを少し試してみました。

Airtableとは

Airtableの特徴

  • 画面の操作感がExcelやSpreadSheetに近い
    • kintoneだと画面遷移が必要で静的なページが多いです。

f:id:usami-t:20201002141631g:plain
Airtable操作イメージ

  • ルックアップが即時反映

    • kintoneだとデフォルトの動作はルックアップの項目を更新しても、参照しているデータは更新されません。実現するにはプラグインなど必要です。
    • Airtableはデータベースで外部キー参照している感覚です。
    • また、1つのフィールドに複数の値を持つことが可能です。

      https://support.airtable.com/hc/article_attachments/360024030014/linked_records_2.gif

  • 日本語の情報が少ない

    • 日本語での情報量はkintoneの圧勝です。
  • 無料プランがある Pricing - Airtable

    • kintoneは基本的に有料です。
  • FormのURL共有

    • レコードを追加可能なフォームのURLが即時共有できます。
    • プランによってはパスワード制限も可能です。
  • 1つのアプリ内に複数テーブル保持

    • kintoneでは1テーブルごとにアプリと呼びます。Airtableはbaseと呼ばれるアプリの概念があり、その配下に複数テーブル持つことが可能です。
  • Airtableとkintoneの共通点

以下の機能はどちらのサービスでも対応してます。

Tables

Airtableを試しているうちにGoogleがベータ版を公開しました。(現在使用可能なのはアメリカのみ)

blog.google

Googleの紹介動画を観ると、Airtableと似た操作感なのではないかなと思います。

  • データサマリの通知機能が強そうです。

所感

弊社ではユーザ向けWeb画面と管理画面の両方を開発する案件が多いのですが、 下記のような案件があってもいいなと感じました。

  • バックエンドはkintoneまたはAirtableで構築し、管理画面扱いとする。
  • フロント画面はAPIでアクセスを行う。
  • その他SaaSなどの外部サービスとのデータ連携を行う。
  • 基本機能で出来ない部分だけ弊社で開発 など...

kintoneやAirtableにREST APIが用意されているというのは結構強みなのかなと思います。

サービス内の標準機能でどこまで出来るのかといった点がシステム発注側の方も詳しいと、 実装難易度、工数、費用など認識が共有しやすくなるんじゃないかなと感じます。

SaaS導入などお考えでしたら是非弊社へお問い合わせください!

CSVファイルからExcel開いて困った世にも奇妙な話

どうもおはこんばんにちは。
まだまだ駆け出し中の社員kobaです。
もう気付けば9月も終わってしまいますね・・・
年々時の流れの速さに困惑してしまいます ´д` ;

前回は7月にExcelファイルからPDFファイルの変換で右往左往した話を
ご紹介させていただきました。

tech.briswell.com

今回は第2弾ということで
CSVファイルからExcelファイルを開いたら困った世にも奇妙な話を
ご紹介したいと思います(※ご存知の方がいらっしゃったらすみません)

当社では数々のシステムを扱ってますので
システムデータをCSVファイルに落として
CSVファイルからExcelを開いて
CSV内容とシステムデータが一致しているか確認する作業を行っております。
今回はその作業で起こった現象が2つあるので備忘録の意味でも
書かせていただきたいと思います。
ちなみに私が使っているPCはMacです。

CSVからExcelに変換したファイルデータ文字化けした

CSVファイルからExcelファイルへ変換したらファイルデータの一部が文字化けしました

f:id:briswellyuki:20200926163939j:plain
変換したExcelファイル文字化けした例
当初なにかやらかしてしまったかと思いましたが、
調べてみると文字コードが対応していないのが原因でした。
文字コードは簡単に言ってしまうと、
文字の種類に番号を割り振ったもののことをいうみたいです。
コンピューターはテキストの文字をその番号で判断しており、
対応されていない番号のファイルは正しく変換されず、
上の写真のような文字化けの状態になってしまいます。

・文字化けになったときの解決方法

CSVファイルをテキストエディットで開いて複製→保存すると
下記写真のような画面になります。

f:id:briswellyuki:20200926162808j:plain
CSVファイルをテキストエディットで開いて複製→保存時の画面

標準テキストのエンコーディングの部分が文字コード変換の設定になります。
どうやら元のCSVファイルはUTF-8になっていたようです。

f:id:briswellyuki:20200926162811j:plain こちらをShift-JISにして保存すれば
f:id:briswellyuki:20200926164244j:plain 正しく変換できました〜
かなり初歩的ではありますが、
文字コードの変換を忘れてCSVExcelに変換することは多い気がします。

1つのセルに複数の数値があるCSVを変換したら

1つのセルに複数の数値がある項目のCSVExcelに変換した場合、
Excelが勝手に1つの数値に変換してしまうことがありました。

f:id:briswellyuki:20200926171251j:plain
1つの数値に変換されてしまう例

別プロジェクトで複数の数値がある項目のCSVは正しく変換されている・・・
比べてみると最初以降の数値の前に半角スペースが入っているみたいでした。

f:id:briswellyuki:20200926174239j:plain
テキストエディターツールmiで開いた通常のCSV
半角スペース入れて変換してみたら
f:id:briswellyuki:20200926174010j:plain
テキストエディターツールmiで開いた半角スペース入力したCSV
f:id:briswellyuki:20200926174017j:plain
半角スペース入れたCSVを変換したExcel
正しく複数の値が1つのセルに表示されるようになりました〜
内容が薄いですが、なにか少しでも上記の情報がお役に立てたら幸いです。



「業務のアイカタであり続けたい」
中小企業様向けERPソリューション

ai-cata.com

江戸屋敷がすぐそばに

f:id:KenjiU:20200927203521j:plain
Kazutripさんによる写真ACからの写真

夜な夜な江戸の古地図を眺めてタイムスリップを楽しんでおります。

現代の地図と見比べながら、当時あったが今はないもの、今もまだあるものと、違いを見つけながら歴史を紐解いていくと、とても楽しいです。

さて、弊社株式会社ブリスウェルですが、2019年2月に「渋谷区広尾1丁目」→「港区芝大門1丁目」に移転しました。

https://www.edomap.jp/
こちらのいつもお世話になっております「大江戸今昔めぐり」アプリで、それぞれの場所の地図を眺めてみましょう。

f:id:KenjiU:20200927203958p:plain
移転前:渋谷区広尾1丁目

f:id:KenjiU:20200927204031p:plain
移転後:港区芝大門1丁目

なんと
移転前の広尾(恵比寿)オフィスは、赤穂藩森家の下屋敷が目の前にあり、
移転後の大門オフィスは、赤穂藩森家の上屋敷が目の前にありました。
オフィスの窓から見ていた外の風景に、お屋敷があったことと、それも同じ藩主家の屋敷だったことには驚きです。両方の場所は、現在、平地で区画もきれいに四方に仕切られており、当時大きな建物があったような雰囲気はあります。

ちなみに
大門の地図の①には「赤穂藩森家上屋敷跡出土の石垣石」の遺跡があります。

f:id:KenjiU:20200927204605j:plain
赤穂藩森家上屋敷跡出土の石垣石

大門の地図の②には「芝神明町町屋敷跡」の遺跡があります。

f:id:KenjiU:20200927204654j:plain
神明町町屋敷跡

江戸時代の暮らしの息吹を感じますね!

と、ここで江戸ブログではなくテックブログなので一つAI技術をご紹介いたします。

弊社の大門オフィスから徒歩18分ほどの場所にある愛宕山。江戸市中において最も高い山(標高26メートル)で、江戸湾まで一望できた観光名所でした。以下の写真はその愛宕山から撮影した江戸の町です。

f:id:KenjiU:20200927204915j:plain
引用:愛宕山から見た江戸の町 : 江戸時代(幕末) | https://pin.it/5yfx90Z

この白黒写真をディープラーニングを使って色付けしてみます。

f:id:KenjiU:20200927205032j:plain
愛宕山から見た江戸の町

江戸時代がぐっと身近に感じられますね!
弊社オフィスの前にもこのような屋敷が連なっていたのでしょう。
では、拙者はこれにて失礼致す、御免。

About the AWS Auto Scaling

Hello, everyone.

It's Shun.

 

今回は「AWS Auto Scaling(オートスケーリング)」についての概念をまとめてみました。

「こういったことができるだ、へー、便利だね」くらいに感じていただけると、幸いです。

 

Auto Scalingのユースケース

全体的に見ると必要なリソース量は少ないが、瞬間的にリソースが必要になる場合があり、一番リソース量が増える時のリソース量にサーバーのスペックを合わせているオンプレミス環境構成で運用をしている場合。

 こういったケースに、Auto Scalingを使用すると、コストを最適化することができます。

以下、Auto Scalingあり/なしの場合のイメージを図で示してみました

Auto Scalingあり/なし比較

Auto Scalingなし

f:id:artistyuiguitarelegance:20200923165940p:plain

オートスケーリングなし

実際には使用していない部分(上図ピンク塗り箇所)が使用料の2倍以上あるため、必要なリソース量に対してマシンのスペックが見合っていない。

Shun「なんで、実際にはサーバーを使っていない時間帯が多いのに、こんなに使用料を払わなきゃいけないんだよ・・・はぁ、萎える。」みたいな状態です。

コスト最適化の面で改善の余地がかなりあります。

Auto Scalingあり 

f:id:artistyuiguitarelegance:20200923170033p:plain

オートスケーリングあり

実際には使用していない部分がないため、必要なリソース量に対してマシンのスペックが見合っている。

Shun「今月はこんだけサーバーを動かしたんだ。それにしてもリソースの使用料は変わらないのに、Auto Scalingしていない頃と比べてこんなに費用を削減できるんだね、すごい・・・じゃあ、浮いたお金で美味しいもの食べにでも行きますかね^-^」みたいな状態です。

コスト最適化がされています。

 

Auto Scalingのトリーガー

 Auto Scalingありの図中の吹き出しでご説明いたしました、この部分ですが、

必要なリソース量が増えれば、そのリソース量に応じてマシンの性能を拡張し、必要なリソース量が減ると、そのリソース量に応じてマシンの性能を縮小する

どういった条件の場合((例)CPU使用率が80%を超えたら)にマシンの性能を拡張し、どういった条件の場合((例)CPU使用率が70%を割ったら)にマシンの性能を縮小するといったようなことを設定できます。

 →Amazon Cloud Watchと組み合わせて使用します(Cloud Watchはざっくりご説明すると、マシンの使用量などを図で視覚的に見ることができるものとでも覚えておけば、まずはよろしいのではないかと思います)

 

条件の設定値はマネージメントコンソール上からいつでも簡単に変更することができますので、運用していく中でマシンの設定値をチューニングしていくのがいいと思います。

 

最後に

以上、「Amazon Auto Scaling」の概念をかいつまんでご説明させていただきました。

コスト最適化については、環境構成を変更したり、マシンのスペックを下げたりとその他にも色々考えられることはあると思いますが、今回ご紹介させていただきました「Amazon Auto Scaling」は特に、コスト最適化の面で貴人の大きな助け舟になると思います。

必要な分だけ使って、使った分だけ使用料を払いたいですね。

 

それでは、今回はこの辺で。

Thank you so much, see you next time✋

 

 

ローカルPC上の開発中のネットワークサービスを外部公開できるサービスngrok

はじめまして、私はPhiと申します。
システム開発業務に携わってます。

最近は外部サービスと連携するためwebhookを開発しています。
webhookなので、オンラインURLがないとテストできないです。
毎回テストするため、elasticsbeanstalkへデプロイするのは結構面倒 + 時間かかります。
上記の解決策を探していたら、ngrokを見つけました。

NGROKとは?

ngrokとは「セキュアトンネル経由、NATおよびファイアウォールの背後にあるローカルサーバーをパブリックインターネットに公開」というサービス。 f:id:phint:20200831225715p:plain

利点は?

  1. webhook/chat bot 開発する時にとても便利
  2. モバイルアプリもしくはSPAのバックエンドサーバをdebugできる
  3. リモートでお客さんにウェブサイトのデモを紹介できる
  4. ローカルサーバを別の環境(スマホwindows/linux/macos)でテストできる

使い方

ngrokでアカウントを登録して、アプリをダウンロードしたら使えます。

  1. アカウント登録:
    このサービスは無料で使えますが、有料プランもあります。開発のみの場合は無料を使っても全然問題ないと思います。
    ここで登録してください。
    登録さた後、ダッシュボードへ遷移されます。
    ここで認証ためのコマンドを見えます。
    例: ./ngrok authtoken xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    アプリダウンロードした後、例のコマンド叩いたら、ログインできます。

  2. アプリダウンロード:
    ダウンロードリンクです。
    私はmacOS使っていますが、windowsも大体同じです。
    ※下記画像はmacの画像になります

まずはダウンロードファイルを解凍します。そのあとは terminal を起動して、解凍先のフォルダーへ移ります。(私はApplications フォルダーに解凍しましたから、Applicationsへ移ります)
f:id:phint:20200901123155p:plain ここで、上記の認証コマンドを実施します。 f:id:phint:20200901123711p:plain ここまでは準備のステップは終わりました。ngrok使いしょう!
./ngrok http <port> この簡単なコマンドでローカルサーバがパブリックインターネットに公開されます。私のローカルサーバは port 3333 で動いてますから、 ./ngrok http 3333 実施します。これは結果です。 f:id:phint:20200901125700p:plain httpsのリンクもあります、便利ですね。無料プランですから、毎回コマンド実施したらランダムURL返却されます。
ngrokのダッシュボードページでURLも見えます。 f:id:phint:20200901130104p:plain そして、コマンド実施結果の Web Interface http:127.0.0.1:4040 をアクセスすればリクエスト詳細を検査できます。 f:id:phint:20200901130359p:plain

他の機能も色々ありますが、今回の記事はここまでになります。皆様ngrokを試して楽しんでみてください!

PHPのメモリについて(Part2)

どうもこんにちは。BriswellのTuanと申します。
今日また、PHPのメモリについて続きたいと思います。
前回の内容を参考したい方は下記のリンクを参考してください。

PHPのメモリについて(Part1) - Briswell Tech Blog

PHPは自動的にメモリ管理できると言うことを分かりましたが、何を管理しているのでしょうか?

まず、値代入参照代入を簡単に説明します。
PHPには基本的にオブジェクト以外各変数は値代入です。
例えば下記のコード確認しましょう:

<?php 
$a = 1; 
$b = $a;    
$a++;    
var_dump($a, $b);  
    
$x = (object)['value' => 3]; 
$y = $x;    
$x->value = 10;  
var_dump($x); 
var_dump($y);

実行結果

int(2)

int(1)

object(stdClass)#1 (1) { ["value"]=> int(10) }

object(stdClass)#1 (1) { ["value"]=> int(10) }

$a, $bの値は簡単にわかるでしょうか!
しかし、$x$yはどう思ういますか? $x, $yはオブジェクトですから値代入ではなく、参照代入ので、
個別のオブジェクトですが、実際は同じメモリ位置に参照しますので、$xを更新すると、$yにも反映されます。

関数の引数もデフォルトは値渡しです。

<?php 
function fnByVal($v) { 
        $v = "test";  
}   

// 参照渡しを指定
function fnByRef(&$v) 
{   
        $v = "test";  
}   
$y = 'Briswell';    
fnByVal($y); var_dump($y); 
fnByRef($y); var_dump($y); 

実行結果

string(8) "Briswell"
string(4) "test"

上記のコードを実行して、fnByValを呼んだ後に$yの値はそのまま「Briswell」でしょうか! でもfnByRefの場合、$yの値更新されました。

ちょっと面白いと思いますが、下記のコードを実行したら、結果は想定と同じでしょうか!自分で試して、是非コメントで説明してください。

<?php 
function fnByVal_($obj) {  
        $obj->value = "test";  
}   
$x = (object)['value' => 1]; 
fnByVal_($x); var_dump($x);    

PHPは必要であれば、自動的にメモリをアロケート又は解放します。
ただし、「必要であれば」はいつでしょうか? これから、色々を試しながら確認しましょう。

※注意:以降の例は基本的に検証の想定通りですが、PHPバーションによって、メモリ管理方違う部分があるので結果違います。ご注意してください。

例1:

<?php 
    $mem = memory_get_usage();    
    $a = str_repeat("1", 1000); // ①       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    $b = $a;                    // ②
    $c = $b;                    // ③ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    $a = $a . '1';               // ④ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
        
    unset($b);                   // ⑤ 
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    unset($c);                   // ⑥ 
        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 

実行結果

used mem: 1280
used mem: 1312
used mem: 2592
used mem: 2592
used mem: 1312

ソース見るだけ分かりずらいと思いますが、下図を見てください。

f:id:tuanda:20200831183105p:plain

f:id:tuanda:20200831183143p:plain

配列も同じ管理方です。
例2:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, '1'); 
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0] = '2';   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36920
used mem: 36952
used mem: 73872
1001
1000
1000
used mem: 73872
used mem: 73872
used mem: 36952

例3:

<?php 
$mem = memory_get_usage();    
$a = array_fill(0, 1000, (object) array('x' => '1'));  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$b = $a;    
$c = $b;    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[0]->x = '2';    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
$a[] = '1'; 
echo count($a)."\n";  
echo count($b)."\n";  
echo count($c)."\n";  
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
    
>unset($b);   
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
unset($c);   
    
>echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";   

実行結果

used mem: 36960
used mem: 36992
used mem: 74288
1001
1000
1000
used mem: 74288
used mem: 74288
used mem: 37368

試した結果上で、PHPには同じメモリエリアに複数変数が参照できますが、
それぞれの変数がいずれか更新したい場合は別のメモリエリアをアロケートします。
これは大切だと思います。

*データベースから数万件のデータ抽出する時に、注意しないと、「Fatal error: Out of memory」発生可能性が高いです。

例えばデータ処理はほとんどForeachというループ命令を使ってますが、下記の2つバーションのForeach確認しましょう。

一般的バーション

<?php     
$mem = memory_get_usage();        
$a = [  array_fill(0, 1000, '1'),      
        array_fill(0, 1000, '2'),     
        array_fill(0, 1000, '3'),     
        array_fill(0, 1000, '4')];        
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
foreach ( $a as $key => $item) {        
     $a[$key][0] = '9';       
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n";     
}       

実行結果

used mem: 148056
used mem: 185384
used mem: 222304
used mem: 259224
used mem: 296144

参照バーション

<?php 
$mem = memory_get_usage();    
$a = [  array_fill(0, 1000, '1'),  
        array_fill(0, 1000, '2'), 
        array_fill(0, 1000, '3'), 
        array_fill(0, 1000, '4')];    
echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
foreach ( $a as <b><span style="color: #0000cc">&</span></b>$item) { 
    $item[0] = '9';        
    echo ">> used mem: ". (memory_get_usage() - $mem) ."\n"; 
}   

実行結果

used mem: 148056
used mem: 148152
used mem: 148184
used mem: 148216
used mem: 148248

結果見ると、どちら効率かすぐ分かりますね。でも、一般的皆あまり参照のバーション使ってないと思います。

PHPは自動的にメモリを解放できますが、必要であれば、自分達「unset」で解放できます。
PHPソースには配列を多分一番よく使うデータ型ですが、参照代入ではなくて、値代入ので、ご注意してください。
意外の増やすメモリのケースが多いと思います。

ではPHPのメモリについてここまで終わります。
みなさん是非試して確認して、実際のプロジェクトに適用すれば、良かっただと思います。

動画の人物をホネホネ化

今回のAIブログは、骨格検出(通称:ホネホネ化)についてご紹介いたします。
骨格検出とは、動画または写真の中から人物の骨格を検出する技術となります。
サクッとどのようなものなのか、見ていきましょう。

【下北ラヴァーズ】スマートスピーカー

こちらの弊社Uri&Yuki漫才コンビ「下北ラヴァーズ」のダンス動画について骨格検出をしてみます。

微妙にシンクロしていないですね...(いや微妙というか全然かも!?)
骨格検出を利用すれば、実際にどのくらいシンクロしていないかを数値で定量的に評価することもできます。

骨格検出には「tf-pose-estimation」というモデルを使用します。
これは以下の「OpenPose」という骨格検出アルゴリズムを「TensorFlow」用に移植したものとなります。

github.com

では、早速ですが検出結果を見ていきましょう!

youtu.be

ほぼ完璧にホネホネ化できていますね。素晴らしいです。
骨格の位置を可視化するだけでなく、骨格の各ポイントについてXY座標で出力することもできます。

例えば、右腕の座標位置の推移を見てみると

f:id:KenjiU:20200901185451p:plain
Uri(立ち位置左)の右腕の座標位置推移

f:id:KenjiU:20200901215246p:plain
Yuki(立ち位置右)の右腕の座標位置推移

f:id:KenjiU:20200901185550p:plain
UriYukiの差分

X座標の差分が徐々に大きくなってきてますね...
このように「微妙にシンクロしていない」というのを数値で評価することができるようになります。面白いですね!

次は具体的にシンクロ度「何%」と出せる仕組みも作っていきたいなと思っております。

Briswell AI Team

20代に読んでほしい書籍

こんにちは加藤です。 8月はオリンピック・パラリンピックのないまま今日で終わり、明日から9月になります。 2020年も残り4ヶ月、123日しかないです。

f:id:brix:20200831212406j:plain Pic by Skeeze at Pixabay

ブログネタに困っていたところ、社員がお題をくれたので乗りたいと思います。

・20代に読んで欲しい書籍

これ読んどきなさい的なやつを、経営者目線で書いて欲しいです。 社員のだれかが読んで、アンサー記事を書くところまでストーリー化したいです。

20代に読んでほしい書籍を紹介するなどと、おこがましいなと思いながらも、 ブリスウェルは平均年齢も若いので、初老の僕はそういう役割なのでしょう、素直に書きます。

そもそも僕の20代の頃はまだKindleがなく、紙の本を書店で買う時代〜ネットで買う時代の過渡期だったと思います。

以前勤務していた会社では、週次サーキュレーション(社内配送サービス)があったので、

Amazonから会社に送って転送してもらい、出張先でうまく受け取るといった、おばあちゃんの知恵のようなライフハックがあったものです。

今回は20代のころの本の読み方と、今の読み方をmixしながら紹介したいと思います。

ーーーーーーーーーーーー

20代に読んでほしい書籍

20代のころはPJTに入る際には、関連する領域の本を10〜20冊程度まとめてざっと読むということをやっていました。

大きめの書店、当時の八重洲ブックセンターや、渋谷ブックファーストなどへ行って、お目当ての領域の目についた本を手当り次第、持てるだけ買います。

多くのビジネスマンの情報収集法にこの手法が出てきますので、僕も誰かに勧められたのかもしれません。

ただこの読み方はおそらく名前がついていません。

「スタメン20」などと呼びたいところですが、尾原和啓さんの「本のメートル買い」が一番適切かと思います。 logmi.jp

① ウォームアップ

短期間でビジネスパーソンとしてのいろはを身につけるための、入門編の定番たちです。

・入社1年目の教科書 岩瀬 大輔 (著)

何度か社内で新入社員に配った気がします。

就業経験・起業経験のない新人向けに心構えを説く本としては最高の1冊、これだけで十分だと思います。

・経済ってそういうことだったのか会議 佐藤 雅彦 (著), 竹中 平蔵 (著)

広告・メディア界と経済・アカデミア界のスーパースター同士の対談で、 マクロ経済・ミクロ経済の基本的な考え方を、柔らかい文章で書いてあったと記憶しています。

・コンサル一年目が学ぶこと 大石哲之

最近斜め読みしたのですが、平易な文章で若手に向けたハウツー本で、受け入れやすかったと思います。

MBAより簡単で英語より大切な決算を読む習慣 シバタ ナオキ (著)

MBAも英語も重要だと思いますが、決算を読めるとあるいは読む習慣があると強いでしょうね。

・図解入門ビジネス シリーズ

未だにですが、就職活動大学生向け・初心者向けのイメージのあるこのタイプの書籍も大好きです。

このシリーズと類似シリーズで計20-30冊は買ったのではないかと思います。

結局は、業界・企業に詳しくなればなるほど、こういった入門書に書いてあることが必ずしも正しくない、新しくないことがわかるのですが、 初心者が数時間で概要を掴むにはうってつけです。

ユースケースとしては、移動や出張の際にぷらっと書店に寄り、本格派に加えてこういった入門書を書い、まず入門書で肩慣らしするというのがよくあるパターンでした。



② 考え方の基礎

考え方を考える、見せ方を考えるなどと思考自体についての書籍達です。

・企業参謀 戦略的思考とは何か 大前 研一 (著)

今となっては経営学(経営工学)がデータドリブンとなって、これが書かれたときとは意思決定の依拠となるデータ・ファクトの厚みが全く違うのですが、 考え方の教科書としては未だに名著と言えると思います。

何度か紙で買った気がしますが、今はKindleで廉価版が出ていて良いですね。

・意思決定のための「分析の技術」 後 正武 (著)

こちらもかなり時代を感じる内容ですが、考え方の基礎として良い教科書です。

今はビッグデータをツールに打ち込めばあとはソフトウェアが分析してくれるというのが早いのでしょうが、その背景を理解しておくことが重要かと思います。

・考える技術・書く技術―問題解決力を伸ばすピラミッド原則 バーバラ ミント (著)

こちらも定番のハズですがKindle版がありません。人気ないのでしょうか。

「君の話はわかりづらい」などと言われる若手は是非読んで体得すべきかと思います。 うちの20代の皆さん、敢えて一冊だけといえば、これです。これをまず読んでください。

③ 業界のいろは

インターネット、ソフトウェア開発、エンタプライズ、DXなどと、インダストリー(業界)カット・業務領域カットなどでフォーカスを絞って集中して読むのが良いと思っています。

※この「インダストリーカット・業務領域カット」は、コンサルファームやエンタプライズSIでは一般的なのですが弊社のような若い会社にはあまり浸透していないので、別の機会に書きたいと思います。

・インターネット的 糸井重里 (著)

2001年時点でインターネットを「リンク」「フラット」「シェア」と特徴づける糸井さんの慧眼に、やられます。

・【全15巻合本版】角川インターネット講座 村井 純 他 (著)

村井先生に始まりJoi Itoに終わる壮大なSagaです。

・令和2年版 情報通信白書 総務省 (著)

敢えて読まなくても良いのですが、最新情報があふれるなか少し立ち止まって、ストックとなっている公知の情報を眺めて見るというのも良いものです。

自分たちが思っているより、テクノロジー自体はもっと先に行っている一方、その社会実装は全然進んでいません。

パラノイアだけが生き残る アンドリュー・S・グローブ (著)

僕の20代の頃はWinTelが兎に角強くて、ペイジとブリンが出てくるまでは、ビル・ゲイツアンディ・グローブがヒーローでした。

最近、新装で再発されたので新しいバージョンが良いと思います。

トヨタ生産方式 大野 耐一 (著)

最後は少し毛色が違います。 20台の頃、以前の会社で僕は通信業界の部署にいたので、製造業に深い造詣があるわけではないですが、最近Kindleで見つけたので紹介です。

製造業の生産管理、在庫・BOM管理、原価管理の基礎があると、エンタプライズ領域なら他業界でもなんとかなります。

また業界の大著は抑えておくと、クライアントと最低限のプロトコルがあいます。

ーーーーーーーーーーーー

なお、今回紹介したのは仕事の為のインプットという観点での書籍です。

つまりはPJT開始時に情報のシャワーを浴びるときの書籍たちなので、複数冊を並行して辞書のように使うのが通常です。

Kindle版へのリンクで紹介しましたが、上記の用途を考慮すると紙の本の方が使い勝手が良いかもしれません。



・以下ブリスウェルの今月の新製品のご紹介:

日々のExcelや紙の業務をクラウドで一元管理して効率化したいというご要望に答えて、販売管理/ERP領域のSaaSをリリースしました。 ぜひお問い合わせの上、触ってみてください。

〜 業務のアイカタであり続けたい 中小企業様向け クラウドERPソリューション 『アイカタ(ai-cata)』〜 bit.ly

f:id:brix:20201106174254j:plain
低コストERP導入パッケージ「アイカタ」

Postmanで配列とファイルをPOSTする話

連日の猛暑が続くなか、自宅のPC部屋にクーラーがなく、リビングで運転しているエアコンの風をサーキュレーターと扇風機を駆使しながらリモートワークしているid:rosoneです。

熱中症対策をしながら、ギリギリ無理のラインで頑張ってます。

はじめに

APIサーバのテストでPostmanを使用しているのですが、文字列・配列・バイナリファイルをセットしてPOSTするリクエストをうまく作れず、ハマりました。

振り返ってみると別に難しいことはないのですが、どのようにセットすればよいかを紹介します。

前提

サーバー構成

f:id:rosone:20200820184848p:plain
サーバー構成

  • サーバー構成は上記の図を参照
  • 今回はAPIサーバに対するテストをPostmanで実施

画面

f:id:rosone:20200821113517p:plain
画面イメージ

  • 姓名・セイメイ:文字列
  • 好きな食べ物:文字列
    • [追加する]ボタン押下で、入力フォームが増える(配列で送信)
  • プロフィール画像:画像データ
  • [登録する]:ボタン押下でareKoreCreateAPIを実行
  • バリデーションは無し

API

f:id:rosone:20200820185447p:plain
API仕様

  • Content-Typeはapplication/json
  • URI Parametersの情報をDBに登録
  • バリデーションは無し

Postmanのリクエス

姓名・セイメイ

f:id:rosone:20200820192226p:plain
リクエスト:姓名・セイメイ

form-dataを選んでそれぞれのKEY/VALUEにセットするだけなので、とてもシンプル。

好きな食べ物

form-dataどうやって配列を指定するのかよくわからない...。

ちなみに僕が好きな食べ物はハンバーグです...。

よくわからない①

f:id:rosone:20200821105308p:plain
NG①
f:id:rosone:20200821111020p:plain
NG①-②
VALUEを配列っぽくセットしてみるが、NG。

SUCCESS①

ぐぐってみたところ、jsonをそのままセットすればOKとのこと。

f:id:rosone:20200820193345p:plain
SUCCESS①
rawにJSONを書いてあげればうまく行った。

プロフィール画像

よくわからない②

f:id:rosone:20200821105702p:plain
NG②
好きな食べ物の配列を送るためにraw(JSON)でリクエストを作ったが、バイナリファイルをこのJSONにセットするやり方がわからない...。

SUCCESS②

一旦好きな食べ物のことは忘れて、そもそもバイナリファイルどうやってリクエストにセットするのかをぐぐってみると、form-dataでKEYの形式をtextからFileに変更すると、ファイル選択ボタンが出現するらしい。

f:id:rosone:20200820195105p:plain
SUCCESS②

無事にsibusawa-jidori.jpgをセットできた。

全てのパラメータをセット

さて、ここからがブログタイトルの通り、本題となります。

よくわからない③

配列はrawにJSONを書けばよいが、そうするとraw(JSON)で画像をセット出来ない。

f:id:rosone:20200821105702p:plain
NG②

画像はform-dataでKEYをFileに変えればセットできるが、そうすると配列の表現方法がわからない。

f:id:rosone:20200821105716p:plain
NG③

ハマりました。もうわからない。

Sending an array as form-data - Help - Postman

最終的にこの問題を解決してくれたのはPostmanのフォーラムに記載してあった上記ページの一文、

  • タイトル:Sending an array as form-data
  • コメント:use key[]: value

でした。

既にform-dataでファイルをセットするリクエストは SUCCESS② で成功しているので、あとはそのform-dataに上記の配列を追加してあげれば解決、ということになります。

SUCCESS③

実際にセットするとこんな感じになります。

f:id:rosone:20200821111339p:plain
SUCCESS③

カタクチイワシは配列の[0]、セキトリイワシは配列の[1]として送信されることを確認できました。

配列の添字も有効のようで、

f:id:rosone:20200821115322p:plain
SUCCESS③-②
このように表現することも出来ました。

おわりに

今回は手を動かすよりも色々とぐぐって「これはもう試したけど駄目だった!!」とやっていた時間が多かったです。

最終的には公式のフォーラムにどんぴしゃの答えがありましたので、

  • オフィシャルのリファレンスを読み込む
  • オフィシャルのフォーラムを覗いてみる
  • 日本語以外でも検索してみる

ここらへんを教訓にして、次に出会う課題ではもっと短時間で解決できるようにしていきたいと思います。