ハトマスクステッカーアプリを作ったよ

ハトマスクステッカーアプリって?

顔や全身が写っている写真をURL、または、ファイルで指定すると、適当な感じでステッカーと合成するアプリ。 Agile Japan 2020 ハトマスクステッカー(未認可・非公式)おみまいするぞ で遊ぶことができる。 Agile Japan 2020というイベントのちょっとしたお遊びとして作ろうと思ったのがきっかけ。

f:id:couger:20201123213035p:plain
ハトマスクステッカー「に」合成

f:id:couger:20201123213023p:plain
ハトマスクステッカー「を」合成

どう作った?

コマンドラインバージョン

最初はコマンドラインで、「ハトマスクステッカー合成」する機能を作ろうとしていた。

f:id:couger:20201123213035p:plain

最初の一歩として、写真の背景を切り抜く処理を探す。なるべく自動化したいので、APIが提供されているものを探して、見つけたのは以下の2つ。

残念だけど両方ともお財布に合わなかったので、別のものを探すことに。でもなかなか見つからない...。自分の財力ではムリがある。 GitHubにないかなぁと "github remove background" でググったら、トピックのリストが見つかった!!!

github.com

なんとなく使ってる人の多そうな danielgatis/rembg: Rembg is a tool to remove images background. を使うことにした。 GitHubスゴい。OSSスゴい。

説明を見ながらCLIで実行。キレイに切り抜きができた!!! スゴい。 更に、ステッカーに合成する簡単なプログラムを見よう見まねでPythonで作り実行。上手くいった!
※ RembgがPythonだったのでそれに合わせた。

その時、作ったコードが以下である。

curl -s $1 | rembg > work/target.png
python hatomask-gosei.py work/target.png
import sys
from PIL import Image

def resize_image(original, width):
  return original.resize((width, (int)(width * original.size[1] / original.size[0])))

hatomask = Image.open('hatomask-aj2020.png')

pathToTarget = sys.argv[1]

target = resize_image(Image.open(pathToTarget), 300)

hatomask.paste(target, (1024-300, 600), target)
hatomask.save('omimaisuruzo.png')

これで、合成したい写真のURLを指定すれば、ハトマスクステッカーに合成ができるようになった。ここで辞めておけばよかったのに、Webアプリにしたい欲求が湧いてきてしまう。
そういえば、最近プログラム全くしてなかったし。Azureも久しぶりに使ってみようかと軽い気持ちで始めたら、結局土日2日を潰すことになった。思いつきはだいたい高くつく...。

Webアプリにする

まずは軽いWebアプリフレームワークと、CSSフレームワークを探す。選んだのは以下の2つ。

初めて触るフレームワークだったので、以下のような感じで1ステップずつ進めていった。都度、App Serviceにデプロイして動作確認をしていたと思う。

  • 画面を表示する
  • 画像のURLが指定できるようにする
  • 指定したURLの画像を表示する

この後、Rembgを使った「指定したURLの画像の背景を切り抜く」処理を追加、App Serviceにデプロイしようとするとエラーが出た。 数回試したけどダメ。エラーメッセージにはメモリがないとかディスクのスペースがないとか出てくる。仕方がないので、プランをFreeから、B1にグレードアップ。やっぱり失敗する。

泣く泣くP1v2にして、デプロイが成功。ただし、デプロイに10分くらいかかる。ツラい。1ヶ月使うと1万円かかる。ツラい。
※ S1にしなかった理由は、P1v2と比べて1000円くらいしか違わないから。なんとなく性能の問題のような気もしたし。

とはいえ、のんびり調査している暇もないので、そのまま開発を続けて最初のバージョンをリリースした。 リリースした後「ハトマスクステッカーを合成」する方がニーズあるんじゃないかな? と思い、急遽機能を追加、次の日に再度リリース。

最終的なコードは以下(アプリ部分のみ)。

import sys
import io
import base64
import urllib.request
import hashlib
from PIL import Image
from flask import Flask, render_template, request
from rembg.bg import remove
app = Flask(__name__)

app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024

def resize_image(original, width):
  return original.resize((width, (int)(width * original.size[1] / original.size[0])))

def crop_image(original):
  # https://stackoverflow.com/questions/14211340/automatically-cropping-an-image-with-python-pil/51703287
  imageSize = original.size
  imageBox = original.getbbox()

  imageComponents = original.split()

  rgbImage = Image.new("RGB", imageSize, (0,0,0))
  rgbImage.paste(original, mask=imageComponents[3])
  croppedBox = rgbImage.getbbox()

  return original.crop(croppedBox)

def convert_image_to_base64(image):
  image_buffered = io.BytesIO()
  image.save(image_buffered, format="PNG")
  return base64.b64encode(image_buffered.getvalue()).decode("utf-8")

def remove_background(imageStream):
  r = lambda i: i.buffer.read() if hasattr(i, "buffer") else i.read()
  w = lambda o, data: o.buffer.write(data) if hasattr(o, "buffer") else o.write(data)

  result = io.BytesIO()

  w(
    result,
    remove(
      r(imageStream),
      model_name="u2net",
      alpha_matting=False,
      alpha_matting_foreground_threshold=240,
      alpha_matting_background_threshold=10,
      alpha_matting_erode_structure_size=10,
    ),
  )

  return Image.open(result)

def hatomask_omimaisuruzo(target):
  result = Image.open('static/images/hatomask-aj2020.png')
  target_resized = resize_image(target, 300)
  result.paste(target_resized, (1024-300, 600), target_resized)
  return result

def sticker_ga_ikuzo(target):
  sticker = Image.open('static/images/hatomask-aj2020-rembg.png')
  sticker_resized = resize_image(sticker, (int)(target.size[0] / 3))

  paste_lefttop = (target.size[0] - sticker_resized.size[0], target.size[1] - sticker_resized.size[1])
  target.paste(sticker_resized, paste_lefttop, sticker_resized)
  return target


@app.after_request
def add_header(r):
    r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    r.headers["Pragma"] = "no-cache"
    r.headers["Expires"] = "0"
    r.headers['Cache-Control'] = 'public, max-age=0'
    return r

@app.route("/")
def hello():
  return render_template('aj2020.html')

@app.route('/sareruzo_url', methods=['POST'])
def sareruzo_url():
  imageUrl = request.form.get('imageUrl')
  f = io.BytesIO(urllib.request.urlopen(imageUrl).read())
  target_removebg = remove_background(f)
  target_cropped = crop_image(target_removebg)

  hatomasked = hatomask_omimaisuruzo(target_cropped)
  return render_template('aj2020-omimaishitazo.html', imageBase64=convert_image_to_base64(hatomasked))


@app.route('/sareruzo_upload', methods=['POST'])
def sareruzo_upload():
  if 'imageFile' not in request.files:
    return render_template('aj2020-omimaishitazo.html', imageFile="images/hatomask-aj2020.png")

  imageFile = request.files['imageFile']
  imageFileName = imageFile.filename

  if '' == imageFileName:
    return render_template('aj2020-omimaishitazo.html', imageFile="images/hatomask-aj2020.png")

  target_removebg = remove_background(imageFile.stream)
  target_cropped = crop_image(target_removebg)

  hatomasked = hatomask_omimaisuruzo(target_cropped)
  return render_template('aj2020-omimaishitazo.html', imageBase64=convert_image_to_base64(hatomasked))

@app.route('/suruzo_url', methods=['POST'])
def suruzo_url():
  imageUrl = request.form.get('imageUrl')
  imageFile = Image.open(io.BytesIO(urllib.request.urlopen(imageUrl).read()))

  hatomasked = sticker_ga_ikuzo(imageFile)
  return render_template('aj2020-omimaishitazo.html', imageBase64=convert_image_to_base64(hatomasked))


@app.route('/suruzo_upload', methods=['POST'])
def suruzo_upload():
  if 'imageFile' not in request.files:
    return render_template('aj2020-omimaishitazo.html', imageFile="images/hatomask-aj2020.png")

  imageFile = request.files['imageFile']
  imageFileName = imageFile.filename

  if '' == imageFileName:
    return render_template('aj2020-omimaishitazo.html', imageFile="images/hatomask-aj2020.png")

  hatomasked = sticker_ga_ikuzo(Image.open(io.BytesIO(imageFile.read())))
  return render_template('aj2020-omimaishitazo.html', imageBase64=convert_image_to_base64(hatomasked))

ハマったところは?

Azure App ServiceのFreeプランでは動かない

B2プランなら大丈夫。Freeプランでは、Rembgを動かすためのリソースが足りないのだろうと推測。

やりたい処理によって画像ファイルを扱うクラスを変える必要がある

コピペ優先でホイホイ作ってたから、この辺を理解しておらず、追加機能を作る際に苦労した。
ちなみに以下の3つを覚えておけば多分いいはず。(それくらい最初に調べとけってツッコミは甘んじで受けます...)

  • アップロードされたファイル: werkzeug.datastructures.FileStorage
  • 画像の透過、貼り付け: PIL.Image
  • Rembgを使った背景除去: io.BytesIO

今後は?

ステッカーの種類を増やしたり、位置や大きさを変えられるようにしようかなーと思ってたりするんだけども。さて。

ガンプラ作りとイテレーティブ、インクリメンタル

アジャイルでよく聞く言葉にイテレーティブと、インクリメンタルというものがある。

インクリメンタルでもイテレーティヴでも同じものを目指しているように見えるが、 インクリメンタルな開発は顧客が満足しないものを作ってしまうリスクが軽減されていない。 大きな絵はプロジェクトのいちばん最後にしか見ることができない。 インクリメンタル開発で細部まで作りこんでしまうと、修正が発生した場合に、多くの努力が無駄になってしまう。 イテレーティヴな開発は開始時点からの絵の変化を見ることができる機会を提供している。 そして一歩ずつ全体の絵の完成に向けて進んでいくのをガイドしてくれる。 イテレーティヴとインクリメンタルの違い | Ryuzee.com

https://www.ryuzee.com/contents/blog/images/2985/mona-lisa.png

最近ガンプラ作りを始めたのだけど、その中で、インクリメンタルとイテレーティブを実感したので、説明してみるテスト。何を今更お前は...というツッコミは気にしないことにする。

1体目 - 1/144 FG-01 RX-78-2 ガンダム

サフを吹いてパチ組*1しただけのモデル。これにはインクリメンタルもイテレーティブもない気がする。

f:id:couger:20201123113636j:plain
FG-01 ガンダム サフ+パチ組。サフ吹くだけで悦に入れるのはなぜだろう?

2体目 - 1/144 FG-02 MS-06S シャア・アズナブル専用 ザクII

合わせ目消し+全塗装にチャレンジした。いきなりハードルを上げすぎた気はするが、やりたかったんだから仕方がない。 最初は、パーツごとに合わせ目消し+塗装まで行い、完成させていた。

f:id:couger:20201123113815j:plain
FG-02 シャアザクの太もも。太もも。

合わせ目消しと塗装は超久しぶりで、どんな道具を使い、どういう風に、どの程度までやるのが自分に合っているのかさっぱりわからない。 私はカジュアルにくじけるタイプなので、途中でくじけないように、モチベーションを維持することがとっても大切。 この時は「一部でも完成しているもの」を見て「悦に入る」ことで、モチベーションを維持していた。

当然、最初と最後でやり方も練度も異なるので、できあがりの精度が(へたっぴレベルで)マチマチ。 最初の方に作ったパーツは、塗装を削って、合わせ目消しをやり直すようなこともあった。

全体的に見ると、非効率極まりない気はするが、それよりも、自分のモチベーションの維持が大事だったので、これはこれで良かったんだと思う。 最後は、せっかくだからと、撮影ブースを自作して撮影してみたり。ガンプラ沼も広くて深い。ヤバい。

f:id:couger:20201123113844j:plain
FG-02 シャアザク。撮影ブースで。(塗り分けはギブアップしております)

3体目 - 1/144 RGM-79GS ジム・コマンド [宇宙用] (旧キット)

HGUCに行く前に練習と思って買ったわけだけど、あれこれ見てると旧キット作る方が難しいっぽい...。よくこの手の間違いを犯すんだけど、仕方がない。

今回は、あとハメ*2+合わせ目消し+全塗装にチャレンジ。シャアザクで合わせ目消しや、塗装の経験があったせいか、ちょっと作り方が変わった。作り方というか「悦の入り方」が変わったというのが正しいだろうか?

具体的には、パチ組で悦に入り、あとハメ加工したあと組み上げて悦に入り、合わせ目消しした後組み上げて悦に入り...。という流れ。各工程は(工夫の余地はたくさんあれど)やり方が分かってきたので、区切りの良いところで、組み上げて全体的なものを見て悦に入るという感じ。 まだ合わせ目消しの途中だけど、多分、この後は試し吹きして組み上げ、合わせ目修正+スジ彫りして組み上げ、塗装して組み上げ、という流れになると予想される。

f:id:couger:20201123113858j:plain
ジム・コマンド [宇宙用] あとハメ+合わせ目消しして組み上げたやつ。ポーズが気に入っている

で、何が言いたいの?

ようやく、タイトルの話になるんだけども、2体目の組み方がインクリメンタル、3体目の組み方がイテレーティブなんじゃないかなと。 で、インクリメンタルとイテレーティブでは「悦の入り方」が違うのかもなーと思ったというお話でおしまい。 仕事に使えるかどうかはさっぱり分からない。が、まぁ、そこはいいのである。

とはいえ、最初から3体目のような悦の入り方で進めるのは、私には無理そう。手馴れたものだとイテレーティブにできるよねってだけかな?

*1:スナップフィットモデルを接着、塗装など行わずパチパチと組み立てたもの https://twitter.com/ravensnest8525/status/894866675954089984

*2:組み立て後に分解できなくなるパーツを、組み立て後もパーツ同士をハメたり外したりできるように加工する工作 https://yzphouse.com/gunpla-kaizo-atohame

ハトマスクおみまいするぞアプリを作ってみたよ

機能

  • 顔を検出すると見境無くハトマスクをかぶせるよ
  • 顔の向きに合わせてハトマスクをかぶせるよ
  • たくさん顔があってもかぶせるよ
  • かぶせるマスクを変えることもできるよ
    • f:id:couger:20191223193207p:plain
  • リアルタイムでかぶせるよ
  • 保存もできるよ
  • 今の所は iPhone でのみ動くよ
    • UnityだからAndroidの対応も楽なんじゃないかなぁと期待しているよ

きっかけ

使ったツール

使った時間

  • 原型作るのは1週間だったよ
    • 顔の向きにある程度合わせてマスクが出るところまで作ったよ
    • dlibのサンプルプログラムを改変したらできるかなと安易に考えてたけど、Unityさっぱりわからないので結局チュートリアルから始めたよ
    • マスクのディティールアップに1日使ってたりするよ
  • その後、コードの整理や顔の向きの調整、スマフォの縦向き、横向きに対応してたら2ヶ月経ってたよ
    • 自分の時間にやってる(ので平日は1時間くらい、休日は5,6時間)とはいえ、そんなにかかるとは思ってなかったよ
    • 原型はコピペで作ったんだけど、細かい調整するためには理屈をある程度理解する必要があったので苦労したよ
    • コードは整理というかほぼ書き直したよ
  • 理屈が先か、動かすのが先か悩むけど、私は最初に理屈を求めるとメゲるので、動かすのが先派だよ

ちなみに右往左往はScrapboxにメモしたよ。
フォーマットあんまり気にせずガシガシ書けるから実況に使うと捗るよ。
ハトマスクをおみまいするぞアプリ - のび犬.メモ

今後

  • AppStoreに出すのが目標だよ
  • まずはβ版を出してみるので、フィードバックもらえると嬉しいよ
    • iPhoneだとTestFlightってアプリを入れる必要があるのでちょっと敷居が高いかもしれないよ
  • ハトマスクはアーチーマクフィーのものを参考にしてるので、許可を取ろうと思っているよ
    • 実はお問い合わせから打診のメールを送ったんだけど、全く相手にされなかったよ...。
      • ぶっきらぼうなメールだったので、怪しいメールで終わっちゃったんだと思ってるよ

Azure FunctionsでAzure Storageに置いたExcelファイルを取ってきて、編集する

やりたいこと

シフト表を作りたい。

  • シフト表のテンプレートはAzure Storageに置いている。
  • スケジュールの調整は、スケジュール調整サービス(調整さんとか、TONTONとか)でやっている。

スケジュール調整サービスから結果を取り出し、シフト表のテンプレートに反映して、ダウンロードしたい。

やったこと

とりあえず、Azure Functionsで、ExcelファイルをAzure Storageから取ってきて、ダウンロードできるところまでを作ってみる。
ExcelJavaScriptで操作するライブラリは exceljs を使ってみた。

github.com

コード

特に変わったことはしていない。
ハマったところは、function.json"dataType": "binary" を設定するところ。設定しないと workbook.xlsx.load でコケてしまう。

index.js

const Excel = require('exceljs');

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    var workbook = new Excel.Workbook();
    await workbook.xlsx.load(context.bindings.shiftScheduleTemplate);

    context.res.setHeader("Content-Type", "application/vnd.ms-excel")
    context.res.setHeader("Content-Disposition", "attachment; filename=ShiftSchedule.xlsx");
    var buff = await workbook.xlsx.writeBuffer();
    context.res.body = buff;
};

function.json

{
  "bindings": [
    {
      "type": "blob",
      "name": "shiftScheduleTemplate",
      "direction": "in",
      "dataType": "binary",
      "path": "assets/shiftschedule-template.xlsx",
      "connection": "Assets_STORAGE"
    }
  ]
}

コツコツが苦手な人が何をコツコツやれるのか? って探してんのかも

コツコツが苦手な人が何をコツコツやれるのか? って探してんのかもね。

コツコツではなく、ダラダラでもやるだけマシ、ついついやっちゃうものは自分が気づいてないか、気づいててもその使い方が分かんない。

ダラダラは3日坊主を月3回やったら、1/3くらいできてるのでよし。とか、ハードル下げとくのと、好きなことを絡めること。好きなもので解釈したり、好きなもので練習したり。(好きでもコツコツできないものもあるだろう)

ついついやるのは、なんらかの理由によって自分にとっては必要なもの。と考えると、その理由がわかれば、同じニーズや課題を持つ人を助けられるかもしんない。

なかなか上達しない自分を許す、自分の「ついついやる」をのんびり掘ってみる。

単にせっかちでのんびり続けるにはで終わりそうな気もしてきた。

ただ、せっかちも使いどころなので、なくすともったいない。そもそもそんなに簡単に治らんw

変化が速い(気がする)コミュニティと、ゆっくりな(ような気がする)会社にいるので、両方を体験はできてるのかもな。 子育てとかもゆっくりだ。

この辺は速度の違う複数の環境に身を置いてると言える。どれもできない、中途半端な立ち位置にいるのが、オレだとすれば「情報生産者になる」の「境界人」になりえるかもしんない。

んなこと言ってる間にやればいいって話はあるんだけども、やれるんだったらこうなってないので、こういう風に文字に起こしながら、自分の納得をゆっくり育ててる。

あー、せっかちで頑固ってことか。うわ、面倒。 ま、それも使いどころってことで。

グダグダな主人公がなんとかかんとかやってるマンガやドラマとかが知りたい

何でそんなものを?

  • 仕事で上手くいかない時に自分に対してボヤくことがあるんだけど、たまにボヤキすぎてふさぎ込んでしまうので、ヤバい。
  • ふさぎ込みそうになった時は、気分転換として、グダグダな主人公がなんとかかんとかやってるマンガやドラマを見て気分を切り替えることが多い。
  • 自分のネタを晒したら、同じような境遇の人(いるのか?)にネタを見せてもらえるかもしれないので、晒してみよう。

グダグダな主人公がなんとかかんとかやってるマンガやドラマ

水曜どうでしょう

いきなりマンガでもドラマでもないものを選んでしまった。でも良いのである、回復さえすれば。
大泉洋氏のボヤキと、4人の七転八倒の旅は癒しである。

仮面ボクサー

30年パンチを打つまでのグダグダ感がとても素晴らしい!!! とか言いつつ、この記事書くまで忘れてたので、今度から読むようにしよう。

燃えよペン逆境ナイン

症状が軽い場合はこれで良いかも。炎尾燃の「駄作で金をもらってこそ本当のプロ」とか、サカキバラ・ゴウの「それはそれ、これはこれ」とか。
うっかりすると、負け犬パルスに感染するので注意。「君よ、パルスを正せ!」って、そもそも負け犬パルスになってるのを修正するために、読むんだった...。

以下は、教えてもらったもの。

GIRLS

例えば恋愛面では、「次々と登場するイケメンとの恋愛」のような現実離れした設定は一切なく、ダメンズとの上手くいかなすぎる関係が連続。主人公のレナ・ダナムもハリウッドタイプとは言えないヌードを披露し、体を張って「本当にいる女子」をそのままスクリーンに持ってきている。

front-row.jp

面白そうなので見てみるかなぁ。

聖 おにいさんのイエス

言われて思い出した。あの人も結構グダグダだ。神様なのに。

TL;DR

自分に対してボヤく

タイトルにあるように、うっかりアジャイルの推進側に回った人なので、相応の覚悟とかスキルとかない。 特に相談とか調整とか、すごく苦手。メール書くだけで軽く30分は唸る。なるべく調整とかしたくないから、ミニマム、自分のできる範囲で考えちゃう。
最初の一歩としてはその方が良い時もあるんだけど、広めようとした場合は逆。必要なリソースを集められないので、困ることになる。
いつも首が回らないのはこのせいでもある。

でも、分かっていてもどうにもならないんだよなぁ。どうにもならないと言うか、これから修正するのは厳しすぎると言うのが正直なところ。
いや、単に、そこはもう修正したくないところなのかもしれない。人間やろうと思えば、いつからだって変われるわけだから。

そう言う欠点にようやく気付いたのが最近。ついでに、アジャイルにも向いてないってことも分かったりして、推進側としてそれで良いのか? と思うことが増えてきているわけである。
なら、やめれば良いんだけども、で、それが正しい気はするんだけども...。まぁズルズルやっちゃってる...。ごめんなさい。

色々できないことが増えてくと、うっぷんがたまる。
たまったものを他の人にあてたら嫌なやつだ(たまにやるけど)。そもそも悪いのは自分なんだから、自分に対して自分で愚痴る。ボヤく。
アジャイルでコントロールできるのは自分だけって教えてもらったしなぁ。

ボヤキすぎるとハマる

自分に対するボヤキも最初のうちは面白おかしく言ってるわけだけど、たまにバッドルートを選んじゃうことがある。
このルートに入ると、どんどん気が滅入ってきて、何もやりたくなくなる。
才能もないのに動くことすらしなかったらもうどうしようもない。なんとか動くところまで戻りたい。

今書いてて思ったけど、こういうところを行ったり来たりしてパワーを使ってるからダメなのか。でも、仕方がない。自分なんだもの。そうそう簡単に変わるわけないもの。うまく付き合うしかないんだもの。

ハマった時の脱出方法

この話をFacebookで書いて、最初のコメントで教えてくれたのがこれ。

tarashare.net

とりあえずなんか始めてみようハック。
確かにその通りで、これがファイナルアンサーなんだけど。そこに至るまでが難しい。
後出しで悪いんだけど、私は意思がとっても弱いのだ。その点だけは自信がある。

なので、意思の弱い私が「何もしたくない」とふさぎ込んでしまった時、どうやって自分をなだめて「とりあえずなんか始める」ところまで持っていくのかってことになるわけだ。書いてて寂しくなってくるけれども、仕方がない。これがありのままの自分なのだ。事実から目を背けてはいけない。

ふさぎ込んでるから、さらっと見れる慣れ親しんだものがいい。自分は漫画とアニメとおバカである。
キラキラした本とか事例とかは避けたほうが無難。と言うか、ふさぎ込みが加速してしまう。私は日の当たる場所の住人じゃないんですとか言い始める。
とはいえ、最終的には前向いて進んでる感のあるものじゃないと、そもそもの目的が達成できない。

ようやくこれでタイトルの「グタグダな主人公がなんとかかんとかやってるマンガやドラマが知りたい」と言う話に繋がるわけである。
話が長いんだなぁ。オレ。

ボンクラ仲間探してます [Ver 2018.3.18]

ボンクラ仲間探してます (途中) - cougerの日記 の続きというか、リライト。また書き直すと思う。

今北産業

  • 「自分は何ができるのか」を言語化しようとする中で『無い才能を見切って』たら、ボンクラに行き着いた
  • 「念仏唱えて功夫積むしかない (by 角師父)」からは逃げられないと悟った
  • でも、修行は辛いし、ボンクラを受け入れるのもまぁまぁ辛いので、基本、笑っていられるよう、好きとか、面白いを大事にすることにした
  • 万が一オレもそうだって人がいたら、こっそり教えてほしい

若干ストーリーを作ってるところはあるけど、大体こんな感じのはず。 1つ目と2つ目はおそらく同時並行的に。どっちが先だったとかあんまないはず。

ボンクラとは?

角征典さんのブログでボンクラの定義が紹介されている。 BREAK Max (ブレイクマックス) 2011年 12月号で、吉田豪さんが町山さんにインタビューしたときの話だそうだ。

町山「ボンクラって、もともとシノギができないヤクザのことを言うんだよね。ヤクザの世界では、すごく頭がよくて商売をやってシノギができる人が正しいんだけど。ボンっていうのは博打で、博打とかお金のことがうまくできない人をボンクラって言うわけですよ。その人はどうしてヤクザになったかっていうと、ヤクザに変なロマンを持って入ってきてる人なんですよ。でも、そういう人は絶対成功しないんだよね。」

「商売が下手」「変なロマンを持っている」というところが私としてのポイント。
金稼げないわ、面倒くさいわ、で扱いづらいことこの上ないってことなんだね...orz

「自分は何ができるのか」を言語化しようとする中で『無い才能を見切って』たら、ボンクラに行き着いた

断っとくと、最初から「自分は何ができるのか」なんて大層なことを考えてたわけではない。
後、金稼ぐのは下手だと分かっていたけど、ボンクラとは認識はしてなかったように思う。

ボンクラに気づくきっかけは 【デンパ】 人間の業を肯定し、得体のしれないモチベーションを使ってアジャイルと付き合う - ボンクラの日記 に書いていた。

45歳になってとある教育を受けたとき、このまま情報ため込んで爆死はちと寂しいと考えるようになり

老い先短いと感じて、どうしたもんかと考えたらしい。
同時期(多分)に、 【全文公開】伝説の漫画編集者マシリトはゲーム業界でも偉人だった! 鳥嶋和彦が語る「DQ」「FF」「クロノ・トリガー」誕生秘話 を読んだ。

作家には「描きたいもの」と「描けるもの」があるんだよ。そして、作家が「描きたいもの」は大体コピーなの。既製品の何かで、その人がそれまでの人生で憧れてきたものでしかない。 鳥山明さんであればアメコミっぽい作風だとか、そういうものが「描きたいもの」としてあったけど、そこからヒット作はやっぱり出てこないんです。実際、鳥山さん自身の「描きたいもの」は、申し訳ないけどつまらないんですよ(笑)。

「描けるもの」はそう簡単に見つからないので、自分にとって「描きたいもの」は何だろうと考えた。 社内外のスゴい人などと比較しながら、自分にダメ出しして、「ない才能を見切った」結果、残ったのは「情報屋」だった。

まぁ見切ると言っても、エンジニア、マネージャ、事業家、コーチ、エバンジェリストくらいなので、「そりゃないわ」で終わるんだけどね。

今考えると「情報屋」にもスゴい人は沢山いるだろうから、見切るリストに入るはず。運良く?スゴい人のイメージがなかったから、ここならいけるのかも? と思っちゃったんだろうなぁ。

ともかく、やれそうなことがぐっと減った上に、ここまでお金のことを考える機会から逃げてきたこともあり、情報屋で稼ぐ方法も思いつかないので、「商売が下手」は確定。

「変なロマン」については「ボンクラの定義」を引用。

吉田「カッコ悪い金の稼ぎかたをしちゃいけない、みたいなことを考えちゃうわけですか?」 町山「そうそうそう。仁義とか考えたり、男同士の友情とかそういうのを考えてヤクザに入ってくる人は絶対成功しないんだよ。商売に向かないから。

オレが持ってる「変なロマン」はこの辺っぽい。これは確かに儲からない。
よく考えたら、入社して以来、メインストリート歩いてない。アジャイルもそうだ。今はともかく、ちょい前は傍流だった。ずっとオルタナティブなところを歩いてる。

そんなこんなで「商売が下手」「変なロマン」の2つが揃ってるボンクラな人なんだなぁと認識することになった。
※ 変なロマンを認識したのは、この記事を書いている最中である。

「念仏唱えて功夫積むしかない (by 角師父)」からは逃げられないと悟った

「念仏唱えて功夫積むしかない」は、勝手に師匠と仰いでいる、角征典さんから仕入れた言葉。
角さん、アジャイル界隈で知る人ぞ知るすごい人だと思ってるんだけど、知名度がどうも低いらしい。

微力ながら応援したいので、今度「角さんスゴい」エントリ書くことにしよう。

...脱線したので、元に戻る。

もともと飽きっぽく、いろいろ長続きしない性格なので、「念仏唱えて功夫積む」という行為は対極に位置するもの。 それでも、そこしかないんだなぁと気づくきっかけをくれたのは、「社内情シスにおけるDevOps導入のお手伝い」だ。

「社内情シスのお手伝い」では、「念仏唱えて功夫積む」を丸ごと経験した。

レガシーな開発をしてた人が、アジャイル/DevOpsの世界に入門し、2年もがいた結果、1週間で何かしらリリースするところまでこぎつけたのである。
ファンタジーでもない、どっか遠い世界の事例でもない、目の前で起こった事実だった。ちょっと驚いた。

このお手伝いを通じて、「環境をある程度整えて、時間をかければ、成長する可能性はある」という「念仏」を唱えて、ひたすら修行を続ける、「功夫を積む」ことで、生まれるものがあるんだなぁと実感できた。
ちなみにこの2年という時間を確保するために、マネージャーは胃を痛め、精神を削られながら頑張っていた。尊い。頭がさがる。

もちろん、マイクロソフトでDevOpsエバンジェリストをしていた牛尾さんが、偶然、情シスの取り組みに興味を持ち、幹部への説明や、技術支援、さらには、社外での事例発表の場を設けてくれるなど、様々なバックアップをしてくれなければ、この場所にはたどり着いてはいなかった。
タイミングというか、運が良かったという点は抜きにして語れないんだけども、そこはオレに制御できるものではないので、気にしないことにする。

後、アジャイル界隈でも、倉貫さんが立ち上げた ソニックガーデン の活動が、経産省を始め、様々なサイトで取り上げられており、自分の信じるものを軸にコツコツと続けている方々が成果を出しているのを目の当たりにし、勝手に感銘を受けているみうらじゅん氏の「ない仕事の作り方」や、大槻ケンヂ氏の「サブカルで食う」で「ボンクラは継続するしかないんだぞ」と諭され、ここから逃げることは不可能だと悟った次第。

あ、情シスさんの事例はde:code17で発表、資料がSlideShareにアップされている。動画もあるので、興味のあるかたは是非。

番外) 長く続けるための「自分なくし」

「昼の勉強会」についても少しだけ触れておく。
「昼の勉強会」では、長く続けるためのTIPSみたいなものを学んだ気がする。長く続けようとすると飽きるし、疲れるので、自分だけでは回すことができない。
結果、色んな人の手を借りて進めることになる。となると、全てを自分の好みで統一するのは不可能だ。というか、そんなことしたら手が借りられない。
だから、自分は何が好きで、何が嫌いなのか、どこが譲れないところなのかを考えることにした。
結果、「お気軽」な所だけ守れてたら、あとは何でもありってことにした。それが功を奏したかどうかはわかんないけど、自分的にはずいぶん楽になったような気がする。

みうらじゅん氏が言うところの「自分なくし」は「自分をなくすほど夢中になる」ってところがメインらしいんだけど、自分の譲れないところを最小限にしてみるってのもあるんじゃないかなぁと思った。
スゴい人なら自分の譲れないところを全部持っていけるんだと思うんだけども、オレはスゴい人じゃないので。

でも、修行は辛いし、ボンクラを受け入れるのも辛いから、基本、笑っていられるよう、好きとか面白いを大事にすることにした

書いてある通りである。辛い。
辛いが続くと心が荒む。オレの場合、心が荒むと他人のアラが許せなくなるらしく、周りへの当たりが強くなる。
功夫を積むために、他の人の力を借りないといけない人が、心が荒んで周りへの当たりを強くしてしまうと、暗黒である。

残念ながら回復力は高いほうではない。ので、一度荒むと自力で回復するのは難しい。
なので、なるべく荒まない方向で考えることにした。

  • 面白い、面白そうと思うもので修行する
  • 好きなもので身の回りを囲む

面白い、面白そうと思うもので修行する

最近、ハトマスクをかぶってあちこちで写真を撮っている。こんなの。

きっかけは「隣の人がハトマスクを持っていたこと」である。デイリーポータルZの林さんの記事(2013年)を見たときからいいなーくらいは思ってたんだけど、隣の人が持ってると知って、やりたいに加速がかかった。(自分が好きなことを誰かがやろうとしていると、やりたくなってしまうという困った性分があるらしい)

portal.nifty.com

北の方(社内)でちょうどイベントがあるということで、そこに持ち込むことにした。
最初は自分の写真が撮れれば十分だったんだけど、思ったよりウケたので、調子に乗ってあちこちで写真を撮った。
Twitterで流したら、意外とウケた。ので、さらに調子に乗ってあちこちで写真を撮ってみた。

が、続けてみるとやっぱり辛い。なんでオレこんなことしてるんだろうとか思うこともある。
ガンダムスタンプラリー では、全65駅でハトマスクかぶって写真を撮ってみた。撮るだけじゃ寂しいかとコメント入れてみたんだけど、全駅に入れようとするとこれまた辛い。

そういえば、最近写真撮ってなかった気もするな...撮らなきゃ。(義務に変わりつつある...)

と、まぁ、最初面白くてやったものが修行っぽくなってきたのである。
ただ、アジャイル界隈で初めてのイベントに行って「ハトマスクの人ですよね」で通じたりするので、コミュ障にとってはありがたかったりもする。いい写真が撮れると楽しいし。
なので、「継続する」修行だと思って続けることにした。

あとは、ソシャゲー。こちらも例に漏れず方々食い散らかしてたんだけど、運良く好みの絵や外連味のあるゲームに出会えたので、これ幸いと「継続する」という修行をすることにした。
ドラゴンスラッシュ」と「戦の海賊」がそれ。グレイソウルかっこえー!!! :D
俺的には、強いキャラに浮気して「オレ強い」欲求を満たしつつ、好きなキャラで萌えて継続するのがイイ感じらしい。

そんなこんなで、修行は面白いや好きなことをうまく使ってやることにして、仕事でやるのは最小限にした。

好きなもので身の回りを囲む

ここはあんまり言うことがない。
多少の荒みは「好き」が回復してくれる。笑うと力が抜けるのか、体が楽になることもある。
今日の好きは「Laurelさんのイラスト」。かわいすぎる!!!

好きなもので身の回りを囲んで、精神の安定を保っておけば、ある程度のことは面白がったり、笑ったりできるみたいだし。

おしまい

ということで、かなり長くなったけど、自分的にはボンクラとハトが繋がって非常に満足。
この先は、さっき紹介した変なロマン、

この辺を中心に、今までにあんまり表に出てこなかった(と思われる)視点で、アジャイル界隈を切り取ってみようかなぁと思う。 これまでに得た全ての理屈を、こういうわけわからんことを説明するために使うっていうのは、最高にムダな感じがして良い :P

アジャイルがメインストリームになりそうな今、アジャイルの中にあるオルタナティブを探しに行くのだ。

もしかしたら、似たようなボンクラな人にはフィットするかもしんないけど、そこは私にはわからない。万が一フィットした人がいたらこっそり教えてくれると嬉しい。

書けなかったこと

自己肯定の話も書きたかったんだけど、疲れたし、どこに入れればいいのかわかんなかったので、メモだけ残して終わる。

助けになったのは「ジョイ・インク」と「ザ・ヤングアメリカンズ

ジョイ・インクは、米国で最も幸せな職場と言われるメンロー・イノベーションズ社について書かれた書籍。
なぜ買ったのか覚えてない。でも、ショックを受けたのは覚えてる。 まずあるのが「喜び」。他のことは「喜び」に従属するもの。ややこしい理屈で生きてない。ものすごいシンプル。
素直に「喜び」でいいんだーって思った。書籍でいう「喜び」はオレの思ってた「開発者としての喜び」とは違うもので、ぶっちゃけ勘違いだったわけなんだけど、そこには後で気づけたし、勘違いでも救われたんだから、まぁよしとする。

ザ・ヤングアメリカンズの方は、正確には、彼らが行う「アウトリーチ」というプログラム。

ヤングアメリカンズは1992年から「アウトリーチ」と呼ばれる教育活動をスタート。学校やコミュニティを訪れ、小・中・高校生たちと一緒にわずか3日間(地域によっては2日間)で歌やダンスのショーを作り上げます。 ヤングアメリカンズが第1幕を、そして第2幕では参加者の子どもたちがヤングアメリカンズと共演し、ご両親、友達、先生方や学校関係者を驚かせることになるわけです。

学校でもらったチラシを子供が「受けたい」って持ってきたので、受けてみることに。
私は荒み時期だったので、まぁいいんじゃないって感じだったと思われる。が、最後のショーを見て驚いた...ハズ。

熱量もスゴいんだけど、子供たちが自信持って踊ってる。上手い下手関係なく。
全く知らないところから3日間でショーを作り上げるんだから、そりゃ至らないところだって山ほどある。でもそこは大事なとこじゃないのだ。
頑張って挑戦したことが尊いのである。

(以下、続く)