SlideShare uma empresa Scribd logo
1 de 42
Baixar para ler offline
呪符式高速詠唱シェル芸 2
たいちょー
みなさん#!/bin/bash(こんにちはの意)
たいちょーです
twitter: @xztaityozx_001
GitHub: xztaityozx
好きな言語: C#, Go
職業: お嬢様系難読化シェル芸人
今回話すこと
呪符式高速詠唱シェル芸の精度を編集距離と誤認識テーブルを使ってあげてみた話
前回までのあらすじ
1. yukichantという文字列⇔呪文変換ツールがあった
$ echo シェル芸 | chant

羅の烙印を底より守る。沈み世界を呼び声の砕ける。引きを肉より災いを成り。守り。
2. 詠唱が難しいので前もって書いておくことにした
echo unko の呪文
3. OCRの気持ちになり切れず修行不足という結論にな
った
というわけで
いろいろ改善をしてきましたのでその話をしていきます
編集距離による補正をしてみる
編集距離とは
二つの文字列がどの程度異なっているかを表す距離のこと
具体的には片方の文字列をもう片方の文字列にするために行う 挿入 ・ 削
除 ・ 置換 の操作回数
編集距離の例
abc と abd の編集距離は置換が1回なので、1もしくは1/3=0.3333....
置換を挿入=>削除と考えて操作回数2回とする場合もある
編集距離とは
レーベンシュタイン距離ともいう
こっちのがカッコいいね
レーベンシュタイン距離による補正をしてみる
yukichant には辞書がある
辞書に登録されている言葉から割り当てされる
現れる言葉が決まっているので、距離の近い言葉が検索できる
計算量は、長さ n と長さ m の文字列を比較するとき となっている
n も m も高々6なので問題なし!ヨシ!
つまり、なんかできそうな気がする
送り仮名が間違ってるとき
似ているひらがなは間違われやすい(前回のLT参照)
正 誤
栄える 栄んる
編集距離は1。結構近いので補正してくれるかも
漢字自体が間違ってるとき
正 誤
消える 削える
「消える」との編集距離は1なので補正してくれそう。でも「削る」も編集距離は1
実装してみる
今の実装は以下のようになっています
1. 画像ファイルをOCRエンジンに渡す
2. OCRエンジンから読み取り結果をもらう
3. 読み取った文字列を yukichant に渡す
4. yukichant から解読結果をもらう
5. 解読結果をコマンドとして実行
ステップ2とステップ3の間にレーベンシュタイン距離による補正を入れていきます。
文字列切り出しの方針を考える
補正しますといっても、どうすればいいのでしょう
例えば echo unko の呪文をレーベンシュタイン距離を使って補正しようとするとしま
す
誘惑の邪気を魂魄借り。業火よ羅刹に星空の失え。血肉とともに果たせ。

当然比較相手が必要ですが、その相手はどう生成すればいいのでしょう?
呪文を切り分けてみる
長い呪文を直接比較することは困難です。
なので yukichant に登場する単語ぐらい短くなるように切り分けていきます
1. 形態素解析
文字列の解析といえば
今回は採用しなかった
読み取った呪文はめちゃめちゃになることがあり、だいたい1文字ずつ分割さ
れるため
2. 6,5,4,2,3の順番に先頭から切り出す
数字は yukichant に登場する単語の長さ
順番は登場頻度が小さい順
今回はこっち
レーベンシュタイン距離による補正の疑似コード
var input = "呪文";

var dictionary = { ... yukichantの単語辞書 ... };

while(input.Length > 0) {

var minDistance = 999;

var result = "";

foreach(var length in {6,5,4,2,3}) {

var subStr = input[..length];

// 同じ長さの単語群と切り出した文字列を比較

foreach(var word in dictionary[length]) {

// 距離が最小になるものを見つける。

// 距離が一緒なものが複数個あったときはどないしようかなあ

var distance = Levenshtein(subStr, word);

if(distance < minDistance) {

minDistance = distance;

result = word;

}

}

}

input = input[length..];

}
実際にやってみた
入力画像は
です。ここではOCRエンジンはTesseractを用います。
レーベンシュタイン距離による補正を入れる前
誘惟の那気を魂すら俸り楳火に雑の春と失え。血を果たせ。
入れた後
誘惑の邪気を魂すら祈り。業火に蟲の天と失え。血を果たせ。
ああ!なんか補正できました!!!
補正過程をみてみる
レーベンシュタイン距離での補正で割ともとの文字列に近くなりましたね。これがシ
ュタインズ・ゲートの選択ってこと?
似ている漢字の間違いを補正する
漢字の読み取り間違いを補正するのは難しいです。
似ていようが、似ていなかろうが操作回数1なので以下の二つの編集距離はともに
1
雑の => 蟲の
春と => 天と
文字列の長さがある程度あると補正が効きやすい
楳火に => 業火に
どうにか漢字を補正できないかな…
変換テーブルを定義すればええやん
漢字と似ている漢字のテーブル「誤認識テーブル」
「 刹 は 和 と 利 に似ている」みたいなことを表すテーブルを定義
似ている方に属すことができるのは呪文に登場しない漢字のみ
似ている方にある漢字が呪文に登場したら置き換える
漢字 似てる1 似てる2 似てる3
刹 和 利 祈
誤認識テーブルによる補正
候補が複数個あるとき
漢字 似てる
因 口
囚 口
困 口
口われる から 困われる , 囚われる , 因われる の3つを作ってレーベンシュタイン距離でさ
らに補正する
さっきの間違いは以下のようなテーブル定義があれば良い
漢字 似てる
雑 羅
春 星
楳 業
というわけで yukichant に登場するすべての漢字(548個)について、このテーブルを定
義できればさらに補正が…
できないッ…!!!
数が多すぎる。すべて思いつくのは
不可能です
思いつかないなら実際に誤認識させ
てみればいいよね
漢字の書き取り
548個の漢字を書いてOCRに食わせてみます
1回だと最高でも1つしか似ている漢字を見つけられないので10回ずつ書きま
す
そしてOCR結果からテーブルを作るってワケ。天才ね。
同じように書いても同じように読み取られるだけなので、ちょっとずつ変え
て書く
ちょっと平べったい
ちょっと長い
書き取り結果がこちら
こんなんを55枚書きました。正直これが一番キツかった。夏休みの宿題を思い出しま
した。
書いたら集計
1. 画像を1行ずつ切り出す
2. OCR(TesseractとWindows)で読み取る
3. 誤認識を取り出す
4. テーブルに書き込む
集計したら実装
レーベンシュタイン距離での補正をする前に誤認識テーブルでの補正をします
while(input.Length > 0) {

var minDistance = 999;

var result = "";

foreach(var length in {6,5,4,2,3}) {

var subStr = input[..length];

// 誤認識テーブルで補正を書けて候補を作る

var list = createAdjustedWords(subStr);

foreach(var item in list) {

foreach(var word in dictionary[length]) {

var distance = Levenshtein(item, word);

if(distance < minDistance) {

// ...

}

}

}

}

input = input[length..];

}
実際にやってみた
入力画像は同じく
です
というわけで
デモをします
# なんもなし

$ cd ~/source/repos/ofuda/cli-tesseract-ocr; dotnet run -- ../img/tegaki-yoko-2gyo.png --tesseractPath C:UsersxztaityozxAppDataLocalProgramsTesseract-OCRtesseract.exe

# レーベンシュタイン距離のみ

$ cd ~/source/repos/chant-gate/chant-gate; dotnet run -- ../../ofuda/tegaki-yoko-2gyo.png --ocr-engine Tesseract

# 誤認識テーブル+レーベンシュタイン距離

$ cd ~/source/repos/chant-gate/chant-gate; dotnet run -- ../../ofuda/tegaki-yoko-2gyo.png --ocr-engine Tesseract -c
なんもなし
誘惟の那気を魂すら俸り楳火に雑の春と失え。血を果たせ。
レーベンシュタイン距離のみ
誘惑の邪気を魂すら祈り。業火に蟲の天と失え。血を果たせ。
誤認識テーブル+レーベンシュタイン距離での補正
誘惑の邪気を魂すら借り。業火に羅の星と失え。血を果たせ。
ああ!直ってます!!
変換過程
というわけで
ライブコーディングをします。
今回はデジタル手書きです。今度こそ立派な魔術師に…。
まとめ
レーベンシュタイン距離と誤認識テーブルを使って読み取った呪文の補正に挑戦
しました
なんとか補正することができました
OCRの段階でめちゃめちゃになったものをどうにかするのはまだできない
そもそもできなさそう
書き取りめっちゃ大変だった。もうしない
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|

| 終 |

| 制作・著作 |

|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ |

| xztaityozx |

|_________|

∧∧ || 

( ゚д゚)|| 

/ づΦ

Mais conteúdo relacionado

Mais de xztaityozx

Mais de xztaityozx (17)

ワタナベシェル
ワタナベシェルワタナベシェル
ワタナベシェル
 
柿と杮
柿と杮柿と杮
柿と杮
 
難読化PowerShell芸入門
難読化PowerShell芸入門難読化PowerShell芸入門
難読化PowerShell芸入門
 
シェル芸をドット絵にして思いを伝えよう!
シェル芸をドット絵にして思いを伝えよう!シェル芸をドット絵にして思いを伝えよう!
シェル芸をドット絵にして思いを伝えよう!
 
終わりを出力するコマンドつくった
終わりを出力するコマンドつくった終わりを出力するコマンドつくった
終わりを出力するコマンドつくった
 
ワタナベ難読化シェル芸
ワタナベ難読化シェル芸ワタナベ難読化シェル芸
ワタナベ難読化シェル芸
 
~/.bashrcを難読化しよう!
~/.bashrcを難読化しよう!~/.bashrcを難読化しよう!
~/.bashrcを難読化しよう!
 
CLIツール作るの楽しい
CLIツール作るの楽しいCLIツール作るの楽しい
CLIツール作るの楽しい
 
レッツゴー難読化シェル芸
レッツゴー難読化シェル芸レッツゴー難読化シェル芸
レッツゴー難読化シェル芸
 
超・記号オンリー難読化シェル芸
超・記号オンリー難読化シェル芸超・記号オンリー難読化シェル芸
超・記号オンリー難読化シェル芸
 
部活でシェル芸がはやらない
部活でシェル芸がはやらない部活でシェル芸がはやらない
部活でシェル芸がはやらない
 
潜入工作任務用シェル芸
潜入工作任務用シェル芸潜入工作任務用シェル芸
潜入工作任務用シェル芸
 
ダブルシンク難読化シェル芸
ダブルシンク難読化シェル芸ダブルシンク難読化シェル芸
ダブルシンク難読化シェル芸
 
破壊的難読化シェル芸
破壊的難読化シェル芸破壊的難読化シェル芸
破壊的難読化シェル芸
 
みんなで!Base64難読化シェル芸
みんなで!Base64難読化シェル芸みんなで!Base64難読化シェル芸
みんなで!Base64難読化シェル芸
 
シェル芸で使いたくてLINQが使えるコマンドを作ったらawkでよかった話
シェル芸で使いたくてLINQが使えるコマンドを作ったらawkでよかった話シェル芸で使いたくてLINQが使えるコマンドを作ったらawkでよかった話
シェル芸で使いたくてLINQが使えるコマンドを作ったらawkでよかった話
 
難読化シェル芸
難読化シェル芸難読化シェル芸
難読化シェル芸
 

呪符式高速詠唱シェル芸2