Raspberry Pi Zero WHで作った定点カメラを改良したい②画像に日付を付ける

記事がクソ長くなってしまったので分けることにした。

画像に日付を付ける

調べてみたらexifを使うやつが多いみたい。そんな厳密でなくてもいいんだよな…。Pythonには画像処理ライブラリとして、Pillow, NumPy, OpenCVと種類があるみたい。やりたいのは画像に文字をつけるだけなので、Pillowだけでいいんかな?

Pillowをインストール

$ pip install Pillow

でインストールなんだけど、エラーでちゃんとインストールできない。最後にMemoryErrorと出てたので

$ sudo nano /etc/dphys-swapfile

で、

CONF_SWAPSIZE=2048

こう。でもまだエラーが出る。

Failed building wheel for Pillow

The headers or library files could not be found for jpeg,
a required dependency when compiling Pillow from source.

Please see the install instructions at:
https://pillow.readthedocs.io/en/latest/installation.html

なので

$ sudo apt-get install libjpeg-dev

こう。んでもっかいインストール。

$ pip install Pillow
Collecting Pillow
Using cached https://files.pythonhosted.org/packages/51/fe/18125dc680720e4c308
Building wheels for collected packages: Pillow
Running setup.py bdist_wheel for Pillow … –
done
Stored in directory: /home/pi/.cache/pip/wheels/f6/4e/42/5f6c85a93dd4555e47c982a2b1e4405ad056ce255800130552
Successfully built Pillow
Installing collected packages: Pillow
Successfully installed Pillow-6.1.0

いぇい。こんなん自分で調べて解決しれって言われても無理だわー。先人最高!ありがとう先人!!

フォントのインストール

文字を挿入するのにフォントが必要とのことなので、/usr/share/fontsを探しに行ったところ、そもそもフォルダがなかった。Liteってそうなのか。なんかいい感じのフォントないかなーと探してみると7セグを再現したフォントを見つけた。

https://www.keshikan.net/fonts.html

これをダウンロードしてnasのフォルダに入れとく。

画像を読み込んで日付入れて保存

with picamera.PiCamera() as camera:
    sleep(5)
    camera.hflip = True
    camera.vflip = True
    camera.capture(dir_path+file_name+'.jpg')

img = Image.open(dir_path+file_name+'.jpg')
now = datetime.datetime.now()
text = now.strftime('%Y-%m-%d %H:%M')
draw = ImageDraw.Draw(img)
font = ImageFont.truetype('/home/pi/nas/DSEG7Classic-Bold.ttf', 15)
draw.text((5, 5), text, font=font, fill=(255,255,255))
img.save(dir_path+file_name+'.jpg')

camera.capture()で、画像が保存されるので、まずは保存された画像をImage.openで読み込む。datetime.datetime.now()で現在の日付時刻を取得。.strftime(‘%Y-%m-%d %H:%M’)で表示する形式に型変換。ImageDraw.Draw()で、書き込む形式にするみたいな感じらしい。描画する場合この形式にするもんみたい。ImageFont.truetype()で使用するフォントを読み込む。大きさは相対指定したかったけど、とりあえず絶対指定で。draw.text()で始点を指定、今回は左上にした。右下だと計算がめんどい。fontがフォント、fillが色。img.save()で開いたファイルと同じ名前で保存。上書き保存される。んで、

$ python /home/pi/nas/shutter.py

すると…

ついた!!

ターミナルでは動くけど、cronだと動かない

※分かってやってる風に書いてるけど、調べつつやってます。

また画像溜めてからffmpegやってこーと思い、sudo crontab -eで

0-59/10 * * * * python /home/pi/nas/shutter.py

とやった。でも画像が溜まっていかない…、なんでや!こういう時こそログを見ればいいんだな、と思い、/var/log/cron.logを見に行ったところ、ファイルが無い。なんでや!どうやら標準ではログ取らないようになってる模様。ということで

$ sudo nano /etc/rsyslog.conf
#cron.*             /var/log/cron.log

で、cronの部分がコメントアウトされてるのを戻す。(#を取る)

$ sudo /etc/init.d/rsyslog restart

サービスを再起動して反映させる。

$ sudo nano /etc/default/cron
EXTRA_OPTS='-L 5'

#を外して、ログレベルを変更する。’-L 5’にした。

$ sudo /etc/init.d/cron restart

cronも再起動する。そうすると、時間が来ると/var/log/cron.logが作成されて、ログが記録されるようになった。中身を見てみると

Jul 15 21:10:01 raspberrypi-pierce CRON[1173]: (root) CMD (python /home/pi/nas/shutter.py)
Jul 15 21:10:02 raspberrypi-pierce CRON[1169]: (CRON) error (grandchild #1173 failed with exit status 1)

てなってた。確かにエラーになってる。ただこれだけだと意味が分からん。とりあえず「grandchild #1173 failed with exit status 1」でググってみたら、やっぱりこれだけだとcronの実行結果だけで、内容は分かんないみたい。ただpythonの実行エラーっぽいらしい。で、pythonのログを出力するためにsudo crontab -eの内容を

0-59/10 * * * * python /home/pi/nas/shutter.py >> /tmp/test.log 2>&1

とする。この書き方だと、標準出力とエラー出力が一緒に出るそう。で実行されるのを待って/tmp/test.logを見てみると

Traceback (most recent call last):
File “/home/pi/nas/shutter.py”, line 5, in <module>
from PIL import Image, ImageFont, ImageDraw
ImportError: No module named PIL

PILがimportできてない、ということみたい。ターミナルだとちゃんと動くのになんで?ということで「ImportError: No module named PIL」でググる。とりあえずインストールされてるか確認

$ pip list
cryptography (1.7.1)
dnspython (1.15.0)
enum34 (1.1.6)
idna (2.2)
ipaddress (1.0.17)
keyring (10.1)
keyrings.alt (1.3)
numpy (1.12.1)
picamera (1.13)
Pillow (6.1.0)  #これのはず。PILの後継ってことだし。
pip (9.0.1)
pyasn1 (0.1.9)
pycrypto (2.6.1)
pygobject (3.22.0)
pyxdg (0.25)
RPi.GPIO (0.6.5)
SecretStorage (2.3.1)
setuptools (33.1.1)
six (1.12.0)
wheel (0.29.0)

入ってるよ…?関係ないけどpython2.7って2020.01.01で終わるんだって。

DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won’t be maintained after that date. A future version of pip will drop support for Python 2.7.

廃止予定:Python 2.7は、2020年1月1日にその寿命が尽きます。Python2.7はその日以降保守されないため、Pythonをアップグレードしてください。 pipの将来のバージョンはPython 2.7のサポートをやめるでしょう。

もうちょっと調べると、ターミナルとcronだと、環境変数が違うみたい。cronの場合pythonがどこにあるか分からなくてエラーになる。みたいな。試してみる。

$ which python
/usr/bin/python
#cronに追記
0-59/10 * * * * which python > /tmp/path.txt
#/tmp/path.txtの中身
/usr/bin/python

同じだなぁ…。でも一応パスを通してみる。

$ echo ${PATH}

で調べると

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

と返ったので、まんまcrontabに

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games

と追記。でも、じっと待ってみたけど変化なし。今度はcrontabにpythonをフルパスで書いてみる。

0-59/3 * * * * /usr/bin/python /home/pi/nas/shutter.py >> /tmp/test.log 2>&1

…これも変化なし。ちょっと、ググりパターンが尽きてきた。。。そもそもpython自体は起動できてるので、cronじゃなくてpythonの問題なのかもしれない。で、importエラーに絞って検索してみると、ライブラリのインストールに関する記事を見つけた。

$ pip show pillow

Name: Pillow
Version: 6.1.0
Summary: Python Imaging Library (Fork)
Home-page: http://python-pillow.org
Author: Alex Clark (Fork Author)
Author-email: [email protected]
License: UNKNOWN
Location: /home/pi/.local/lib/python2.7/site-packages
Requires:
Required-by:

ここで見るのがLocationのとこ。pillowは/home/pi/.local/lib/python2.7/site-packagesにインストールされている。ライブラリがインストールされてるとこのパスが通ってない場合があるらしいので、まずは

import sys
print(sys.path)

ていう内容のpysys.pyを/home/pi/nas/に作り

$ python pysys.py

すると

['/home/pi/nas', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-arm-linux-gnueabihf', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/pi/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

‘/home/pi/.local/lib/python2.7/site-packages’があるので、ターミナル上で実行した場合、pythonはライブラリの場所を分かってるってことなんだと思う。ではcronではどうか。crontabに

0-59/3 * * * * python /home/pi/nas/pysys.py >> /tmp/test.log 2>&1

と追記。カップ麺を作りつつ待って、/tmp/test.logを見てみると

['/home/pi/nas', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-arm-linux-gnueabihf', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

おおおおおおおおおおおおおおーーーーーーーーーーーーー!!!!!!!!

‘/home/pi/.local/lib/python2.7/site-packages’が無い!!!よね!!!???初めて原因っぽい事に突き当たった気がする!で、じゃあcronで実行する時にパスが通った状態にするにはどうすればいいのかしら…?ググるとpillowをオプション付けて再インスコすればいいみたい。

$ pip uninstall pillow

でアンインスコ。…だけど

Uninstalling Pillow-6.1.0:
  Would remove:
    /home/pi/.local/lib/python2.7/site-packages/PIL/*
    /home/pi/.local/lib/python2.7/site-packages/Pillow-6.1.0.dist-info/*
Proceed (y/n)? y
  Successfully uninstalled Pillow-6.1.0

さっきのディレクトリが含まれてる。うーん?いいのかな。で、まぁ今度は

$ python -m pip install pillow

でインストール。あれ?エラー

ERROR: Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/Pillow-6.1.0.dist-info'
Consider using the `--user` option or check the permissions.

権限ぽいのでsudo付けてみる。

$ sudo python -m pip install pillow

そしたら

Successfully installed pillow-6.1.0

通った。そしたらもっかい

$ pip show pillow

すると

Name: Pillow
Version: 6.1.0
Summary: Python Imaging Library (Fork)
Home-page: http://python-pillow.org
Author: Alex Clark (Fork Author)
Author-email: [email protected]
License: UNKNOWN
Location: /usr/local/lib/python2.7/dist-packages
Requires:
Required-by:

おぉ、Locationがcronが見てるパスに変わった!なるほど、そっちか。cronにパスを通すんじゃなくて、そもそものインストール先を変えるのね。と、いうことは、crontabにまた

0-59/3 * * * * python /home/pi/nas/shutter.py >> /tmp/test.log 2>&1

て追記してみると…

うおおおおお!!!!!

できた!!!!!長かったぁ~٩(′д‵)۶

読んでなんとなく分かった気になった質問と回答を雑に翻訳しとく

https://www.raspberrypi.org/forums/viewtopic.php?t=213591

Pythonのライブラリってどこにインストールされるの?

pipを使ってPythonのライブラリをインストールした時、どこのフォルダ階層にインストールされるの?

Re:
  • シングルユーザーの場合(sudoを使わない場合)
    • ~/.local/lib/python2.7
  • システム全体の場合(sudoを使う場合)
    • /usr/local/lib/python2.7
  • aptによってPythonのパッケージをインストールした場合
    • /usr/lib/python2.7

通常、Pythonはサブディレクトリsite-packagesを使うけど、Debianベースのインストール(Raspbianね)はサブディレクトリdist-packagesを使うよ。

つーことで、もし

sudo pip install mylib

てしたら、mylibは

/usr/local/lib/python2.7/dist-packages

にインストールされるよ。

pip3を使う場合、python2.7をpython3.5に置き換えてね。

ふむふむ。つまり一番最初にpillowをインストールした時には、シングルユーザーでインストールされてたので、システム全体のcronで使おうとしてもインストール場所が分かんなくてエラーになってたってことでいいのかな。いいことにしとこう。

結局cronでパス通すやり方は分かんなかったけど、目的は達成できたのでいーや。しかしまぁ権限とかユーザとかグループとかいまいちちゃんと飲み込めてない…。やってけば分かるかなぁ。

参考

https://note.nkmk.me/python-image-processing-pillow-numpy-opencv/

https://qiita.com/tsuchima/items/ca8f0cd383fa93d875c8#raspberry-pi-zero%E3%81%AEswap%E3%82%92%E4%B8%8A%E3%81%92%E3%82%8B

https://qiita.com/paper2/items/b67d07813eba7f895635

https://note.nkmk.me/python-pillow-basic/

http://min117.hatenablog.com/entry/2017/08/26/110104

https://qiita.com/Higemal/items/5a579b2701ef7c473062

https://teratail.com/questions/124857

http://tkns-jp.net/index.php?id=11

https://qiita.com/kkoito/items/28d9a453c425b08738d2

https://gist.github.com/koudaiii/49ac3f8b7c207f0da31f#link2keyword=crontab%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E3%82%82%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84%E6%99%82%E3%81%AE%E7%A2%BA%E8%AA%8D%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%20%E3%83%BB%20GitHub

https://teratail.com/questions/49082

https://higelog.brassworks.jp/1775#link2keyword=%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E5%8F%A9%E3%81%8F%E3%81%A8%E5%8B%95%E3%81%8F%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8CCron%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%AA%E3%81%84%E6%99%82

https://titirobo-develop.hatenablog.jp/entry/2018/07/03/141510

https://qiita.com/arumiti/items/835e87c35dcbb69d8ca2

https://qiita.com/Kent_recuca/items/349586e9c034535f2991

https://www.haya-programming.com/entry/2018/09/09/202711

https://teratail.com/questions/181563

カテゴリー: したい タグ: , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です