takahashi_kunn が 2024年10月24日15時35分01秒 に編集
コメント無し
本文の変更
___カレンダー式思い出写真日記___ #### はじめに > 今回は、Raspberry Pi4のカメラで撮影した写真を自動で整理してカレンダー式の写真日記にしてくれる。ものを作成しましたので、次の"概要"で紹介いたします。 ### 概要 ・Raspberry Pi4のカメラを使って写真を撮影 ・撮影された写真は自動で日付ごとにカレンダーに整理 ・特定の日の思い出を簡単に振り返ることができます ## 設計イメージ図 ![キャプションを入力できます](https://camo.elchika.com/a85761194520ba105cf9851dfa10a122840f4827/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f65653762393332382d643566372d343563382d386132652d326534326538316532636331/) ## 動作画面
![キャプションを入力できます](https://camo.elchika.com/9676523f9c3ac067d2ee400bfb3709245aa276eb/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f64663364333331652d343663662d343236632d396539342d303436613939323833356261/) 写真は1~4枚だと見栄えがよくカレンダーに表示をさせることができます。
![キャプションを入力できます](https://camo.elchika.com/45c699f6ef0842f5cf45cdd9be3bcd3b85de1ff7/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f39643931366332352d613532332d343561322d623035332d303039386637323936343861/) 特定の日付をクリックし、写真が入っていれば写真が表示されます。 ![キャプションを入力できます](https://camo.elchika.com/31b1362d7450534a1a5c018230dddfe7e84b60cd/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f64633537613531382d313130632d346361342d623462352d393561636635643461626535/) ![キャプションを入力できます](https://camo.elchika.com/449bd96d224149d539178cc34b9cf42fb79a6c0e/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f33336135313833652d333536632d346132312d623735622d666230643161666635333064/) 写真が4枚以上の時は「→」をクリックすると4枚以降の写真が表示されます。
## 使用した部品 - Raspberry Pi4 - Raspberry Pi カメラモジュール - IoT学習HAT(SW1使用) ### ソースコード ```arduino:カレンダー作成コード import tkinter as tk from tkinter import ttk import calendar from datetime import datetime
from PIL import Image, ImageTk # Pillowライブラリを使用して画像を表示
from PIL import Image, ImageTk
import os # メインウィンドウを作成 root = tk.Tk() root.title("カレンダー") # 現在の年月を取得 current_year = datetime.now().year current_month = datetime.now().month # 曜日ラベルのリスト weekdays = ["月", "火", "水", "木", "金", "土", "日"]
# 表示中の画像のページ番号 current_page = 0
# カレンダーの日付ごとにボタンを表示する関数 def show_calendar(year, month):
# 前に表示されているボタンを削除
for widget in days_frame.winfo_children(): widget.destroy()
# 曜日ラベルを表示
for col, weekday in enumerate(weekdays): fg_color = "black"
if col == 5: # 土曜日
if col == 5:
fg_color = "blue"
elif col == 6: # 日曜日
elif col == 6:
fg_color = "red" tk.Label(days_frame, text=weekday, width=5, height=2, font=("Courier", 10), fg=fg_color).grid(row=0, column=col)
# 指定した年月のカレンダーを取得
cal = calendar.monthcalendar(year, month)
# 日にちごとにボタンを作成
for row, week in enumerate(cal): for col, day in enumerate(week): fg_color = "black"
if col == 5: # 土曜日
if col == 5:
fg_color = "blue"
elif col == 6: # 日曜日
elif col == 6:
fg_color = "red"
if day == 0: day_button = tk.Label(days_frame, text=" ", width=5, height=2) else: day_button = tk.Button(days_frame, text=str(day), width=5, height=2, fg=fg_color, command=lambda d=day: on_day_click(year, month, d)) day_button.grid(row=row+1, column=col)
# 日にちボタンがクリックされた時の処理
def on_day_click(year, month, day):
print(f"{year}年{month}月{day}日がクリックされました!") print("写真を表示します") show_images(year, month, day)
global current_page current_page = 0 # ページ番号をリセット show_images(year, month, day, current_page)
# 画像を表示する関数(複数画像対応) def show_images(year, month, day): global image_labels # 画像ラベルのリストをグローバル変数として宣言
def show_images(year, month, day, page): global current_page current_page = page
date_str = f"{year}-{month:02d}-{day:02d}"
# 既存の画像ラベルを削除
for widget in image_frame.winfo_children(): widget.destroy()
image_labels = [] # 新しい画像ラベルのリストを作成
images_per_page = 3 start_index = page * images_per_page + 1 end_index = start_index + images_per_page
image_exists = False
# 画像を順番に検索して表示 for i in range(1, 11): # 最大10枚の画像を表示(必要に応じてこの数を調整)
for i in range(start_index, end_index):
image_path = f"/home/pi/album/{date_str}_{i}.png"
if os.path.exists(image_path): image_exists = True try: img = Image.open(image_path)
img = img.resize((200, 200)) # 画像のサイズを調整
img = img.resize((200, 200))
img = ImageTk.PhotoImage(img)
# 画像番号を表示するラベル tk.Label(image_frame, text=f"{date_str}日{i}枚目").grid(row=0, column=i-1)
# 日付と画像番号を表示するラベル label = tk.Label(image_frame, text=f"{date_str} - {i}枚目", font=("Helvetica", 10)) label.grid(row=0, column=i - start_index)
# 画像ラベルを作成してフレームに配置 image_label = tk.Label(image_frame, image=img)
image_label.image = img # 参照を保持しておく必要がある image_label.grid(row=1, column=i-1) # 横に並べて表示 image_labels.append(image_label)
image_label.image = img image_label.grid(row=1, column=i - start_index)
except Exception as e: print(f"エラー: {e}. 画像 '{image_path}' の表示中に問題が発生しました") if not image_exists:
print(f"エラー: 画像 '{date_str}_n.png' が見つかりません")
tk.Label(image_frame, text="画像がありません").grid(row=0, column=0)
# 年と月を変更する関数
total_images = sum([os.path.exists(f"/home/pi/album/{date_str}_{i}.png") for i in range(1, 100)]) if total_images > images_per_page: if page > 0: prev_button = tk.Button(image_frame, text="←", command=lambda: show_images(year, month, day, page - 1)) prev_button.grid(row=2, column=0, pady=10, sticky="e") if end_index <= total_images: next_button = tk.Button(image_frame, text="→", command=lambda: show_images(year, month, day, page + 1)) next_button.grid(row=2, column=2, pady=10, sticky="w")
def update_calendar(): year = int(year_var.get()) month = int(month_var.get()) show_calendar(year, month)
# カレンダーを表示するフレームを作成
days_frame = tk.Frame(root) days_frame.grid(row=1, column=0, columnspan=7)
# 画像を表示するフレーム
image_frame = tk.Frame(root) image_frame.grid(row=2, column=0, columnspan=7)
# 年と月を選択するためのスピンボックス
year_var = tk.StringVar(value=current_year) month_var = tk.StringVar(value=current_month) year_spinbox = ttk.Spinbox(root, from_=1900, to=2100, textvariable=year_var, width=5) year_spinbox.grid(row=0, column=0, padx=5) month_spinbox = ttk.Spinbox(root, from_=1, to=12, textvariable=month_var, width=3) month_spinbox.grid(row=0, column=1, padx=5)
# 更新ボタン
update_button = ttk.Button(root, text="更新", command=update_calendar) update_button.grid(row=0, column=2)
# 起動時に現在のカレンダーを表示
show_calendar(current_year, current_month)
# メインループを開始
root.mainloop()
``` # ### カレンダーの写真を撮影するプログラム ディレクトリは/home/pi/album/を作成する ```arduino:写真撮影ソースコード # python3 # coding:utf-8 import os import sys import RPi.GPIO as GPIO import datetime from time import sleep from PIL import Image TSW = 24 # TrrigerSW(白SW)のBOAED番号 GPIO.setmode(GPIO.BCM) GPIO.setup(TSW, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) SAVE_DIR = '/home/pi/album/' print("CAMERA START") try: while True: if GPIO.input(TSW) == GPIO.HIGH: d = datetime.datetime.now() date_str = d.strftime('%Y-%m-%d') # 連番は指定フォルダのファイル数を元に設定 i = len([name for name in os.listdir(SAVE_DIR) if date_str in name]) + 1 temp_filename = 'temp_image.png' newfilename = f'{SAVE_DIR}{date_str}_{i}.png' # 写真撮影 os.system(f'libcamera-still -n -o {temp_filename} --width 1024 --height 768 --quality 100') # 画像回転処理 (expand=True で黒枠を防止) img = Image.open(temp_filename) img_rotate = img.rotate(90, expand=True) img_rotate.save(newfilename) # 一時ファイルの削除 os.remove(temp_filename) sleep(1) except KeyboardInterrupt: print("\nCAMERA STOP") GPIO.cleanup() sys.exit() ```
![キャプションを入力できます](https://camo.elchika.com/956ba42885756051fdc75a7df53529aa2cb6ebac/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32636533623233652d303536612d346635652d393838322d3338656530376633343434612f39613538643934312d623335332d343763662d383931332d643764303964373435396336/) 今回はIoT学習HATの白スイッチ(SW1)を使用します。 ## 参考文献 [初心者がラズパイにカメラつけて写真撮ってみた](https://inupy.com/raspi-008/) [IoT学習HATの入出力対応表](https://akizukidenshi.com/goodsaffix/iotlearninghatkit_io.pdf) #### まとめ >今回は、Raspberry Piのみの使用でしたが、次に作成するときには、iPhoneなどの写真をGoogle フォトなどを利用して今回作成したカレンダーの中に写真を入れていけるような物を作成したいと考えています。