自動観察日記

自動で観察したい

Raspberry PiカメラモジュールをPythonのライブラリで動かす

日光が少ないためか、葉をあまりつけないままアボカドが縦にどんどん長くなってしまい、カメラの枠に収まらなくなってきていました。

saibaimen.hatenadiary.jp

カメラの向きを90°回転させると良さそうだったのですが、少し問題があったので、それについて書きます。

よくわからない問題

これまで、一応Pythonでカメラは動かしていましたが、標準ライブラリのosモジュールで無理やりコマンドを送っていました。

saibaimen.hatenadiary.jp

ですが、次のような問題に悩まされました。

$ raspistill -t 0

(-tオプションで0にすると、シャッターの待ち時間が無限になる)

横向きだとちゃんと枠内に収まるのに
f:id:shut9:20180913015939p:plain

$ raspistill -t 0 -rot 270

-rotオプションで回転させると、枠内に収まらなくなる
f:id:shut9:20180913020439p:plain

これは画面内に収まっていないだけではなく、画像として保存してもこのままになっています。

picameraモジュールを使う

カメラモジュールはpicameraというライブラリで動かせるそうです。

$ pip install picamera

とりあえず次のようなプログラムを書きます。

import time
import picamera

camera = picamera.PiCamera()

def takepic(picname):
    camera.resolution = (600,800)
    camera.rotation = 270
    camera.start_preview()

    # Camera warm-up time                                                                                                               
    time.sleep(200)
    camera.capture(picname)

def main():
    takepic("test.png")

if __name__ == '__main__':
    main()

これで回転しても全体が映るようになりました。

f:id:shut9:20180913021152p:plain

camera.resolution = (600,800)

この部分で画像サイズを決めていますが、最大撮影解像度である3280x2464を超える数値を入力するとエラーが出ます。
はてなブログにアップロードしている画像のサイズが800x600なので、それを横向きにしたときに一致するサイズ(600, 800)としています。

プログラムの修正

温湿度取得と写真撮影をするプログラムを次のように修正しました。

#!/home/pi/.pyenv/shims/python                                                                                                                                                                              
# -*- coding: utf-8 -*-                                                                                                                                                                                     

import os
import Adafruit_DHT
import datetime
import RPi.GPIO as GPIO  #GPIOにアクセスするライブラリをimportします。                                                                                                                                      
import time
import picamera

now = datetime.datetime.now() # 現在の日時を取得                                                                                                                                                            
camera = picamera.PiCamera()

sensor = Adafruit_DHT.DHT22
pin = 4
degC = '℃'

GPIO.setmode(GPIO.BCM)  #GPIOへアクセスする番号をBCMの番号で指定することを宣言します。                                                                                                                      
GPIO.setup(18,GPIO.OUT) #BCMの18番ピン、物理的12番ピンを出力に設定します。                                                                                                                                  

def condition():
    humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
    discomfort = 0.81*temperature + 0.01*humidity*(0.99*temperature - 14.3) + 46.3

    return humidity, temperature, discomfort

def takepic():
    camera.resolution = (600,800)
    camera.rotation=270

    GPIO.output(18,GPIO.HIGH)
    time.sleep(2)
    camera.capture("/home/pi/log_condition/log_pic/{0:%Y%m%d%H}.png".format(now))
    time.sleep(1)
    GPIO.output(18,GPIO.LOW)

def main():
    # log current condition                                                                                                                                                                                 
    file = open('/home/pi/log_condition/log_TH/{0:%Y%m%d}.txt'.format(now), 'a+')  #書き込みモードでオープン                                                                                                
    humidity, temperature, discomfort = condition()
    # Markdown記法(半角スペース2個で改行)                                                                                                                                                                 
    file.write('時刻:{0:%Y/%m/%d %H:%M:%S}  \n'.format(now))
    file.write('湿度:{0:3.1f}%  \n'.format(humidity))
    file.write('温度:{0:3.1f} {1}  \n'.format(temperature,degC))
    file.write('不快指数:{0:3.1f} \n\n'.format(discomfort))

    #    take a picture                                                                                                                                                                                     
    takepic()

if __name__ == '__main__':
    main()

GPIO.cleanup()

この修正は9/8から反映されています。
saibaimen.hatenadiary.jp