Tea break

ちょっとした息抜きに

pykakasiとMeCabを使ってモールス信号変換器を作る

CSGAdventCalendar 9日目 最近ラズパイを使ってモールス符号変換器を作ったので、備忘録。 f:id:wisteria30:20200325235655j:plain

概要

入力した文字列をモールス信号に変換、それをRaspberry PiのLEDを光らせて遊びました。 その際にpykakasiとMeCabを使ってアルゴリズムを組んだので備忘録です。 Githubリンクも載せておきます。 環境はMac, python3.5.2です。

モールス信号とは

文字や記号を表象する方法のひとつ。電信による伝達を目的として発明され、短点とその3倍の長さを持つ長点の組み合わせにより文字や記号を表す。ラテン文字を基礎とした国際モールス信号の他、和文モールス信号のように各国の文字に対応したモールス信号が考案されている。

みなさんご存知SOSのあれです。 日本語やアルファベットを「トン」「ツー」の二つの記号で表すことができます。 そんなモールス信号にもいくつかのルールがあります。

  1. 長点1つは短点3つ分の長さ
  2. 文字と文字の間には短点3つ分をあける
  3. 単語と単語の間には短点7つ分あける

この他にもSOSは例外的に連続して打つなどルールはありますが、 今回は上記の3つをルールを中心にしていきます。

やるべきこと

目標は日常的にSNSで書いている文章をモールス信号に変換できるようにすることです。 そのためにはやるべきことがいくつかあります。

  1. 漢字をひらがなにする(漢字は変換できない)
    1. pykakasiを使って変換する
  2. 自動的に単語で区切る(普通文章を書くときに単語では区切らない)
    1. MeCabを使って形態素解析で単語ごとに区切る
  3. 変換のための条件分岐をひたすら書く

pykakasi

pykakasiは日本語の漢字仮名交じり文を平仮名やローマ字綴りの文に変換するプログラムKAKASIPythonバージョンです。 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を選んだ理由は下記の二つです。

  1. 各種スクリプト言語バインディングされていること
  2. 他の形態素解析エンジンより高速であること

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)

まとめ

kakasiMeCabといった既存の変換器を使うことで簡単にモールス信号変換器を作ることができました。 pykakasiのwakatiを使えばMeCabは必要なかったのですが、勉強のために色々触ってみました。 テキスト処理はしっかりしてるはずなので次はこれをAmazon EchoのSkillと組んで遊びたいです。