shobylogy

叩けシンプルの杖

I'll talk about color detection from fashion images in Fasion Tech Meetup #2

I'll participate in Fashion Tech Meetup #2, and talk about color detection from fashion images. The meetup will be held on March 22.

fashion-tech.connpass.com

Sad to say, the event will not be translated into English. However I'll translate my presentation after the event.

My talks contains following contents.

  • Removing background from fashion images
  • Color correction of images taken with a fluorescent lamp
  • Extracting "main color" and "sub color" from a image
  • Color matching between RGB values and color groups

Please check it! Thanks.

第二回 Fashion Tech Meetup (3/22) で商品画像からの色検出について話します

3/22(火)に第二回 Fashion Tech Meetupというイベントに参加します。 フリルにカラー検索という機能を実装した際に、商品画像から色情報を検出した話をする予定です。

fashion-tech.connpass.com

Fashion Tech Meetupは、ファッション x テクノロジーというテーマで ファッション関連のサービスを運営している企業が、日頃得た技術的なノウハウを共有する勉強会です。

MERYを運営するperoliさん、iQONを運営するVASILYさんと共に、フリルを運営するFablicが発表をします。

僕の発表は、以下のような内容の予定です。

  • 商品画像からの背景領域削除
  • 蛍光灯下で撮影された画像の色補正
  • 商品画像から商品のメインカラーとサブカラーを検知
  • RGB値とファッションにおける「色系統」のマッチング

かなり面白そうなイベントなので、僕自身もワクワクしています。 良ければ話を聞きに来てください。

Objective-Cで書かれたメインプロダクトを少しずつSwiftに書き換える

現在、私はObjective-Cで書かれたメインプロダクトを少しずつSwiftに書き換えている最中です。*1

おそらく奮闘中の皆さんのためにも、私が得た知見をお話ししようと思います。

なぜメインプロダクトのSwift移行が進まないのか

これは、単純にメインプロダクトは巨大で複雑であることと、メインプロダクトでユーザーに新たな価値を届けつつ、同時にSwiftに移行するのが困難であるのが原因であるように思えます。

大きなメインプロダクトは一部を書き換えるだけでも依存関係を解消するのに骨が折れます。 書き換えを進めると「え、このクラスここでも使われてるの…?」というような新事実が後から判明します。

また、メインプロダクトは、新機能の実装や改修でユーザーに新たな価値を届けなければなりません。会社の収益源となっているようなサービスの開発を長期間止め、Swiftへの移行だけに力を注ぐわけにはいきません。

機能開発と同時にアプリを別言語に書き換えるというのは、走っている自動車のタイヤを走りながら付け替えるような荒技のように思えます。なかなか難易度が高いですね。

上記のような理由でメインプロダクトのSwift移行がなかなか進んでいないのだと思います。

そこで、そのような環境下でも、少しずつSwiftに移行する方法をひねり出しました。

メインプロダクトを少しずつSwiftに移行するTips

  • 新規クラスは必ずSwiftで書く
  • 1度に書き換えるのは1回のQAでカバーできる範囲まで
  • Utility -> View -> ViewController -> Model -> APIClientの優先度で書き換える

新規クラスは必ずSwiftで書く

新規クラスは必ずSwiftで書くようチーム内でルールを定めましょう。

既存のObjective-Cのクラスを書き換えるのは大変ですが、新規クラスをSwiftで書くのであればさほど問題ありません。

メインプロダクトの開発の主目的である「ユーザーに新たな価値を届ける」という目的を達成しつつ、Swiftのコードを増やしていけます。

1度に書き換えるのは1回のQAでカバーできる範囲まで

Swiftへの書き換えは、1度に1回のQAでカバーできる範囲内にとどめましょう。 やりすぎると事故が起きます。

例えば、画像周りで機能改修をしている場合、関連するクラスを一緒に書き換えると、機能改修と書き換えを同時にチェックすることができます。

事故は注意していなかった部分で起きることが多いため、注意が向いている部分を書き換えて一緒にQAしてしまうと安心してリリースができます。

Utility -> View -> ViewController -> Model -> APIClientの優先度で書き換える

依存度が低い部分から書き換えましょう。

特にちょっとした処理をまとめたUtilityクラスや、Viewのコードは依存する箇所が少ないため、比較的安全に移行ができます。

ViewControllerはちょっと勇気が要りますが、単体で完結していることが多いため、やる気さえあれば移行ができると思います。

問題はModelとAPIClientです。いろいろな箇所から呼び出され、依存関係も複雑なため、移行にはかなりのやる気が必要になるでしょう。*2

まとめ

メインプロダクトは巨大で複雑であり、機能開発と同時に移行を進めなくてはならないためSwiftへの移行がなかなか進みません。

新規クラスはSwiftで書くようにルールを定めたり、1度に書き換えるのを1回のQAでカバーできる範囲内にとどめる、UtilityやViewなど依存の少ない安全な部分から移行を進めることで比較的安全にSwiftに移行を進められます。

*1:ここでのメインプロダクトとは会社の収益源となっているサービスというニュアンスです

*2:ちなみに私はまだ手がつけられていません。

UIAlertControllerを最前面に表示できるよう拡張する

UIAlertController、UIAlertViewのshowみたいな感覚で表示できなくて不便ですよね。

特に、Modalで表示したViewControllerの上に、UIAlertControllerを被せるような使い方をしようと思うと大変です。

そこで、若干ゴリ押しですが、常に最前面にUIAlertControllerを表示できるようにしてみました。

これだとUIAlertViewのshowみたいな感覚で使えると思います。

extension UIAlertController {
    // 最前面にUIAlertを表示する。UIAlertViewのshowと同じようなメソッド
    func presentInFront(completion completion: (() -> Void)?) {
        guard let rootViewController = UIApplication.sharedApplication().delegate?.window??.rootViewController else {
            return
        }
        
        if let presentedViewController = rootViewController.presentedViewController {
            presentedViewController.presentViewController(self, animated: true, completion: completion)
        } else {
            rootViewController.presentViewController(self, animated: true, completion: completion)
        }
    }
}

エンジニア向け都内から行ける日帰り温泉

エンジニア、肩や腰が凝りますよね。そんな疲れた時には温泉に行きましょう。

実は都内から気軽に行ける日帰り温泉がたくさんあります。

今回は、私が頻繁に通うおすすめの温泉を紹介します。

おすすめ温泉

  • 東京染井温泉 Sakura
  • 港北天然温泉 スパガーディッシュ
  • 天山湯治郷

東京染井温泉 Sakura

www.sakura-2005.com

巣鴨にある温泉です。この温泉はアクセスの良さが最高。 山手線で乗り換えなしで行けるのが魅力です。

また、23時までやっているため、仕事帰りに寄ることもできます。 施設が新しく綺麗なので、快適に過ごすことができます。

循環しているようなので源泉掛け流しではないですが、露天風呂が広く、空を仰ぐことができるタイプなので開放感がありリラックスできます。

休憩室が狭めなのが欠点。また、岩盤浴は時間制なため、あまりリラックスできませんでした。 さっと温泉に入ってさっと帰るのがオススメです。

港北天然温泉 スパガーディッシュ

www.gardish.com

横浜方面の温泉です。 この温泉はお風呂の種類が多いのと、施設の広さが良いポイント。

源泉掛け流しの温泉や、人工炭酸泉、ハーブ湯などもあります。 サウナも低温のアロマタイプと、高温の通常タイプの2種類があり嬉しいです。

また、休憩室がかなり広く、漫画も多数取り揃えているため、温泉 -> 休憩室 -> 温泉 -> 休憩室...を繰り返すことで1日潰せます。 (漫画を読みすぎると逆に疲れるので注意)

岩盤浴は時間制限がなく、広めでゆったりした作りなため、リラックスすることができます。

都内からだと若干行きづらいのが欠点。

休日にゆっくりと1日過ごすつもりで行くと良いと思います。 行く価値はあります。

天山湯治郷

tenzan.jp

箱根湯本にある温泉です。 「え、箱根?」と思われるかもしれませんが、 新宿駅から特急なら1時間半、普通列車でも2時間と、気軽に日帰りで行くことができます。 また、普通列車なら交通費は往復2千円ちょっと。意外とお安く行くことができます。

天山は都内から日帰りで行ける温泉の中では最高の温泉だと思います。 泉質も良く、露天風呂の開放感は都内では決して味わえないレベルです。

ポイントが高いのが、ご飯も美味しいこと。 温泉に入ってご飯を食べるだけで幸せな気分になること間違いなしです。

欠点は温泉に入った後、帰ってくるまでに湯冷めしてしまうこと。 普通列車で2時間掛けて帰ってくると、リラックスした気分や楽しかった思い出も冷めてしまっているかもしれません。

まとめ

疲れた時は温泉に行って体を癒しましょう。 仕事後に行くならSakura、休日に行くならスパガーディッシュ、気合を入れて行くなら天山湯治郷がおすすめです。

「シリコンバレー式 自分を変える最強の食事」を読んで「完全無欠生活」を始めた

最近どうにも体調がすぐれず「健康になりたい」という漠然とした思いを抱いていたのですが、「シリコンバレー式 自分を変える最強の食事」という良さそうな本を見つけたため、その本に則って「完全無欠(Bulletproof)生活」を始めました。

シリコンバレー式 自分を変える最強の食事

シリコンバレー式 自分を変える最強の食事

私自身、「健康」や「ダイエット」という単語には一切興味がなく、不健康な生活を続けていたのですが、「シリコンバレー式」や「パフォーマンスを最大化」という謳い文句には強く惹かれ、3週間以上「完全無欠生活」を続けられています。

今のところ、体感としては以下のような変化がありました。

  • 集中力が高まった
  • 全身の倦怠感が減った
  • ズボンがゆるくなり、ベルトの穴を一つ締めた

以下に完全無欠生活とは何か、完全無欠生活を始める準備などを書いていきます。

概要

  • 完全無欠生活とは?
  • 完全無欠生活のデメリット
  • 完全無欠生活を始める準備
  • 完全無欠生活の用語集

完全無欠生活とは?

完全無欠生活とは、どういう食事(インプット)をすると、どういう変化(アウトプット)が体に現れやすいか、ということを著者が自分の体を使って実験した結果生まれた、パフォーマンスを高めるための食生活です。

この生活では、自分が何を食べたらパフォーマンスが上がるか、下がるかを見極め、自分にとってパフォーマンスが上がる食生活を継続することがゴールです。

完全無欠生活の根底には「体に良いものを食べよう」ではなく「体に悪いものを避けよう」という思想があるように感じます。

完全無欠生活の特徴的な考え方

完全無欠生活の特徴的な考え方を以下に抜粋します。詳しくは実際に本をご覧ください。

  • 体に炎症が起きにくい食材のみを摂取するとパフォーマンスが上がる
    • 体に炎症が起きていると脳のリソースが使われて集中力が下がる
    • 食材に対する炎症反応は個人差があるが、万人に悪影響が少ない食材(完全無欠食品)もある
  • エネルギーを炭水化物ではなく良質な脂質から取ることで体脂肪の蓄積を抑える
    • 朝は「完全無欠コーヒー」のみ
    • 炭水化物は夜しか食べない

完全無欠生活のサイクル

「完全無欠生活」をまずは2週間続けることがスタートです。 2週間の間は、体に炎症を起こしやすい食事を避けて「完全無欠食品」のみを口にして生活します。

2週間経った後は、好きなものを思いっきり好きなだけ食べて、「完全無欠生活」との体調の変化を確認し、「完全無欠生活」を続けるかどうかを決めます。*1

その後は、個人によって反応が変わる「要注意食材」を少しずつ試しながら、自分にとって良い食材、悪い食材を見極めていき、パフォーマンスの上がる生活を続けられたら成功です。

完全無欠生活のデメリット

上に完全無欠生活のメリットばかり挙げましたが、実際に3週間試したところデメリットもありました。

主に以下の3点です。

  • お金が掛かる
  • 料理の手間が掛かる
  • 我慢が必要になりストレスを感じる

お金が掛かる

体に悪影響が少ないような良い食材は高いです。 完全無欠生活ではオーガニックの食材が推奨されているのですが、 オーガニックの食材は通常の食材と比べて約1.5倍程度の価格です。

自分の体調やパフォーマンスを確認しつつ、お財布と相談しながら食材を選ぶと良いと思います。

料理の手間が掛かる

完全無欠生活をしている間は、基本的に外食ができなくなるため、料理の手間がかかります。

我慢が必要になりストレスを感じる

特に完全無欠生活の初期では、食べたい物が食べられず、かなりのストレスがかかりました。 私の場合、ストレスを感じた場合は厳密にルールを適用するのをやめ、炭水化物を摂取するようにしています。

完全無欠生活を始める準備

完全無欠生活に興味を持った方は、実際に始める準備をしましょう。

主に、以下の2点が重要です。

  1. 完全無欠食材を扱っているスーパーを行動圏内で見つける
  2. お弁当箱を買う

完全無欠食材を扱っているスーパーを行動圏内で見つける

完全無欠生活を続けるために一番難易度が高いのは完全無欠食材の継続的な入手です。

近くに質の良い食材(できればオーガニック)を扱っているスーパーを見つけましょう。

私は職場の近くにあるナショナル麻布というスーパーで食材を購入しています。 外国人向けのお店であるため、なかなか入手が難しい完全無欠食品であるグラスフェッドビーフやラム肉などが入手できます。

お弁当箱を買う

上でも述べましたが、完全無欠生活を続けようと思うと、外食をすることが困難になります。 お昼もきちんと完全無欠食品にしたい場合、お弁当を作るしかなくなります。

フードコンテナを買っておくと、スープも持ち運べて便利です。

私はこちらのフードコンテナを購入しましたが、お昼は炭水化物を摂取できないためか若干量が少なく感じるため、0.38L以上の物が良いと思います。

サーモス 真空断熱フードコンテナー 0.3L リーフ JBJ-301 LEF 0.3L リーフ JBJ-301 LEF

サーモス 真空断熱フードコンテナー 0.3L リーフ JBJ-301 LEF 0.3L リーフ JBJ-301 LEF

完全無欠生活の用語集

完全無欠生活を始める上で必要な用語をリストアップしました。

  • オーガニック
  • グラスフェッドビーフ
  • オメガ3
  • MCTオイル

オーガニック

有機農法で栽培された食品のことです。 畜産物は有機栽培された飼料を与えている場合のみ、有機畜産物となるようです。

「ナチュラル」「自然派」など類似した疑わしいキャッチコピーもあるため、 基本的に有機JASマークの食材を選ぶと良いと思います。

www.maff.go.jp

グラスフェッドビーフ

牧草肥育された牛肉のことです。 一般的に日本で流通している牛肉は穀物肥育の物がほとんどなので、見つけるのに苦労します。

ほとんど流通していない理由としては、牧草肥育されると固く赤身の多い肉になり、独特の臭いが出るため、日本人には好まれないのが原因のようです。 逆に穀物肥育されると柔らかくサシの入った臭いの少ない肉になります。

mgkitchen.jp

放牧で牧草を与えることで有名なオーストラリア産の牛肉も、最近では日本人に合わせて出荷前に穀物を与えているものが多いそうです。

そのため、グラスフェッドであることをきちんと確認しましょう。入手が難しければショートグレインの物を買うと良いと思います。

298now.jp

また、どうしても入手が難しい場合、国産のあか牛が代替となります。放牧され、牧草を多く与えられているようです。

www.akaushi.jp

オメガ3

DHAやαリノレン酸など、抗炎症作用を持つ不飽和脂肪酸の種類です。

ω-3脂肪酸 - Wikipedia

グラスフェッドビーフはオメガ3を豊富に含むらしいです。

MCTオイル

いわゆる中鎖脂肪酸を100%含むよう精製されたオイルです。 慣れていない時に大量に摂取するとお腹を壊しやすいので注意。

まとめ

完全無欠生活は自分にとってパフォーマンスを上げる食事を見つけることをゴールにしています。 体の炎症を減らしてパフォーマンスを上げ、脂肪を蓄積させないことで減量を促します。 お金が掛かるなどのデメリットもありますが、お財布と相談しましょう。 完全無欠生活を始めるには、良い食材を売っているスーパーを見つけること、お弁当箱を入手することが大事です。

私の場合、集中力が高まり、全身の倦怠感が減り、ベルトの穴が一つ締まるなどの効果がありました。

*1:ちなみに私の場合、全身が酷い倦怠感に襲われ、仕事に全く集中できなくなったため、すぐに完全無欠生活に戻しました

RMagickで画像のホワイトバランスを調整する

蛍光灯下で撮影された画像が緑っぽくなってしまうのを補正するために、RMagickでホワイトバランスを調整する手法を実装してみました。

手法

実装がシンプルなgray worldとretinexをRMagickを使って実装してみました。

qiita.com

上記記事のcolorcorrectと元の論文を参考に実装しています。

gray worldは「画像中の全画素の平均を取るとグレーになる」という仮説を利用しており、 retinexは人間の視覚特性をモデル化しているようです。

gray world

image = ImageList.new('image.jpg')

red_mean   = image.channel_mean(Magick::RedChannel).first
green_mean = image.channel_mean(Magick::GreenChannel).first
blue_mean  = image.channel_mean(Magick::BlueChannel).first

white_balanced_image = image
white_balanced_image = balanced_image.convolve_channel(1, [green_mean / red_mean], Magick::RedChannel)
white_balanced_image = balanced_image.convolve_channel(1, [green_mean / blue_mean], Magick::BlueChannel)

retinex

image = ImageList.new('image.jpg')

red_extrema   = image.channel_extrema(Magick::RedChannel)
green_extrema = image.channel_extrema(Magick::GreenChannel)
blue_extrema  = image.channel_extrema(Magick::BlueChannel)

red_max = red_extrema.last.to_f
green_max = green_extrema.last.to_f
blue_max = blue_extrema.last.to_f

white_balanced_image = image
white_balanced_image = white_balanced_image.convolve_channel(1, [green_max / red_max], Magick::RedChannel)
white_balanced_image = white_balanced_image.convolve_channel(1, [green_max / blue_max], Magick::BlueChannel)

感想

gray worldは蛍光灯下で撮影された画像を綺麗に補正することができましたが、「全画素の平均を取ったらグレーになる」という仮説を利用しているためか、文字入れなどの加工がされた画像には弱く、そのような画像では色味が変になってしまいました。

retinexは蛍光灯下で撮影された画像に対しては補正が弱めで緑っぽさが若干残りましたが、加工された画像に対しても色味を変えずに補正が可能でした。

使用する画像に合わせて手法を変える必要がありそうです。