ぼくのかんがえたさいきょうのダイエット
本記事は, Sansan Advent Calendar 第18日目のチラ裏である.
痩せたぞ!!!!
今年の夏,弊部署に新しい部長がやってきた.初めての1on1,彼は開口一番こう言うのである.
「プロフィールと全然顔違わない?」
このセリフだけでは,良い意味とも悪い意味とも取れる.しかし,私には前者である確信があった.何を隠そう,私は2021年,10kgほど減量したのである.同期からも「誰だか分からなかった」と言われたことがある[1].
本記事では,私が実践した内容について触れながら, ぼくのかんがえたさいきょうのレコーディングダイエット方法 を提案する
実践していたこと
BASE FOOD
はっきりと言おう,私はBASE FOOD狂信者である.とはいえ,本物の狂信者には敵わないと思うため,本物[2]の記事を貼っておく.
昨年の前半,ちょうど緊急事態宣言は始まったくらいのタイミングで定期購入を始めた.しかし,昨年はあらゆる誘惑に負け,次の配送までに消費しきれない事象が多く発生していた.「今年はまず溜まりに溜まったパンと麺を全て消費する」,必要に駆られたのが狂信者の入り口であった.
それからと言うもの,くる日もくる日もBASE FOODを食べ続けた.当時部署で食べていたのは私だけだったが,食べ続ける中で最大8人くらいに仲間が増えた.少年漫画もさながらの展開である.
私は体も大きくなければ活動量も多くないため,基本的に毎日2食分を食べる.「不完全食では?」という異論は認めない.この生活を半年ほど続け,体重は線形に落ちていった.
レコーディング
毎朝体重計に乗る.食事のカロリーを記録する.BASE FOOD狂信者とて,ド定番の方法で管理はする.全身鏡で体の変化を画像として記録する方法もあるという.私は,UnderArmor社がリリースしているMyFitnessPalと言うアプリを使っている.バーコードでカロリーが記録できて非常に便利である[3].
一応研究員という仕事をしている性質上,データをCSVにエクスポートできるのも嬉しい点である.データがあるとやりたくなることといえば,なんと言っても時系列予測である.実際に9月までのデータを用い,Prophetによって予測してみる.予測結果によると,今頃は46kgくらいらしい[4].
このままだったら普通のダイエット.ここからがマグマなんです[5].
提案手法
一般的にレコーディングダイエットが失敗する原因は,その面倒くささにある.そもそも面倒くさいと思わない人間は不健康な太り方をしないわけで,本質的にダイエッターたちとは相性が悪い.ここでは,「如何にめんどくさくなくレコードするか」という点で,レコーディングダイエット成功への道を切り開く.
事前知識: Geek Seek
私の所属するSansan株式会社には,Geek Seekという社内制度がある.全体的な話は,次の記事で研究開発部の人[6]が話している内容を読んでもらうと良い.非常にありがたい制度である.
経費精算が発生するため,勉強会の補助については,実施時の風景を撮影した写真を担当部署に報告する運用になっている.当然,参加者本人が確認できる必要がある.
やりたいこと
上記運用をダイエット文脈に読み替えると,「勉強会を開くたびに自分の写真が勝手に貯まっていく」ということである.うまく可視化してやれば,めんどくささを感じずにレコーディングダイエットが完結させられる可能性がある.
そこで今回,次のパイプラインを提案する.勉強会をしているだけで自分の顔の変遷について自動でレポーティングしてくれる ぼくのかんがえたさいきょうのレコーディングダイエット である.
やったこと
さて,ここでは実際に構築したシステムについて解説する.自動レポーティングとは対照的に,ほぼほぼ人力の温もりあるシステムとなった.
証憑DB構築
ひたすら自分がメンションされているポストから画像をダウンロードする.圧倒的ポチ力.つらい.
顔検出
ダウンロードした画像から OpenCV で顔検出する.ほぼHaar-like特徴を使う顔検出のexampleのままだが,結構ギチギチに検出されるため,切り出すときにパディングを入れる.
from pathlib import Path
import cv2
for path in Path('data').glob('*.png'):
img = cv2.imread(str(path))
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cascade = cv2.CascadeClassifier("data/haarcascade_frontalface_default.xml")
face = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3, minSize=(30, 30))
for i, (x, y, w, h) in enumerate(face):
face = img[
max(y-(h//2), 0):min(y+h+(h//2), img.shape[0]),
max(x-(w//2), 0):min(x+w+(w//2), img.shape[1]),
...
]
cv2.imwrite(str(Path('data/detected').joinpath(f'{path.stem}_{i}.png')), face)
ここで切り出された顔らしい部分から自分のみ抽出する.圧倒的目grep.つらい.
可視化
可視化にはFaceMorpherを利用する.FaceMorpherは,ランドマークによって顔画像を変形したり,平均したり,モーフィングするライブラリである.
今回は,勉強会実施日によってソートされた画像列を,幅
コードはこんな感じ.愚直に窓内の平均画像を計算していくため,窓幅が大きいと結構時間がかかる.
from pathlib import Path
import facemorpher
import more_itertools
from PIL import Image
image_paths = list(Path('data').glob('*.png'))
winddow_size: int = 15
step_size: int = 1
images = []
for i, paths in enumerate(more_itertools.windowed(image_paths, window_size, step=step_size)):
filename = f'window{window_size}_step{step_size}_{i}.png'
facemorpher.averager(paths, background='transparent', out_filename=filename)
images.append(Image.open(filename).convert('RGB').quantize(method=0))
Path(filename).unlink()
images[0].save(f'window{window_size}_step{step_size}.gif', save_all=True, append_images=images[1:], optimize=True, duration=100, loop=0)
結果
まとめ
本記事では,社内制度にうまく乗っかってレコーディングダイエットを行うシステムを提案・構築した.現状人力で行っている部分も,API連携・顔認証の導入によって自動化できる可能性がある.「こんな記事出したからには摂生し続けるんですよね?」という自分への戒めとしても,今後取り組んでみたい.
最後に,あくまで社内勉強会自体は大真面目にやっていることを付言するとともに,少しでも社に興味をがあればお声かけくださいまし.
Discussion