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 件のコメント:
コメントを投稿