Kasasagi’s memorandum

JavaとかProcessingとか。最近はAtcoderとか。

zaimAPIで作ったアプリをlambdaで動かした話

こんばんは、かささぎです。

最近家計簿アプリとしてzaimを使ってます。
https://zaim.net/

カテゴリの分類や予算の設定などができ、収入・支出などを見える化できます。

UIがシンプルで使いやすかったり、撮影したレシートを自動で登録してくれる機能があったりと、なかなか気に入っています。(課金もしました)

そしてもう一つ、zaimにはWeb APIが提供されているというメリットがあります。

レシートのCRUDの機能が備わっているため、各々が思うような家計簿を作ることができます(エンジニアなら)。


今回はzaim appをpythonで作成し、AWS lambdaのラムダ関数として登録して定期実行させることにしました。

順を追って説明していきます。

作るアプリ

今回はzaim appのHello world として、外税を内税に変換する簡単なアプリを作りました。

zaimでレシートを記録していて気づいたのですが、レシートには内税で計算されているものと外税で計算されているものの二つが存在します。

zaimでは収支をカテゴリに分けて記録しているので、外税だと扱いが大変です。


例えば以下の例

商品1 1000円 カテゴリA
商品2 4000円 カテゴリB
外税 400円 カテゴリ?
合計 5400円

このようなレシートは正確には以下のように外税を分割して登録すべきです。

商品1 1080円 カテゴリA
商品2 4320円 カテゴリB
合計 5400円

あるいは

商品1 1000円 カテゴリA
商品2 4000円 カテゴリB
外税1 80円 カテゴリA
外税2 320円 カテゴリB
合計 5400円


しかしこれを手動で登録するのは面倒です。

そこで外税カテゴリに登録した外税を自動的に内税に変換させるappを作ることにしました。

zaim api

zaim apiを使うにはZaim Developers Centerからアプリの登録を行います。
https://dev.zaim.net/

f:id:yh9092:20190623174128p:plain

今回はクライアントアプリで作りました。
アクセスレベルには全チェックを入れました。

登録するとIDとシークレット、そして各種URLが発行されます。


APIの使い方はREAT APIの項に情報があります。

情報は全部英語ですが、わかりやすいつくりをしているのでなんとかなりました。

アクセストークンの取得

以下のページを参考にさせていただきました。

https://qiita.com/kosystem/items/7728e57c70fa2fbfe47c

access token と access token secretが発行されます。
これらのパラメータは.envファイルに記述します。

Main.py

メインの処理はこのファイルです。

まずoauth認証を行います。

処理は「昨日の登録データ」に対して行います。

日付をパラメータとしたget_dict_data関数でGETメソッドを用い辞書データとして取得します。


convert_receipt_dict関数では扱いやすいデータに変換してます。

receipt_dictには複数のレシートのリストが格納されます。

それらからfor文で一つずつ取り出して処理していきます。


get_amounts関数ではレシート内のそれぞれの商品の課税対象額と外税の額を取得します。

外税カテゴリにデータがない場合はoutside_taxが0となるので、ここでcontinueします。


そしてこの値をもとにcalc_addition関数で加算額を決定します。

調整前後で金額に差が出ないようにいろいろ処理してます。


その後create_update_receipt関数で新しいレシートデータを作り、update_data関数で登録しています。

u["amount"]が負なら金額が負の外税処理を省いたデータなので処理を行いません。

0のデータは外税の金額を入れていたデータなので、DELETEします。

正のデータは新しい金額にUPDATEします。

実行結果

こんな感じになります。

変更前↓
f:id:yh9092:20190623202422j:plain

変更後(プログラム実行後)↓
f:id:yh9092:20190623202438j:plain

AWS lambdaでの実行

AWS lambdaはAWSのサービスの一つで、サーバレスなコンピューティングサービスです。(カタカナ語を使えばいいと思ってる)

簡単に言えば必要な時だけサーバが立ち上がって、アプリケーションなどを実行できるサービスです。

AWS lambdaの操作については省略します。

コードはlambda_function.pyを作成し、lambda_handler(event,context)関数からmain関数を呼び出します。

注意しなければならないのは、zipファイルにする際に外部モジュールを読み込ませる必要があることです。

参考↓
https://hacknote.jp/archives/48083/

以下のコマンドで読み込ませることができます。

pip install --target <library> <path>

追加したフォルダは.gitignoreに追加して、gitによる管理から外します。


1.5MB程度のzipファイルの保存に1分近くかかったんですが、なぜでしょうかね?

いくら回線が遅いとはいえさすがに…って感じです。

10MB以上はS3を推奨、とあるように、なんらかのチェックなどがあってzipファイルでのアップロードは時間がかかるのかもしれませんね。

cron処理

cronにはCloudWatch Managementを利用します。

ルールから、トリガを設定します。

トリガの設定はLinuxのcronとやや違うので注意が必要です。

またリージョンが日本でも、グリニッジ標準時だったりするので、そこにも注意が必要です。

1日1回の定期実行なので、(おそらくzaimを触らない)午前3:00にトリガを設定しました。

実行され、こんな感じのログが残れば成功です。

f:id:yh9092:20190623205044p:plain

しかしトリガ設定ではGMTで、残るログはUTCなのはなんとかなりませんかね。。。

感想

クラウドサービスの利用は初めてでいろいろ苦戦しましたが、何とか動かすことができました。

zaimAPIを活用して、自分が使いやすい家計簿アプリに改造していきたいと思います。


それでは。

PCを組んだ(組んでもらった)

お久しぶりです。かささぎです。

就職したりなんだりといろいろあって全く更新できていませんでした。

とりあえずひと段落したので、これから少しずつ書いていきたいと思います、


今回はデスクトップPCを組んだ話をします。

一人暮らしになり、家につよいPCが欲しくなって購入することになりました。

はじめはdellBTOのものを買うつもりでしたが、最近自作が安く組めると聞いて調べることにしました。

すると、メモリやSSDの価格がかなり落ちていて、自作で安く組めることがわかりました。

という経緯で自作することになりました。

ちなみに私は自作PCについて詳しくありません。

これからの解説も適当ですがご容赦ください。

予算

予算は周辺機器やデスク・チェアなど全部まとめて20万にしました。

夏のボーナスをつぎ込んで買う形です。

ちなみにボーナスの支給日は6月末です。どうもありがとうございました。

予算はとりあえず本体が15万、周辺機器が3万、デスクとチェアがそれぞれ1万に割り振りました。

購入ショップ

PCパーツは基本的に店頭よりネットのほうが安いので、ほぼネットで購入しました。

PCケースやマウス・キーボードなどはあらかじめ見たり触ったりしておきたかったため、秋葉のヨドバシに行ったりしてました。

ちなみにヨドバシのポイントの還元率を考慮すると、ネットより安くなる可能性もあります。

ネットでの購入には価格.comをフル活用しました。

最終的に以下のショップで購入しました。

  • NTT-X store  ……… CPU,メモリ,SSD,グラボ,モニター
  • Amazon ......... PCケース,マウス,キーボード
  • ソフマップ(ネット) .......... マザボ,CPUファン,電源
  • ヨドバシ(店頭)  .......... マウスパッド,無線LAN子機
  • 楽天  ......... チェア, デスク
  • HARDOFF ......... 電源タップ

NTT-X storeは定期的にセールをやっており、5000円引きとかのクーポンが配られるため、価格の最安ショップより安いことがあります。

Amazonとソフマのパーツは価格の最安でした。

この二つのショップはペイジーでも払えるため、クレカ上限額に引っかかった私を救ってくれました。

電源タップはHARDOFFやセカストでよく安く売ってるのでおすすめです。

パーツ紹介

構成はこちらです。 
http://niku.webcrow.jp/

それでは一つずつ紹介していきます。

CPU

Ryzen 7 2700

intel派とAMD派で宗教戦争が起こるところですが、私は特にこだわりがなかったためコスパで選びました。

グラボ

NVIDIA GEFORCE RTX2070 VENTUS 8G

グラボは価格とスペックが高相関だそうで、強そうなのにしました。

メモリ

ADATA DDR4 PC4-21300 16GB *2

メモリは32GB搭載することにしました。
メモリは容量以外の違いがよくわからないので、DDR4で一番安かったNTT-X storeのやつにしました。

SSD

ADATAUltimate SU630 ASU630SS-960GQ-X

HDDは積まず、SSDのみにしました。
少し前まではSSDはかなり高いイメージでしたが、今は960GBで10000円を切るほどの安さでした。
日本の半導体業界に一抹の不安を覚えながらもポチりました。

マザーボード

ASRockB450 Steel Legend

よくわからなかったので、友達にお勧めされた奴にしました。

電源

ThermaltakeToughpower Grand RGB 850W Gold PS-TPG-0850FPCGJP-R

よくわからなかったので、友達にお勧めされた奴にしました。
なんか光ってかっこいい。

CPUクーラー

サイズ 虎徹 MarkII SCKTT-2000

よくわからなかったので、価格1位にしました。

ケース

NZXTH500 CA-H500B-BL

ヨドバシでNZXTのケースを見て、シンプルでいいなーってなってこれに決めました。
ただ電源ボタンがLEDで光らなかったのが少し残念です。

マウス・キーボード

マイクロソフト キーボード マウスセット Wireless Desktop 3050
https://www.amazon.co.jp/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%BD%E3%83%95%E3%83%88-%E6%9A%97%E5%8F%B7%E5%8C%96%E6%A9%9F%E8%83%BD%E6%90%AD%E8%BC%89-Wireless-Desktop-PP3-00028/dp/B017X1CKW4/ref=dp_ob_title_ce

ヨドバシでキーボードを触って、これが結構しっくりきたのでえらびました。
マウスはLogicoolの二万ぐらいのがよかったのですが、予算オーバーだったのでとりあえず保留してこれを使ってます。

モニタ

ビューソニックジャパン 31.5型ワイドモニター WQHD IPSパネル VX3276-2K-MHD-7
https://nttxstore.jp/_II_VS15922219

でかいモニタがいいなーってなって31.5型のにしました。
安さで選びましたが、普通にきれいで満足しています。
個人的には4Kとか8Kは過剰で、WQHDで十分だと考えてます。

デスク

https://item.rakuten.co.jp/low-ya/f802-g1024-100/?s-id=ph_pc_itemname

31.5型のモニタを置くなら奥行き60じゃ近すぎるかな…ってことで120*70のにしました。
このデスクには電源タップを置く場所があって便利です。
このデスクはかなり気に入っています。組み立てが難しかったけど。

チェア

https://item.rakuten.co.jp/tansu/65090110/?s-id=ph_pc_itemname

頭置くとこがあってメッシュのチェアって条件で探しました。
楽天のレビューとかを見て選びました。
安いだけあって作りが雑でしたが、まあ普通に使えるので及第点です。


組み立て

組み立ては全部友達にやってもらいました。

東京での寝床提供と昼飯のハヤシライスで手を打ちました。

高専の授業で一応組みたてたことはあったのですが、まあ覚えてないよねってことで、完全に託しました。

2~3時間で作ってくれました。ありがとう。

完成

f:id:yh9092:20190609120234j:plain

感想

今のところ問題なく使えています。

BTOとかだと同じ価格でも結構低いスペックだったと思うので、自作にして正解でした。

あとはWiMAXの回線速度との闘いです。助けてくれ。


それでは。

卒論をTeXで書いた話とファイル分割について

こんにちは、かささぎです。

なんだかんだ今年初めての記事です。
1月,2月と卒論が忙しく、書く暇がありませんでした。
とりあえず無事完了しましたので、ちゃんと卒業できそうです。


今回は、卒論を書く際に使用したTeXについて紹介したいと思います。

TeXとは

TEX(TeX; テック、テフ)はアメリカ合衆国の数学者・計算機科学者である
ドナルド・クヌース (Donald E. Knuth) により開発されている組版処理システムである。
-Wikipedia

文章作成を行えるソフトの一つで、スタイルなどをマークダウンで記述します。

TeXのメリット&デメリット

文章を作成する際によく用いるソフトとしてWordがあります。
ここでは私がTeXを利用したうえで、Wordと比較して感じたメリット・デメリットを記述します。

  • TeXを使うメリット
    • 綺麗な文章を作成できる
    • 目次や参考文献のリストを簡単に作成できる
    • 図や表、参考文献の番号を自動で割り振ってくれ、参照も簡単にできる
    • 好きなエディタで作成できる
    • バージョン管理がしやすい
    • 数式をきれいに書ける(最近のWordではLaTeXで記述できるみたいです)
  • TeXを使うデメリット
    • 図や表の導入が複雑
    • pdf変換に時間がかかる
    • TeXの実行エラーの内容がわかりにくい

今回の論文を書く場合では文章量がとても長くなったため、スタイルを統一できたり図番号・表番号を自動的に振ってくれたりする機能がとても役立ちました。

TeXを使うのは(ほぼ)初めてでしたが、そこまで苦労せずに使えました。特殊文字や表の配置は知らん

TeXはテキストファイルなので、自分の好きなエディタで書くことができます。

私はSublime Text3にSumatraPDFをインストールして使いました。
参考文献 → SublimeText3でUTF-8のLaTeX環境を構築する(Windows) - Qiita

Sublime Text3は日本語に弱いのであまりお勧めしません。VScode辺りを使ったほうがいいと思います。

TeXでは書いたコードをpdfに変換して文章にしますが、その変換に時間がかかるという問題があります。特に画像の処理に時間がかかるみたいです。

そこで、今回は文章を細かく分割する方法を取りました。その解説をしていきます。

LaTeXで文章の分割

1つのtexファイルに文章を全て記述すると、pdfの変換に時間がかかってしまいます。
完成版を作成する際には必要ですが、執筆中は基本的に記述した場所のみを確認できればいいと思います。

これを実現するために、texファイルを分割するという方法があります。
こうすることで変換スピードを上げ効率的に作業できたり、ファイルの行数を減らして管理しやすくしたりできます。

卒論ではセクションごとに別のファイルにして管理しました。

コードはこんな感じです。



gista2624c50f081407063101457d3a9e549
gist8e6cb9102d566b7889c1ff2da2d47188

thesis.texが全体をまとめるファイルです。abstract.texはその要素の一つのtexファイルです。

abstract.texやtitle.texなどのファイルをthesis.texと同じフォルダに入れ、\include{abstract} 等とすることで呼び出すことができます。

abstract.tex単体でも実行でき、そのファイルに書かれている内容だけのpdfが生成されます。

注意点としては他ファイルとの相互参照(\ref ・\label)ができないことがあります。
こればかりはどうしようもない(と思う)ので、thesis.texを実行して確認する必要があります。

感想

TeXを使ったのは初めてでしたが、スタイルを簡単に統一したり相互参照が簡単にできたり気に入りました。

私は卒業後就職するのですが、企業ではたぶんWordばっかり使うことになると思うので少し悲しいです。

TeXのメリットとしてバージョン管理(Git)がしやすいというものがありますが、今回はほとんど使わなかった(commitとpushくらい)ので、軽く勉強したいと思います。


それでは。

Intellij IDEAでJava + Processing

こんばんは、かささぎです。

今回はJava + Processingというテーマで書いていきます。

主にProcessingユーザーをターゲットにしています。


Java + Processing のメリット

Processingは簡単なコードでGUIを実現できるというメリットがあります。
そのため、電子アートやプログラムの入門に用いられることが多いです。

しかし、ある程度発展したプログラムを作成しようと思った時に、弊害が出てきます。

例えば厳密なオブジェクト指向ができない点があります。
これはProcessingではプログラム実行時、最初に呼ばれる関数(void setup() やvoid settings())をクラス内に入れることができなかったり、カプセル化ができない等です。

他にも、Processing向けのライブラリが少ないことが挙げられます。Java向けのライブラリ(jarファイル)を外部ライブラリとして利用することもできますが、例外処理などで一部Processingのコード通りにかけなかったりなど、利用するのは難しいと思います。

また、ProcessingのIDEでは、実行からコンソール、デバッグツールの管理などまで一応GUIで利用できるのですが、ファイルツリーなどはなく、やはりよく用いられるIDEと比べると機能が劣っているといえます。

これらを解決するためにJavaからProcessingをライブラリとして呼び出す、という手法があります。

そうすれば厳格なオブジェクト指向ができますし、多彩なJavaライブラリも利用できます。
Javaのみで書くより非常に簡単にGUIを作成できるというメリットもあります。

また、Javaが利用できるIDEを用いてゴリゴリ大規模開発もできます。


Intellij IDEA

Java + Processing ではIDE(統合開発環境)を用いて開発するのをおすすめします。

IDEとはコンパイラインタプリタデバッグツールなどをひとまとめにした環境のことです。

Javaの開発にはEclipseIntellij IDEA,NetBeansなどがよく用いられますが、今回はIntellij IDEAを用います。
https://www.jetbrains.com/idea/

コード補完能力が高い、プラグインが豊富、デザインが現代風などの特徴があります。

無償版でも十分に利用できます。また、学生はメールアドレスの登録で有料版が無料で利用できます。



解説

今回の解説はIntellij IDEA,Processingどちらもダウンロード済みという前提で進めます。

またWindows環境で行います。


プロジェクトの作成

Intellij IDEAを立ち上げると、こんな感じの画面になると思います。

f:id:yh9092:20181216205624p:plain

Create New Projectをクリック。

新しいプロジェクトの設定画面が立ち上がります。

フレームワーク等は用いないのでNext,テンプレートも用いないのでNextを押します。

するとこんな画面になります。

f:id:yh9092:20181216205750p:plain

Project Nameを入れ、プロジェクトファイルの格納場所を変えたかったら好きな場所にします。
Project NameはJavaの慣習的に、最初の一文字を大文字にしておいたほうがいいみたいです。
今回はP5demoというプロジェクトにします。

OKを押すとIDEが立ち上がります。
f:id:yh9092:20181216210003p:plain

次にソースコードを書くファイルを作成します。
プロジェクト名の横の▽を押し、srcを選択します。
右クリックして、New -> Java Classを選択します。

Nameにproject名(今回はP5demo)を入れOK。
このファイルはJavaで書くものにします。

次にもう一度同じ要領でJava Classを作成します。
このファイルはProcessingを書くものにします。
今回はGUIbyP5というファイルにしました。

ファイルはこのように配置できていればOKです。
f:id:yh9092:20181216210450p:plain



ライブラリの設定

次にProcessingをライブラリとして設定します。

メニューバーから、File -> Project Structureを選択。
左にあるLibrariesを選択。このような画面になります。

f:id:yh9092:20181216210833p:plain

  1. を押してjava を選びます。

ファイル選択で、processing-x.x.x(バージョン)/core/library/core.jar を指定しOKを押します。

こんな感じになったら、成功です。OKを押します。
f:id:yh9092:20181216211103p:plain


これで環境の設定は完了です。


ソースコード・実行

P5demo.javaはこのようにします。

import processing.core.PApplet;

public class P5demo extends PApplet{

     public static void main(String args[]){
        PApplet.main("GUIbyP5");
    }

    //ここはJavaで書ける
}

GUIbyP5は円をたくさん描画するサンプルにしてみました。こんな感じです。

import processing.core.*;

public class GUIbyP5 extends PApplet{
    //ここはProcessingで書ける

    public void settings(){
        size(600,600);
    }
    public void setup(){
        ellipseMode(CENTER);
        colorMode(HSB);
        noStroke();
        background(0);
    }
    public void draw(){
        if(frameCount % 500 == 0) background(0);
        fill(random(360),100,100,60);
        ellipse(random(width),random(height),100,100);
    }

}

気を付けなければならないのはsize関数の位置です。
Processing標準IDEではvoid setup()内でsize()関数を呼ぶことが多いと思いますが、外部IDEの場合はvoid settings()という関数を作ってその中に記述する必要があります。
Processing標準IDEでも後者の書き方はできるので、この書き方をする癖を付けたほうがいいと思います。

次に実行です。
Build->Builde Projectでビルド(コンパイルみたいなもん)します。

ビルドが終わったら、Runを押し、P5demoを選ぶと実行されます。

このP5demoの選択は初回実行時のみで、その後はRunを押すだけで実行できます。

Processing では実行ボタンだけで実行できていましたが、IDEでは、ビルドしてから実行する必要があります。

<実行結果>
f:id:yh9092:20181216211910p:plain



まとめ

Java + Processingという手法を説明していきました。

この方法を用いればProcessing のみではできないことも、Javaの力で解決することができます。

また紹介した方法ではJavaのコードとProcessingのコードをきっちり分割することができるので、難解なコードになりにくくおすすめです。

ぜひこの手法でProcessing沼に堕ちてください。


それでは。

らりょすをビスケットに焼き付けた話

この記事はらりょすAdvent Calendar の14日目の記事です。

誰ですか?

鬼の手下です(伝わるか?)


らりょすさん

高専界隈で著名なのでTwitterをフォローしたら、フォロバしてくれたのでいい人なんだと思います。

そこにいるわけでもないのに、#procon28 や #procon29 の会場で「らりょす」というフレーズを何度も耳にしたので、とても有名人なんだと思います。

去年のAdvent Calendarを観てておもしろかったので、今年は書かせていただくことにしました。


本題

高専祭でビスケットに3Dプリンターで絵を焼き付けるという展示がありました。

ビスケットもクッキーも本質は一緒だろということでらりょすさんを焼き付けることにしました。


データの作成

ビスケットに焼き付けるには、線のデータを作成する必要があります。画像処理を用いて解決することにしました。PythonOpenCVを利用します。

ソースコード

import cv2

im = cv2.imread('img/raryosu.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

img = cv2.medianBlur(imgray,5)
_,thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_,contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

imfig = cv2.drawContours(im, contours, -1, (0,255,0), 1)

cv2.imwrite('raryosu_bin.png',thresh)
cv2.imwrite('raryosu_edge.png',imfig)

2値化には大津アルゴリズムというものを用い、閾値を自動的に決定しています。
あとは輪郭を検出して、描画している感じです。

実行結果はこちら。

f:id:yh9092:20181209135118p:plainf:id:yh9092:20181209135955p:plain

うまくいってませんね。
どうやら元画像の明るさが均一でないため、2値化がうまくいかなかったようです。
そこで、次の手法をとることにしました。


適応型閾値処理

画像を小領域に切り分け、領域ごとに閾値を計算する手法です。

ソースコード

import cv2

im = cv2.imread('img/raryosu.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

img = cv2.medianBlur(imgray,5)
thresh = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
_,contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

imfig = cv2.drawContours(im, contours, -1, (0,255,0), 1)

cv2.imwrite('raryosu_bin.png',thresh)
cv2.imwrite('raryosu_edge.png',imfig)

領域ごとに光源の強さが変化するような画像では、この方法で良い結果が得られます。
実行してみます。

<実行結果>
f:id:yh9092:20181209140847p:plain

ということで、モダンアートの完成です。

おわり















ません。

入力画像を使いやすそうなコラ画像にして実行すると、こうなりました。(2次利用してごめんなさい)

f:id:yh9092:20181209141310p:plainf:id:yh9092:20181209141317p:plain

ということで、これで完成とします。

あとはsvg形式に変換して、3Dプリンターに投げると、自動で印刷してくれます。


結果

思ったよりオリジナルっぽくなりました。
らりょすさんの反応はこちら。

ちなみにビスケットはちゃんと割ってからいただきました。


明日はco_rantan1131さんの記事です。

それでは。

PyCharmでSublime Textの右側のアレを導入する

こんばんは、かささぎです。

私はSublimerなのですが、特に気に入っている点として「コレ」があります。
f:id:yh9092:20181210190757p:plain

コードの全体像をなんとなく把握できるので好きです。

いろいろあってPyCharmを入れたのですが、ここでも「コレ」があったら便利だなと思い、導入したので方法をまとめます。


方法

"CodeGlance"というプラグインを入れます。
ちなみに、「コレ」は”minimap”という名前らしいです。
"minimap"と検索してもHitします。

  1. File -> Settings
  2. Plugins -> Browse repositories
  3. 左上で CodeGlance と検索し、install
  4. IDEを再起動

これで導入できます。結果はこちら。
f:id:yh9092:20181210190855p:plain


Sublimeではコードを画像にしてそれを縮小表示した感じですが、PyCharmでは背景色を付けるタイプのシンタックスハイライトをいい感じのサイズにして表示、という感じ(説明が難しい)です。
でもこちらはこちらで気に入りました。

スクロールもSublime Text同様、いい感じに動いてくれます。

今回はPyCharmで試しましたが、JetBrains 社製の他のIDE(Intellij Idea, RubyMine等)でも同じ方法で導入できるはずです。

Sublimerのみなさんは試してみてください。


それでは。

サイゼリヤの間違い探しを画像処理で解いてみた

この記事は高専 Advent Calendar 2018 - Adventar の 5日目の記事です。

昨日はnamachan10777さんの「キーボードを作る話し」でした。
OpenSCAD with clojure - エリマキトカゲになりたい

関数型言語使いこなせててすごい。。。私は???って感じです。

こんにちは、かささぎといいます。高専Advent Calendarを書かせていただきます。

自己紹介

・学校    石川工業高等専門学校
・学年,学科 電子情報工学科 5年
Twitter   @hrt9092

 宗教
 ・OS      Windows10
 ・エディタ   SublimeText3
 ・言語     Java,Processing,Python,Rubyあたり
 ・IDE      Intellij Idea
 ・きのたけ   たけのこ
 ・唐揚げレモン かける派

#procon27 ~ #procon29に参加し、人力でパズルを並べたり、人力でパズルを並べたり、競技アイデア募集企画ってので優秀賞をいただいたりしてました。

本題

私は画像処理系の研究室にいるのですが、自分の研究では本格的な画像操作を行っておらず、なにかやりたいなーと思ってました。

そこでAdvent Calendar に合わせてなにか作ってWrite UP しようと思い、間違い探しを解かせてみることにしました。
間違い探しは、サイゼリヤのキッズメニューについてくるものを利用させていただきました。こちらのHPに問題があります→エンターテイメント|サイゼリヤ

サイゼリヤの間違い探しを画像処理で解くという試みには、先行研究(研究か?)がありました。こちらの方の記事を参考にさせて頂きました→河本の実験室: サイゼリヤの間違い探しが難しすぎたので大人の力で解決した

OpenCVが使えれば世の中の大抵の問題は解決できる。

格好いいですね。

環境

・OS     Windows10
・言語    Python 3.6.5rc1
・ライブラリ opencv-contrib-python 3.4.2.16

本当はRubyでやってみたかった(Pythonでは一応経験があったため)のですが、Windows+Ruby+OpenCVの相性がクソゴミだったので、断念しました。

開発中にOpenCV4がリリースされたのですが、よくわからなかったのでアップデートしてません。

また後述のSIFTアルゴリズムを用いるため、拡張モジュールを含むcontribを入れました。
よくわかりませんが、商用利用が面倒くさいみたいです。

解説

プロジェクトはGitHubに置きました→https://github.com/hiroto3432/matigaisagasi
main.pyが実行ファイルで、solver.pyのクラスやメソッドを呼び出します。

ソースコードは載せるととても長くなるのでここには載せません。GitHubのコードを見てください。

解説にはこの画像を利用します。
f:id:yh9092:20181125113413p:plain

画像の分割

ただ単純に半分で分割すればいいと思っていたのですが、余白のサイズや、左右それぞれの画像のx座標の開始位置が問題画像によってバラバラだったので、自動で検出させることにしました。

手法としては、

  1. とりあえず半分で分割
  2. 分割した2枚の画像から、SIFTアルゴリズムで特徴点マッチング
  3. マッチング結果から、分割すべき画像の横の長さと余白の大きさを求めトリミング

という感じです。

特徴点マッチングとは、2枚の画像のこことここが同じだよーというところを検出することです。
これには、SIFT,SURF,AKAZEといったアルゴリズムOpenCVに用意されています。
こちらを参考にさせて頂きました→OpenCV(Python)で物体認識、特徴抽出(SIFT、SURF、A-KAZEの使い方)

自分で試してみた結果、AKAZEよりSIFTのほうが精度が高い(SURFはよくわからないけど処理が終わらずPCが悲鳴を上げた)ということで、SIFTを利用します。

マッチング結果から、y座標が同じものを描画したものがこちらになります。
f:id:yh9092:20181125112358p:plain

マッチングした点の左の画像と右の画像それぞれのx座標の差分から、余白のサイズと画像の横の長さを求めることができます。

実際はすべてのマッチング結果が同じ値を示すことはないので、結果を辞書に格納していって多数決で求めました。

分割結果はこんな感じです。

f:id:yh9092:20181125113123p:plainf:id:yh9092:20181125113137p:plain

背景差分

次に背景差分というのを取ります→背景差分 — OpenCV-Python Tutorials 1 documentation

cv2.bgsegm.createBackgroundSubtractorMOG() というので簡単にできます。しかしめちゃくちゃ長い名前のメソッドですね。

差分画像はこのようになります。
f:id:yh9092:20181125113859p:plain:h400

白いところが間違いになってますね。

オブジェクト検出

次に差分画像から、オブジェクト検出で差分の領域を取得します。
cv2.findContours()メソッドで簡単に取得できますが、この取得して得られたものをすべて描画するとこのようになります。
f:id:yh9092:20181125114654p:plain:h400

大きな領域の中に小さい領域がたくさん含まれてしまいます。
これを防ぐために、他の領域に包含される領域は描画しないようにしました。

結果

このようになりました。
f:id:yh9092:20181125115015p:plain

ひとつの間違いが複数の領域に分割されているのもありますが、なかなかよい結果になったのではないでしょうか。

ちなみに検出できたのは9つで一つ足りません。これは左上の”Kids menu"のiの一画目が丸いか四角いかという細かな違いなのですが、ノイズとして除外してしまったようです。

ついでにもう一つの画像の結果です。

元画像
f:id:yh9092:20181125115758p:plain
検出結果
f:id:yh9092:20181125115822p:plain

ところどころ誤検出されてますね…。ノイズとの兼ね合いが難しいです。

まとめ

画像処理では間違っている部分の表示は簡単でしたが、その領域を綺麗に検出することは難しかったです。

OpenCVの様々な技術を用いたので、とても勉強になりました。

OpenCVはほかにも、3次元復元や動画解析、機械学習などができ、とても楽しいです。
Pythonの他にもC++Java等でも利用できるので、ぜひ試してみてください。

みんなで堕ちよう画像処理沼!


明日6日目はsei0oさんの「たのしい潮寮生活 2」です。
高専 Advent Calendar 2018 - Adventar
私は通生なので詳しくありませんが、寮生がゴミ回線と虚無な飯と点呼によって精神を病むのは全国共通なんですかね?うちがひどいだけ?


それでは。


p.s.
12/22の高専カンファレンス in 名古屋 2018に参加するので、仲良くしてください。