Raspberry PiをつかってNASアクセス式高解像度デジタルフォトフレームをつくろう．

#はじめに
**デジタルフォトフレーム**は2010年頃に登場した画期的な商品です。

![41TV4VNJFHL._AC_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629378/1421f118-0ac8-acd4-9309-387e1259dd15.jpeg)


それまで、撮った写真は焼いて飾っても額縁に一枚限りです。その他はアルバム化する必要がありましたし、そもそもよっぽどのことがないと見返すことはありません。

その点デジタルフォトフレームでは、保存した写真が自動でスライドショー化され、ふとした時に何かを思い出す最高のコンテンツといえます。

しかしながらこのフォトフレーム、思いのほか**低解像度**で**低容量**、いちいち写真をSDカードに入れたりクラウドにアップロードする**面倒な仕組み**から、あまり世間に浸透することはありませんでした。

（~~そもそも現代において写真とは詐欺と欺瞞と加工の事を差し、自己承認ツールの一部になってしまったためにフォトフレームを必要とする時代ではなくなってしまったんですね。~~）

とはいえこれまで撮ってきた写真、ありのままで見返すと色々思い出がよみがえって面白いですよね。

以上を踏まえると、**高解像度**で**大容量**、写真の扱いが**面倒でない**デジタルフォトフレームがあれば**QoLが上がる**に違いありません。

そこで今回はそんな素晴らしいデジタルフォトフレームを作ろうと思います。

最後までお付き合いいただけると幸いです。

#目標
実のところ、私にとって現在のデジタルフォトフレームがともかく使えないと感じていたのはその容量の無さと写真管理の面倒さでした。

**いちいちSDカードに保存とか面倒でたまらないし**、管理しなかったらしなかったで**永遠に同じ写真のスライドショー**は逆に腹が立ちます。

そこで今回は**NASサーバー**から写真を読み取る仕組みにして、写真アップロードや削除といった管理はすべてパソコンでできるようにして、直接手のかからないような仕組みを目指します。

今回はハードウェアに**Raspberry Pi3+**を、プログラム言語は**Python3**を用いました。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629378/ab8a790a-cf52-2bda-0db1-2dbc304ea3fc.png)

#システム
はじめに、ラズパイの設定やメンテナンスも直接手を触れずにやっていきたいので**SSHは有効**にしておきましょう。※なお、この際にデフォルトのUN/PWで運用すると警告が邪魔になるので変更推奨です。

https://qiita.com/tomokin966/items/bc22d09f97ebeb3955d2

つぎに、ラズベリーパイに**NASを自動でマウントする設定**をしておきましょう。

https://raspi-katsuyou.com/index.php/2020/12/27/19/00/42/2331/

一定時間たってもモニターが暗くならないように**スリープモードは解除**しておきます。

https://rikoubou.hatenablog.com/entry/2020/06/11/133716

また今回使用したRaspberry Pi3+はPi4用の最新OSを使用すると、仕様の変化から2.4Aの電源では警告が表示されるようになります。構造上は問題ありませんが、目障りなので消しておきましょう。

https://qiita.com/nayuki_eng/items/3180da7ea0e4adab4e6c

今後、だれが使っても便利なように**システムは自動で起動**するように登録しておきましょう。(Pythonコードが完成した後)

https://www.shujima.work/entry/2017/09/23/160300

ちなみにAutoStartを使用した場合に、何故かホームディレクトリ直下のファイルしか起動しないことがあります。上手く起動しなかった人は`/home/pi/hogehoge.py`において設定してみると良いかもしれません。

#プログラム
使用したプログラム言語はPython3です。早速、解説していきます。

ほとんどのソースコードは前回の記事、

https://qiita.com/Yurix/items/16a9036a0cb278b82652

ここから流用しました。

```python:Liberary
from PIL import Image, ImageTk

import tkinter
import threading
import random
import time
import os

path = '/mnt/nas/Camera/PhotoFrame/'  #NAS上の写真フォルダの場所
```

使用したライブラリは上記のとおりです。基本的に`tkinter`でUI管理、`threading`でスライドショーという構造です。

`path`はマウントしたNASの画像ファイルの場所を指しています。したがって各々任意に設定してください。

```python:Window
def window():

    global canvas, item

    root = tkinter.Tk()
    root.title()

    root.geometry("1920x1080")  # ウインドウサイズ指定
    root.configure(background='black')
    root.attributes("-fullscreen", True)  # フルスクリーン化用

    canvas = tkinter.Canvas(bg="black", width=1920, height=1080)
    canvas.place(x=-1, y=-1)

    img = Image.open('image.png')  #はじめに表示させる起動画面画像（タイトル的な？）
    img = ImageTk.PhotoImage(img)

    item = canvas.create_image(0, 0, image=img, anchor=tkinter.NW)

    root.mainloop()
```

こちらは窓（UI）の設定に関する関数です。使用するモニターにあわせて解像度は調整してください。今回は手元のモニターがFull HDだったのでこういう値になっております。

またフルスクリーンは動作確認した後に適応することをお勧めします。さもなくばエラーが生じたときにわかりにくくて不便ですから。

`img`はウインドウを設定するのに必要です。プログラムと同一ディレクトリ上に任意の画像を用意してください。ただし映るのは起動後の一瞬だけで、その後は再起動するまでは現れることはありません。適当でいいってことですね。

```python:Repeat
def repeat():

    dir_list = os.listdir(path)  #写真の総数をリストへ

    i = random.randrange(len(dir_list))  #写真の総数の長さまでの間でランダムな値を生成

    img = Image.open(path + dir_list[i])  #ランダムな写真を取得
    resize = img.resize((1920, 1080))  #画面サイズに合わせてリサイズ
    img_resize = ImageTk.PhotoImage(resize)

    canvas.itemconfig(item, image=img_resize)
    time.sleep(120)  #画像が切り替わる時間

    dir_list.clear()  #リストをクリア
```

ここではメインのスライドショーのコードとなるわけですが、このコードではいちいち一枚表示するごとにリストを再生成させて面倒じゃね？とか、`randam`に偏りがあったら同じ写真ばっかりでない？とかいろいろ思われるかと思います。

ちなみに全くその通りです。リストは写真の数が多ければ多いほど生成に時間がかかり、写真の切り替えに時間を要するようになります。またランダム関数には一般的に偏りは無いといわれておりますが、見ている限りは相当低い確率の写真の組み合わせが多々生じているので、確かに偏っているように感じます。

しかしながら、こうすることでシステム稼働中の画像の追加や削除が、エラー無く実行することができます。理論上は任意のNASフォルダの中に写真が一枚でもあれば問題ありません。

これは**システムに疎い人が写真アルバムを扱ってもあまり問題が起きないようにしたかったため**、です。

ちなみにリサイズ処理はどんな画像もこのサイズになるので、縦長の画像とか比率があってないと中々すごいことになります。ここの処理はもう少しなんとかできるかと思いますが、面倒なので今回はこのまま放置しておきます。大体解像度の高い写真は大丈夫そうですね。

```python:PhotoFrame
thread = threading.Thread(target=window)
thread.start()

while True:
    repeat()
```

最後にスレッドを立ち上げてスライドショーを繰り返して終了（開始）です。

#まとめ
![IMG_20211222_094118.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629378/48d3cce2-39cf-2193-318b-fe40af810d2f.jpeg)
↑我が家ではこんな感じに運用されています。
思いのほか高解像度であり、またNASの大容量写真フォルダの中から**はるか彼方に忘れていた写真**が表示されたときなどは、懐かしくもあり話のタネにもなるので大いに役立っています。

今のところ重大な欠陥やエラー等は起きていません。自宅のローカルエリアネットワーク上の使用ではスムーズに事（**画像**）が運ぶようです。

しかしながら…現代ではスマートフォンのカメラ機能の向上とその便利さ故からか、あまりにも写真を撮りすぎて**身に覚えのない写真**とか急に表示されます。その間の120秒は**ホラー**です。

NASの画像フォルダの容量以上に、人間の脳みそは低容量のようですね。