pykakasiとMeCabを使ってモールス信号変換器を作る
CSGAdventCalendar 9日目 最近ラズパイを使ってモールス符号変換器を作ったので、備忘録。
概要
入力した文字列をモールス信号に変換、それをRaspberry PiのLEDを光らせて遊びました。 その際にpykakasiとMeCabを使ってアルゴリズムを組んだので備忘録です。 Githubのリンクも載せておきます。 環境はMac, python3.5.2です。
モールス信号とは
文字や記号を表象する方法のひとつ。電信による伝達を目的として発明され、短点とその3倍の長さを持つ長点の組み合わせにより文字や記号を表す。ラテン文字を基礎とした国際モールス信号の他、和文モールス信号のように各国の文字に対応したモールス信号が考案されている。
みなさんご存知SOS
のあれです。
日本語やアルファベットを「トン」「ツー」の二つの記号で表すことができます。
そんなモールス信号にもいくつかのルールがあります。
- 長点1つは短点3つ分の長さ
- 文字と文字の間には短点3つ分をあける
- 単語と単語の間には短点7つ分あける
この他にもSOS
は例外的に連続して打つなどルールはありますが、
今回は上記の3つをルールを中心にしていきます。
やるべきこと
目標は日常的にSNSで書いている文章をモールス信号に変換できるようにすることです。 そのためにはやるべきことがいくつかあります。
- 漢字をひらがなにする(漢字は変換できない)
- pykakasiを使って変換する
- 自動的に単語で区切る(普通文章を書くときに単語では区切らない)
- 変換のための条件分岐をひたすら書く
pykakasi
pykakasiは日本語の漢字仮名交じり文を平仮名やローマ字綴りの文に変換するプログラムKAKASI
のPythonバージョンです。
pipでインストールしてください。
$ pip install six semidbm $ pip install pykakasi
私は下記のように使いました。 setModeの引数で変換の形を決めることができます。
from pykakasi import kakasi pic = "本日は晴天なり" ... ... ... k = kakasi() k.setMode("K", "H") # カタカナをひらがなに k.setMode("J", "H") # 漢字をひらがなに conv_k = k.getConverter() pic = conv_k.do(pic) print(pic) # ほんじつはせいてんなり
インストールや使い方は公式のリポジトリに載っています。
MeCab
MeCabはオープンソースの形態素解析エンジンです。 Mecabを選んだ理由は下記の二つです。
MeCabを使い、入力された文章を自動で単語に区切ります。 (正確にはMeCabは文章を形態素で区切るので、単語では区切りません。) インストールはMeCab本体とその辞書、そしてPythonでバインディングしたライブラリを入れます。
$ brew install mecab #本体のインストール $ brew install mecab-ipadic #辞書のインストール $ pip install mecab-python3 #ライブラリのインストール
実際には下記のように使いました。
import MeCab pic = "本日は晴天なり" try: m = MeCab.Tagger("-Owakati") pic = m.parse(pic) pic = pic.strip() # 先頭と末尾の空白を削除 pic = pic.replace(' ', '_') # 単語間に開けた空白を変換 except RuntimeError: pic = "" print(pic) #本日_は_晴天_なり
こちらは「MeCab (和布蕪)とは」と「Python3からMeCabを使う」が参考になりました。
実際に使ってみる
上記のpykakasiとMeCabを使った変換器が下記のコードになります。
import morse
はWeb上にあったモールス信号のコンバータを改変したものです。
コードはこちらにあります。
# coding:utf-8 from pykakasi import kakasi, wakati import MeCab import morse def convert(pic): pic = ''.join(pic.split()) # 空白の削除 # MeCabによる形態素解析 try: m = MeCab.Tagger("-Owakati") pic = m.parse(pic) pic = pic.strip() # 先頭と末尾の空白を削除 pic = pic.replace(' ', '_') # 単語間に開けた空白を変換 except RuntimeError: pic = "" # pykakasiによるカタカナ・漢字のひらがなへの変換 k = kakasi() k.setMode("K", "H") # カタカナをひらがなに k.setMode("J", "H") # 漢字をひらがなに conv_k = k.getConverter() pic = conv_k.do(pic) context = "" for c in pic: context += c + "~" context.strip() ans = "" for c in context: ans += morse.s2m(c) return ans
これを下記のように実行させます。
import call txt = "本日は晴天なり" txt = call.convert(txt) print(txt)
すると下記のようにちゃんと変換できているのがわかります。
-・・ ・-・-・ --・-・ ・・ ・--・ -・・・ ・---・ ・- ・-・-- ・-・-・ ・-・ --・
後は、文字列で条件分岐をして光らせるなり音を鳴らす等すれば、完成です。
RaspberryPi LED発光のサンプル
import RPi.GPIO as GPIO import time import call # それぞれの処理の秒数 dot = 0.33333333 # トン stick = dot*3 # ツー space = dot*3 # 空白 between_sleep = dot/3 #「トン」と「ツー」の間の時間 txt = "本日は晴天なり" # 光らせる def light_up(sec): GPIO.setmode(GPIO.BCM) GPIO.setup(23, GPIO.OUT) GPIO.output(23, GPIO.HIGH) time.sleep(sec) GPIO.cleanup() # 光らせない(何もしない) def light_down(sec): time.sleep(sec) pass for c in call.convert(txt) if c == '・': light_up(dot) #1拍点灯 if c == 'ー': light_up(stick) #3拍点灯 if str[num] == ' ': light_down(space) #3拍消灯 time.sleep(between_sleep)
まとめ
kakasiやMeCabといった既存の変換器を使うことで簡単にモールス信号変換器を作ることができました。 pykakasiのwakatiを使えばMeCabは必要なかったのですが、勉強のために色々触ってみました。 テキスト処理はしっかりしてるはずなので次はこれをAmazon EchoのSkillと組んで遊びたいです。