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セグを再現したフォントを見つけた。

7セグ・14セグフォント 「DSEG」

これをダウンロードして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

て追記してみると…

うおおおおお!!!!!

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

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

Where are python libraries installed to? - Raspberry Pi Forums
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でパス通すやり方は分かんなかったけど、目的は達成できたのでいーや。しかしまぁ権限とかユーザとかグループとかいまいちちゃんと飲み込めてない…。やってけば分かるかなぁ。

スポンサーリンク

参考

Pythonで画像処理: Pillow, NumPy, OpenCVの違いと使い分け | note.nkmk.me
Pythonで画像処理を行う場合、PillowやNumPy、OpenCVなど様々なライブラリが利用できる。PythonのOpenCVは画像をNumPyの配列ndarrayとして扱っており、「OpenCVでの画像処理」といって紹介されているものも、OpenCVの関数は使っておらずNumPy配列ndarrayの操作だけで完...
ヒント:ラズパイ(Raspberry Pi Zero WH)でtensorflowをインストール - Qiita
ラズパイにtensorflowを!!ラズパイ(Raspberry Pi Zero WH)にtensorflowを入れてみました。基本はsudo pip install tensorflowの…
python の Pillow をインストール中にエラーが出た時の対処メモ - Qiita
Pillow を pip install しようとしたら以下エラーがでたので対処。The headers or library files could not be found for jpeg,…
Pythonの画像処理ライブラリPillow(PIL)の使い方 | note.nkmk.me
Pillowは、開発が停止しているPIL(Python Image Library)からフォークされた画像処理ライブラリ。OpenCVのようにコンピュータービジョン系の高度な画像処理(顔検出やオプティカルフローなど)はできないが、リサイズ(拡大・縮小)や回転、トリミング(部分切り出し)のような単純な処理が簡単にできる。...
RaspberryPi cronが効かない → ログ表示設定して解決 - min117の日記
// Rasbpberrpi でまたcron が効かなくなった。ちゃんとログ出して対処することにする。 このサイトが良かった。まんま設定する。 shima-nigoro.hatenablog.jp rsyslogでcronのログを取る設定にする。 $ sudo vim /etc/rsyslog.conf rsyslog...
RaspberryPi3で初めてcrontabを使う前に - Qiita
#■はじめにRaspberryでは、とりあえずでcrontabに内容を記載しても何も起こりません(でした)。初めてcrontabを利用する前に必要な設定をまとめます。 1. rsyslogの設定…
cron が効かない、エラーログの意味
Raspbian OS に crondを設定したんですが、うまく動かなくて原因はわかりません。 設定したのは、crond -e に毎1分に動くpythonです。 ```ここに言語を入力 *0
404 Error - Not Found
cronがうまく動かないときの調査 - Qiita
cronを使って定期実行させようとしてうまくいかない場合に、"/var/log/cron.log" には実行ログしかのりません。そのためコマンドの実行結果をファイルに出力させる方法として参考までに…
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
cronでpythonを実行した際、seleniumがインポートできない
###前提・実現したいこと cronでpythonを定期起動したいのですがseleniumがインポートできない旨のエラーが出ます。 crontabには下記の記載をしています。 ``` * *
コンソールで叩くと動くスクリプトがCronで動かない時 - ひげろぐ
以下のサイトが参考になった。 原因究明は以下の順番で。 ログに何も残っていなかったらCronが動いてないということなので、crontabの設定があっているか、crondが動いているかといったあたりをチェックする。 その辺りが問題なければスクリプトのエラーをファイルに出力して内容を確かめる。 シェルをzshにするとエラー...
お探しのページは見つかりませんでした。 - はてなブログ
import error!パスを通す??pythonあるある。 - Qiita
#import errorってなんやねんそれはあまりに突然の出来事だった---->>> import <モジュール>Traceback (most recent call last): Fil…
Pythonモジュールのimportができなくなったときの対処記録 - Qiita
概要自動化処理の勉強中、それまでインポートできていたPythonのrequestsモジュールが急に(?)インポートできなくなったので対処しました。現在はこの方法でうまくいっています。環境win…
お探しのページは見つかりませんでした。 - はてなブログ
インストールしたはずのパッケージにImportError :No module namedがでる.
### 前提・実現したいこと Rasberry pi3 B+ を用いてセンサー値を読み取り, csvファイルに書き込んだものをPythonのグラフ化ツールであるBokehを使ってグラフ化するためにひ

コメント

タイトルとURLをコピーしました