Raspberry PiでOCRを使うでRaspberry PiにTesseract-OCRをインストールしてOCRできるようにしたが、これとTwitterを利用して、Python3でOCRボットを作る。
OSはRaspbian Jessie。
以下の事項を済ませておく。
PythonでTesseract-OCRを使うためにPythonラッパーのPython-tesseractをインストールする。ただその前に、libjpeg8-devと画像処理ライブラリのPillowをインストールしておく。libjpeg8-devはjpg画像を扱うのに必要。
続いてPython-tesseractのインストール。
Pillowとpytesseractのバージョンは以下の通り。
はじめにTesseract-OCRのパスを確認しておく。
使い方は簡単。tesseractのパスを設定して、OCRする画像を読み込むだけ。日本語OCRの精度に不安はあるが(Raspberry PiでOCRを使う)、とりあえずこれで進める。
PythonでOCRできるようになったので、次はTwitter APIを利用できるようにする。Python3でTwitterのデータを取得するではTweepyというTwitter APIのPythonラッパーを使ったが、ここではRequests-OAuthlibというHTTPライブラリのRequestsをサポートするOAuth認証ライブラリを使用する。Requests-OAuthlibはpipでインストール。
以下のバージョンがインストールされた。
Twitterが提供するAPIには、過去データを取得できるTwitter APIだけでなく、リアルタイムにデータ取得できるStreaming APIもある。Streaming APIを使ってリアルタイムに特定キーワードを含むツイートを検索してみる。Streaming APIを利用するサンプルはRequestsのページにあるので、これを参考に以下のようなサンプルコードを作成。
上記コードをPython3で実行すると、以下のように「ラーメン」を含むツイートが表示される。
要領としては、TwitterとPythonでRaspberry Piを再起動するでやったように、Twitterのダイレクトメッセージを使う。スマホから自分宛にダイレクトメッセージで画像を送信し、Raspberry Piで画像のURLを含むダイレクトメッセージを受信する。画像をダウンロードしてからOCRして、結果を自分宛に返信すると、スマホでOCRの結果を受け取れる。以下のコードを作成。
上記コードをPython3で実行し、スマホで撮った画像をTwitterのダイレクトメッセージで自分宛に送る。送ったのは以下2つの画像。解像度はそれぞれ4050 X 719と3898 X 850。
Twitterの遅延なのか数分遅れることがあるものの、ちゃんと動いている。ただ、OCRの精度はイマイチ。実用は難しいか・・・
環境
OSはRaspbian Jessie。
事前準備
以下の事項を済ませておく。
- Tesseract-OCRのインストール(Raspberry PiでOCRを使う)
- Twitter APIの利用に必要なAPIキーとトークンの取得(Twitterの開発者向けのページで申請する)
PythonラッパーPython-tesseractのインストール
PythonでTesseract-OCRを使うためにPythonラッパーのPython-tesseractをインストールする。ただその前に、libjpeg8-devと画像処理ライブラリのPillowをインストールしておく。libjpeg8-devはjpg画像を扱うのに必要。
続いてPython-tesseractのインストール。
Pillowとpytesseractのバージョンは以下の通り。
Python-tesseractを使ってみる
はじめにTesseract-OCRのパスを確認しておく。
使い方は簡単。tesseractのパスを設定して、OCRする画像を読み込むだけ。日本語OCRの精度に不安はあるが(Raspberry PiでOCRを使う)、とりあえずこれで進める。
from PIL import Image import pytesseract # tesseractのパスを設定 pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract' # text.pngという画像を日本語OCRして結果を出力 print(pytesseract.image_to_string(Image.open('test.png'), lang='jpn'))
Requests-OAuthlibによるStreaming APIの利用
PythonでOCRできるようになったので、次はTwitter APIを利用できるようにする。Python3でTwitterのデータを取得するではTweepyというTwitter APIのPythonラッパーを使ったが、ここではRequests-OAuthlibというHTTPライブラリのRequestsをサポートするOAuth認証ライブラリを使用する。Requests-OAuthlibはpipでインストール。
以下のバージョンがインストールされた。
Twitterが提供するAPIには、過去データを取得できるTwitter APIだけでなく、リアルタイムにデータ取得できるStreaming APIもある。Streaming APIを使ってリアルタイムに特定キーワードを含むツイートを検索してみる。Streaming APIを利用するサンプルはRequestsのページにあるので、これを参考に以下のようなサンプルコードを作成。
import json from requests_oauthlib import OAuth1Session, OAuth1 # Twitter APIの認証情報 # Twitterの開発者向けのページで取得したキーとトークンを使う CONSUMER_KEY = 'Consumer Key' CONSUMER_SECRET = 'Consumer Secret' ACCESS_TOKEN = 'Access Token' ACCESS_TOKEN_SECRET = 'Access Token Secret' # 認証情報の設定 tw = OAuth1Session(CONSUMER_KEY, client_secret=CONSUMER_SECRET, resource_owner_key=ACCESS_TOKEN, resource_owner_secret=ACCESS_TOKEN_SECRET) # Twitterデータのリアルタイム検索 # https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter.html url = 'https://stream.twitter.com/1.1/statuses/filter.json' # 検索キーワードの指定 data={'track':'ラーメン'} # Streaming APIを使うときはオプションstream=Trueを指定 r = tw.post(url, data=data, stream=True) for line in r.iter_lines(): if line: status = json.loads(line.decode('utf-8')) # ツイートを表示 print(status['text'] + '\n')
上記コードをPython3で実行すると、以下のように「ラーメン」を含むツイートが表示される。
OCRボットの作成
要領としては、TwitterとPythonでRaspberry Piを再起動するでやったように、Twitterのダイレクトメッセージを使う。スマホから自分宛にダイレクトメッセージで画像を送信し、Raspberry Piで画像のURLを含むダイレクトメッセージを受信する。画像をダウンロードしてからOCRして、結果を自分宛に返信すると、スマホでOCRの結果を受け取れる。以下のコードを作成。
""" Twitterのダイレクトメッセージで送信した画像をOCRして返信する """ import os import json import uuid from io import BytesIO from requests_oauthlib import OAuth1Session, OAuth1 from PIL import Image import pytesseract # Twitter APIの認証情報 # Twitterの開発者向けのページで取得したキーとトークンを使う CONSUMER_KEY = 'Consumer Key' CONSUMER_SECRET = 'Consumer Secret' ACCESS_TOKEN = 'Access Token' ACCESS_TOKEN_SECRET = 'Access Token Secret' # Twitterの認証情報でOAuth1Sessionオブジェクト作成 tw = OAuth1Session(CONSUMER_KEY, client_secret=CONSUMER_SECRET, resource_owner_key=ACCESS_TOKEN, resource_owner_secret=ACCESS_TOKEN_SECRET) # pytesseractのパスを設定 pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract' def send_dm(sn, text): """ ダイレクトメッセージの送信 """ data = {'screen_name':sn, 'text':text} s = tw.post('https://api.twitter.com/1.1/direct_messages/new.json', data=data) def dl(url): """ ダイレクトメッセージに添付された画像ファイルのダウンロード """ # ダイレクトメッセージに添付された画像のURLにHTTPリクエスト r = tw.get(url) # HTTPリクエストのレスポンスから画像データ作成 img = Image.open(BytesIO(r.content)) # 画像ファイルの拡張子を取得 root, ext = os.path.splitext(url) # UUIDでユニークなファイル名を作成して画像を保存 uname = str(uuid.uuid4()) img.save(uname+ext) return uname+ext def get_text(img_path): """ pytesseractを使ってOCRした結果を返す """ return pytesseract.image_to_string(Image.open(img_path), lang='jpn+eng') def streaming(): """ Streaming APIでダイレクトメッセージを受信して、画像があればOCRして 結果をダイレクトメッセージで送信する """ # Stream APIを使うときはオプションstream=Trueを指定 r = tw.get('https://userstream.twitter.com/1.1/user.json', stream=True) print('Ready to OCR') for line in r.iter_lines(): if line: line = line.decode('utf-8') else: continue if 'direct_message' in line: # JSONから辞書型に変換 dm = json.loads(line)['direct_message'] # 送信者と受信者の一致をチェック # 他人からのDirect Messageに反応しないようにするため if dm['sender_screen_name'] == dm['recipient_screen_name']: if 'entities' in dm: if 'media' in dm['entities']: print('DM: {} from @{}'.format(dm['text'], dm['sender_screen_name'])) for media in dm['entities']['media']: # 画像ファイルのURL img_url = media['media_url'] # 画像をダウンロード fname = dl(img_url) # ダウンロードした画像をOCR ocr_text = get_text(fname) print(ocr_text) # ダイレクトメッセージでOCRの結果を送信 send_dm(dm['sender_screen_name'], ocr_text) # 画像ファイルの削除 os.remove(fname) if __name__ == '__main__': streaming()
上記コードをPython3で実行し、スマホで撮った画像をTwitterのダイレクトメッセージで自分宛に送る。送ったのは以下2つの画像。解像度はそれぞれ4050 X 719と3898 X 850。
Twitterの遅延なのか数分遅れることがあるものの、ちゃんと動いている。ただ、OCRの精度はイマイチ。実用は難しいか・・・
0 件のコメント:
コメントを投稿