Help us understand the problem. What is going on with this article?

HeadlessなRaspberry Pi 3でJupyter notebookを自動起動させてOpenCVを使うまで

目標設定

HeadlessなRaspberry Pi3 Model Bを想定し,以下を実現することを目指す.

  • Jupyter notebookが自動起動し,リモートPCからの接続を受け付ける.
    • LANなしでPCと1対1で繋いでも,LANを介して繋いでもJupyterに接続できる.
  • PythonからOpenCVを使うことができる.

想定する環境

  1. RPi3 : Raspberry Pi3本体
  2. PC : RPi3を操作するためのWindows / macOS / Linux機

の2つのデバイスが同一ネットワークに接続されているとする.より具体的には

  1. RPi3とPCがハブを介して接続している
  2. RPi3とPCが有線で1:1接続されている

のどちらでもよいとする.またPCが特にWindowsの場合は,Bonjour for Windowsをインストールしておくこととする.これはRPi3のIPアドレスが不明の場合でも,raspberrypi.localという名前でアクセスできるようにするため(Raspbianのavahiデーモンが実現している機能).

制限事項

以下の点はあえて解決しないままとする.

  • セキュリティについては必要最低限のまま(外部公開は想定しない).
  • インストールがすべて終わった状態であればPCと1:1接続した際にインターネット接続がなくてもOKだが,インストール中はパッケージやソースコードをダウンロードするためにインターネット接続が必要.最初からPCと1:1接続する場合は,PC側でNATしてあげる必要がある.
    • Windowsなら「インターネット接続の共有(ICS)」機能を使う.例えばPCが無線LANでインターネットに接続されているなら,無線インターフェースで「インターネット接続の共有」を有効にし,その際に「ホームネットワーク接続」としてRPiと接続している有線インタフェースを指定する.この設定を行うと「ホームネットワーク接続」で有効にしたインタフェースでDHCPサーバが動き始めるので,一度RPiとのLANケーブルを抜き差しすればRPiにDHCPでアドレスが割り当てられる.インストール後にインターネット接続の共有を解除してもよいし,このまま使い続けてもよい.
  • RPi3を無線LANで接続しない.
    • 無線LANのパスワードなどを設定する必要があるので,今回はパス.
  • LANに複数台のRaspberry Piが存在する場合,raspberrypi.localがどのデバイスになるかは予測しがたい.LANには今回使用する1台だけが存在すると仮定する.

初期設定

以下ではOSとしてRaspbianを新規インストール,つまりディスクイメージをSDカードに書きこむところからスタートすることとする.

RaspbianのインストールとSSHアクセスの有効化

  1. RasobianをMicroSDにインストール.
    • RASPBIAN STRETCH WITH DESKTOP (Version:November 2017)を使用.
    • 実際にはWindowsで作業したので,MicroSDのパーティションを全部消して(「コンピュータの管理」内の「ディスクの管理」より),SD Formatterでフォーマットしてから,Win32 Disk ImagerでOSイメージを書き込んだ.
  2. MicroSDをPCでマウントし,第1パーティション(FAT32.ラベルは「boot」.Windowsなら「boot」というボリューム名のついたドライブに見える)にsshという名前の空のファイルを作る.
  3. RPiを起動

SSH接続

上記のようにbootパーティションにsshというファイルが存在すると,ブート時にsshデーモンが起動する.そこでPCから

> ssh pi@raspberrypi.local

としてssh接続をする(デフォルトのユーザpiの初期パスワードはraspberry).なおPCがWindowsの場合,

などを使うことができるが,BoW環境のsshでは接続できない(/etc/resolv.confにDNSサーバが直書きされているからmDNSで名前解決できない?).

そのほかの設定

  1. 以下のインストール作業にはそれなりの時間がかかるので,tmuxをインストールしておいて適宜detouchできるようにする.
  2. 必要に応じてlv, vimもインストールしておく.

Jupyter

インストール

pipでインストールする.

$ sudo apt-get update 
$ sudo apt-get upgrade 
$ sudo apt-get install python3 python3-dev build-essential python-pip 
$ sudo pip3 install --upgrade pip 
$ sudo pip3 install jupyter 

設定

JNSを参考にJupyterの設定ファイル(~/.jupyter/jupyter_notebook_config.py)を作る以下のスクリプトを作成して実行する.ただしパスワードは別途設定することにしてここでは書き込まない.

configure_jupyter.sh
#!/bin/bash
# script name:     configure_jupyter.sh
# last modified:   2017/03/05
# sudo:            no

if [ $(id -u) = 0 ]
then
   echo "to be run as $(logname)"
   exit 1
fi

# generate config and create notebook directory
# if notebook directory exists, we keep it (-p)
# if configuration file exeists, we overwrite it (-y)

jupyter notebook -y --generate-config
cd $home
mkdir -p notebooks  

target=~/.jupyter/jupyter_notebook_config.py

# set up dictionary of changes for jupyter_config.py
declare -A arr
app='c.NotebookApp' 
arr+=(["$app.open_browser"]="$app.open_browser = False")
arr+=(["$app.ip"]="$app.ip ='*'")
arr+=(["$app.port"]="$app.port = 8888")
arr+=(["$app.enable_mathjax"]="$app.enable_mathjax = True")
arr+=(["$app.notebook_dir"]="$app.notebook_dir = '/home/$(logname)/notebooks'")
#arr+=(["$app.password"]="$app.password =\
#'sha1:81f7fe53c0e5:0c1ddb2ff6bb83d83639c29e4cf6b4cb30ff7617'")

# apply changes to jupyter_notebook_config.py

# change or append
for key in ${!arr[@]};do
    if grep -qF $key ${target}; then
        # key found -> replace line
        sed -i "/${key}/c ${arr[${key}]}" $target
    else
        # key not found -> append line
        echo "${arr[${key}]}" >> $target
    fi
done

続いてパスワードを設定する.パスワードを設定しないと,毎回ランダムに決まるトークンを入力するように促されるのでかえって面倒.

$ jupyter notebook password
Enter password:
Verify password:
[NotebookPasswordApp] Wrote hashed password to /home/pi/.jupyter/jupyter_notebook_config.json

自動起動

Jupyterが自動起動するように設定(参考にしたサイト:https://qiita.com/mt08/items/edb9bcaeaa416d3e5319 ).

/etc/systemd/system/jupyter.service
[Unit]
Description=Jupyter notebook

[Service]
Type=simple
PIDFile=/var/run/jupyter-notebook.pid
ExecStart=/usr/local/bin/jupyter notebook
User=pi
Group=pi
WorkingDirectory=/home/pi/notebooks
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl start jupyter
sudo systemctl enable jupyter
sudo systemctl status jupyter

接続テスト

ここまででwebブラウザから http://raspberrypi.local:8888/ にアクセスすると,パスワードを入力する画面が表示されるはずである.接続できない場合,webブラウザのプロキシ設定も確認すること.

OpenCV

ここを参考にソースからビルドする(だいたいコンパイルに約2時間かかる.MicroSDのスピード次第?).ただしgcc-6の場合はエラーが出るので,途中でcmake/OpenCVPCHSupport.cmake

-    SET(_PCH_isystem_prefix "-isystem")
+    SET(_PCH_isystem_prefix "-I")

を入れる点に注意(参考:OpenCV Issue #6517, OpenLightingProject Issue #1125).

build_opencv.sh
sudo apt-get install -y build-essential cmake pkg-config
sudo apt-get install -y libjpeg-dev libtiff5-dev libjasper-dev libpng-dev
sudo apt-get install -y libatlas-base-dev gfortran libeigen3-dev
sudo apt-get install -y libgtk2.0-dev
sudo apt-get install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev
wget -O - http://github.com/opencv/opencv/archive/3.4.0.zip > opencv.zip
unzip opencv.zip
cd ~/opencv-3.4.0/

cat<<EOD | patch -p1
--- opencv-3.4.0.orig/cmake/OpenCVPCHSupport.cmake   2017-12-31 15:29:51.550167481 +0000
+++ opencv-3.4.0/cmake/OpenCVPCHSupport.cmake        2017-12-31 15:30:00.500101155 +0000
@@ -24,7 +24,7 @@
     ENDIF()

     SET(_PCH_include_prefix "-I")
-    SET(_PCH_isystem_prefix "-isystem")
+    SET(_PCH_isystem_prefix "-I")
     SET(_PCH_define_prefix "-D")

 ELSEIF(CMAKE_GENERATOR MATCHES "^Visual.*$")
EOD

mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D BUILD_EXAMPLES=ON ..
make -j4
sudo make install
sudo ldconfig

そのほかのパッケージ

$ sudo pip3 install matplotlib scipy pandas scikit-learn scikit-image plotly

pandasのインストールにはそれなりの時間がかかる(1時間くらい).

動作確認

webブラウザで http://raspberrypi.local:8888/ にアクセスして,新しいnotebookを作る.以下を実行できればOK.

test.ipynb
import numpy as np
import cv2
import matplotlib.pyplot as plt

print(cv2.__version__)

保存

この時点でのMicroSDをイメージファイルとして保存しておくと,同じことを他のRPiで行いたいときに便利かもしれない.Win32 Disk Imagerを使う場合,MicroSDに2つのパーティションがあるのでどちらのドライブを選択すれば…と迷うが,どちらでもよい.Read Only Allocated Partitionsにはチェックを入れること(そうしないと微妙にサイズが異なるMicroSDに書き込めなくなるというか,そういうことが無いように最初からやや小さめのパーティションを作っておくべきだし,バックアップするときもそれを反映させなさい,ということか?).

nbhr
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away