植物栽培に関係したコードをまとめました。中にはメモとして残した物もあるので実際に使えるかは不明です。自分でまとめたコードもあればChatGPTと対話した結果のものや、それぞれを継ぎ接ぎしたものもあります。何かのヒントになればと思って記録を残します。
実際に使っているコードに関しては、各記事のリンクを貼るのでそちらを参考にしてください。
プログラミングの試行錯誤のたびに追記していく予定です。
シェルスクリプト
カメラ位置の調整用コード
#!/bin/bash
raspistill --nopreview --fullscreen --timeout 0 &
# キーボード入力待ち
read -n1 -s -r -p "Press any key to exit..."
# プレビュープロセスを終了
killall raspistill
カメラを設置して最初に実行するプログラムです。これで画角や距離の調整を行います
カメラ撮影用コード
#!/bin/bash
# 保存先パスとファイル名
save_path="/path/to/save"
default_name="image"
# 現在の日時を取得
datetime=$(date +"%Y-%m-%d_%H-%M-%S")
# ファイル名を作成
filename="$save_path/$default_name-$datetime.jpg"
# 画像を撮影してファイルに保存
raspistill -w 1920 -h 1080 -o "$filename"
最後の一文を「 raspistill -o “$filename” 」に変えると、モジュールのデフォルトの解像度で撮影します。使用しているモジュールだと2592×1944ピクセルになってしまい、画像サイズが大きいのでサイズを落としています。
撮影した画像に余白を作成し、テキスト形式の情報を追加する
#!/bin/bash
# デフォルトのパスやファイル名、条件を設定
default_path="/path/to/save"
default_edited_path="/path/to/save"
default_name="image"
# [up,down,left,right]から塗りつぶし領域を作る上下左右の方向と幅・高さを指定
padding_direction= "up"
padding_width = 100
padding_height = 0
# 塗りつぶし領域の色と幅と高さを指定
fill_color="white"
# 現在の日時を取得
datetime=$(date +"%Y-%m-%d_%H-%M-%S")
# ファイル名を作成
filename="$default_path/$default_name-$datetime.jpg"
# 画像を撮影してファイルに保存
raspistill -w 1820 -h 1080 -o "$filename"
# 入力ファイルと出力ファイルのパスを指定
input_file="$filename"
output_file="$default_edited_path/$default_name-$datetime-output.jpg"
# 画像の幅と高さを取得
width=$(identify -format "%w" "$input_file")
height=$(identify -format "%h" "$input_file")
# 塗りつぶし領域を追加した画像の幅と高さを計算
if [ "$padding_direction" = "up" ] || [ "$padding_direction" = "down" ]; then
new_width="$width"
new_height=$((height + padding_height))
elif [ "$padding_direction" = "left" ] || [ "$padding_direction" = "right" ]; then
new_width=$((width + padding_width))
new_height="$height"
else
new_width="$width"
new_height="$height"
fi
# 塗りつぶし領域を追加して画像を生成
convert -size "${new_width}x${new_height}" xc:"$fill_color" "$input_file" -geometry "+0+0" -composite "$output_file"
# 画像の右側から85、上から20ピクセルの位置にに日時を書き込む
convert "$output_file" -pointsize 24 -fill black -annotate +$(($width - 85)) +20 "$datetime" "$output_file"
成長記録をタイムラプスに変換する際に、画像内に各種情報を載せる余白があった方が編集の手間が省けると思って作成しました。後でよくよく考えると、
- 余白を追加することで使いにくい解像度になってしまう
- 別に画像中の下の部分は植物の栽培的に情報が増える部分ではないので、そこに情報を書き込んでも問題ない
- 1920×1080ピクセルの比率を維持して画面の下などに情報が少ないらなくてもコードの「# 白塗り領域を右に追加して画像を生成」の下の部分のコードを書く記述に変更すると向きを変えられます。
保存された画像を繋げてタイムラプス動画にするコード
#!/bin/bash
# 編集元の画像フォルダのパス
unprocessed_folder="/path/to/unprocessed"
# タイムラプス動画フォルダのパス
timelapse_folder="/path/to/timelapse"
# 編集済み画像の移動先フォルダのパス
edited_folder="/path/to/edited"
# 現在の日時を取得
datetime=$(date +"%Y-%m-%d_%H-%M-%S")
# タイムラプス未加工画像フォルダ内の画像をタイムラプス動画に変換
ffmpeg -framerate 24 -pattern_type glob -i "$unprocessed_folder/*.jpg" -c:v libx264 -r 24 "$timelapse_folder/$datetime.mp4"
# タイムラプス未加工画像フォルダの画像を編集済み画像フォルダに移動
mv "$unprocessed_folder"/*.jpg "$edited_folder/"
24fpsは1秒間に24枚の画像を使用します。画像の枚数が少ない場合はフレームレートを減らす必要があります。
1日15枚の写真を撮った時の各フレームレートごとの再生時間(秒)
1週間 | 1ヶ月 | 2ヶ月 | 3ヶ月 | 6ヶ月 | |
10fps | 10.5 | 45 | 135 | 270 | |
15fps | 7 | 30 | 90 | 180 | |
20fps | 5.25 | 22.5 | 67.5 | 135 | |
24fps | 4.375 | 18.75 | 56.25 | 112.5 | |
25fps | 4.2 | 18 | 54 | 108 | |
30fps | 3.5 | 15 | 45 | 90 |
魔改造コード
#!/bin/bash
# デフォルトのパスやファイル名、条件を設定
default_path="/home/pi/イチジク/完成プログラム/record"
default_edited_path="/home/pi/イチジク/完成プログラム/padding_record"
default_name="image"
# 塗りつぶし領域の幅・高さを指定
padding_width=200
padding_height=0
# 塗りつぶし領域の色と幅と高さを指定
fill_color="white"
# 現在の日時を取得
datetime=$(date +"%Y-%m-%d_%H-%M-%S")
# ファイル名を作成
filename="$default_path/$default_name-$datetime.jpg"
# 画像を撮影してファイルに保存
raspistill -w 1720 -h 1080 -o "$filename"
# 入力ファイルと出力ファイルのパスを指定
input_file="$filename"
output_file="$default_edited_path/$datetime-output-edited.jpg"
# 画像の幅と高さを取得
width=$(identify -format "%w" "$input_file")
height=$(identify -format "%h" "$input_file")
# 塗りつぶし領域を追加した画像の幅と高さを計算
new_width=$((width + padding_width))
new_height="$height"
# 塗りつぶし領域を追加して画像を生成
convert -size "${new_width}x${new_height}" xc:"$fill_color" "$input_file" -geometry "+0+0" -composite "$output_file"
# Pythonスクリプトの実行とデータの取得
sensor_data=$(python3 - <<EOF
import spidev
from datetime import datetime
num_sensor = 3
moist_offsets = [26, 0, 0]
spi = spidev.SpiDev()
spi.open(0, 0)
def read_adc(channel):
adc = spi.xfer2([1, (8 + channel) << 4, 0])
data = ((adc[1] & 3) << 8) + adc[2]
return data
def calculate_moisture_percent(sensor_value, offset):
dry_value = 850
wet_value = 485
sensor_value += offset
moisture_range = dry_value - wet_value
if sensor_value > dry_value:
sensor_value = dry_value
elif sensor_value < wet_value:
sensor_value = wet_value
moisture_percent = 100 - ((sensor_value - wet_value) / moisture_range) * 100
return round(moisture_percent, 2)
try:
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
sensor_data = []
sensor_data.append("date: %s" % timestamp)
sensor_data.append("temp: 00C, humid: 00%")
sensor_data.append("moisture")
for channel in range(num_sensor):
sensor_value = read_adc(channel)
offset = moist_offsets[channel]
moisture_percent = calculate_moisture_percent(sensor_value, offset)
if channel == 0:
sensor_data.append("Top: %02.0f%%" % moisture_percent)
elif channel == 1:
sensor_data.append("Middle: %02.0f%%" % moisture_percent)
elif channel == 2:
sensor_data.append("Bottom: %02.0f%%" % moisture_percent)
except Exception as e:
print("エラーが発生しました:", str(e))
finally:
spi.close()
print('\n'.join(sensor_data))
EOF
)
# 画像の右側から85、上から20ピクセルの位置にに日時と水分量を書き込む
convert "$output_file" -pointsize 24 -fill black -annotate +$(($width - 85)) +20 "$sensor_data" "$output_file"
crontabの設定について
0 5-19/1 * * * /path/to/capture.sh
0 0 * * 1 /path/to/timelapse.sh
コメント