Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

RasPi 4BにTesseract 5.3.0をビルド

Dockerでtesseractを使えるようになったキャッキャッと喜んでいたのも昔。
認識率やら取り回しやらの問題で最新版のTesseractをRasPiに組んで動かす事になりました……。

実際のところ

aptで導入できるtesseractはバージョンがやや古い

$ tesseract --version
tesseract 4.1.1
 leptonica-1.79.0
  libgif 5.1.9 : libjpeg 6b (libjpeg-turbo 2.0.6) : libpng 1.6.37 : libtiff 4.2.0 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.4.0
 Found libarchive 3.4.3 zlib/1.2.11 liblzma/5.2.5 bz2lib/1.0.8 liblz4/1.9.3 libzstd/1.4.8

必要なライブラリ群の入手

例のごとく、ビルドに必要な諸々を入手。

$ sudo apt install -y g++  autoconf automake libtool pkg-config libpng-dev libtiff5-dev zlib1g-dev

ソースコードの入手とビルド

Releases · tesseract-ocr/tesseract · GitHub
より最新版を入手。
執筆時点では5.3.0が最新なので

$ wget https://github.com/tesseract-ocr/tesseract/archive/refs/tags/5.3.0.zip

回答してcd

$ unzip 5.3.0.zip
$ cd 5.3.0

指示通り、ビルドに必要な諸々をそろえてくれるシェルスクリプトを実行

$ ./autogen.sh
$ ./configure --prefix=$HOME/local/

お楽しみのビルド。
RasPi4Bでは一時間ほどかかりました。

$ make
$ sudo make install
$ sudo ldconfig

学習済みファイルの導入

ビルドした状態では一切の学習データが入っていないので、外からもってきます。
https://github.com/tesseract-ocr/tessdata_bestに学習済みデータが入ってるので、必要な言語のものを入手。
私は英語のみ用があったので

$ wget https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
$ sudo mv eng.traineddata /home/user/local/share/tessdata/

ちゃんと認識されたか確認

$ /home/user/local/bin/tesseract --list-langs
List of available languages in "/home/user/local/share/tessdata/" (1):
eng

実験

deadbeef.jpg

$ convert -threshold 20000 deadbeef.jpg bindeadbeef.jpg

ためしに実行すると……カメラ越しのものが、ようやく認識できるように……。

$ /home/user/local/bin/tesseract bindeadbeef.jpg - -l eng
DEAD BEEF

Git submoduleのはなし

submoduleはざっくりいうと「他のgitプロジェクトを作業中のgitプロジェクトでも使えるようにする技」という事になります。
直接引っ張ってくるより、先方のアップデートに合わせて更新したり、逆に更新に付き合わなかったりという事ができます。

実際のところ

HUGOでテンプレートエンジンを展開する際、以下のようなコマンドをうつよう指示があります

$ git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke

引っ張ってくるとき

何も考えずに引っ張ってくるとsubmoduleで導入したディレクトリには何も入っていません。
".gitmodule"は残っているので、これを頼りに自前で引っ張ってくる必要があります

$ git submodule init
$ git submodule update

参考もと

Git - Submodules

【読書メモ】人に優しいロボットのデザイン

ソフトロボティクスの本かと思い手に取ったのですが、素直にタイトル通りの実際にはロボットと人間の関係性のお話でした。

著者は「人工あい」*1という概念を用いて、
人間にとって心地の良い場所を提供するシステムを提案しています。

きっかけになったのが、ネットで話題になった「レンタル何もしない人」というのが中々キャッチーですね。

著者の考えでは、人間は冒険ないしチャレンジをしたいものだが心理的負荷から実行に移せずにいるものの、そこに優しいロボットが寄り添う事で負荷を下げて可能性を広げる事ができるという未来がくる……そうです。

昔からテキストにパターン化された応答を返す人工無能というのはありましたし、最近ならコメントに動的に応答するAI Vtuberなんてのも流行っています。
「AIあい」はもう少し踏み込んで、ケの日でも生き続ける、生活に溶け込んだデバイスを想定しています。
レンタル何もしない人と同様に必ずしも好意的フィードバックをせず居るだけでもあり得る事、所有者との関係性を除いても存在しえ自律性をもつこと*2、定型句だけでなく過去のやりとり(=記憶)から応援する内容が動的に変わっていくといった条件が挙げられています。
要するにファービーやAIBOの凄い賢い奴ですね。

技術屋としてコンセプトは同意したくありますが……カーネギー博士の「人を動かす」の事例と同様に人間の善性を信用しすぎな気はします*3


2023年3月19日追記

などと書いていたら、OpenAIのGPT-4が話題の文脈を理解しながら応答しているとしか思えない挙動を見せ、業界がひっくり返っています。
普段冷笑的なテックギーク層ですら驚いているので、もしかすると本当に寄り添うロボットが実現するかも……??


関連する本

shuzo-kino.hateblo.jp

*1:目次で読んだときには人口無能かAI Vtuberの類かと誤認してしまいました

*2:作中では、ぬいぐるみSNSといってマスコット同士が仮想的なコミュニケーションをとるバックストーリーを展開させる研究が提示されていました

*3:これは作中でも指導学生の一人から指摘されています

AttributeError: module 'cv2.aruco' has no attribute 'detectMarkers'

数カ月前に作ったArUcoアプリを再稼働させたところ

AttributeError: module 'cv2.aruco' has no attribute 'detectMarkers'

などというエラーが。
……何もしてないのに壊れた??

これ、何のことはなく、別のプロジェクトでOpenCVをアップデートした事が原因でした。
4.7.X系からdetectmarkersメソッドからdetectメソッドを使うように変わったそうです。

実際のところ

非推奨……というかエラーを吐いた原因であるdetectMarkersメソッドを使ったバージョンが以下の時

import cv2
import numpy as np
import sys

aruco = cv2.aruco
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)

stdin = sys.stdin.buffer.read()
array = np.frombuffer(stdin, dtype="uint8")
img_src = cv2.imdecode(array, 1)

corners, ids, rejectedImgPoints = aruco.detectMarkers(img_src, dictionary)

if ids is not None:
    img_src = aruco.drawDetectedMarkers(img_src, corners, ids)

cv2.imshow("Image with detected ArUco markers", img_src)
cv2.waitKey(0)
cv2.destroyAllWindows()

detectメソッド使って書き換えると

import cv2
import numpy as np
import sys

aruco = cv2.aruco
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)

stdin = sys.stdin.buffer.read()
array = np.frombuffer(stdin, dtype="uint8")
img_src = cv2.imdecode(array, 1)

parameters = aruco.DetectorParameters_create()
corners, ids, rejectedImgPoints = aruco.detect(img_src, dictionary, parameters=parameters)

if ids is not None:
    img_src = aruco.drawDetectedMarkers(img_src, corners, ids)

cv2.imshow("Image with detected ArUco markers", img_src)
cv2.waitKey(0)
cv2.destroyAllWindows()

bcコマンドで有効桁数

すっかり軟弱になったので数字を

実際のところ

$ echo "scale=0; 4+42/2" | bc
25
$ echo "scale=10; 4+42/2" | bc
25.0000000000

すっかり忘れていましたが……ヒアストリングに変数を与える方式で

$ cat cmd.txt
scale=10; 4+42/2
scale=2; 4+86/3

$ cmdstring=`cat cmd.txt`

$ bc <<< $cmdstring
25.0000000000
32.66

ヒアドキュメントでも

bc << EOF
scale=10; 4+42/2
scale=2; 4+86/3
EOF
25.0000000000
32.66