LoginSignup
3
5

More than 3 years have passed since last update.

Raspberry Pi3 Model B とWebカメラで遠隔撮影

Last updated at Posted at 2019-08-07

Raspberry Pi3 Model B と Webカメラで遠隔撮影

家にRaspberry PiとWebカメラが転がっていたので、大学の自由課題として作ってみました。
Linux系のOS使用したことがある人であれば、誰でも作れるような記事にする予定です。
初心者の人でもググりながらであれば、普通につくれると思います!

使用したもの

  • Raspberry Pi 3 Model B
    もしこれから買うのであれば、3 Model B+や4を買ったほうがいいかと思います!
    BはWi-Fiの5GHzに非対応なので、作業効率が結構悪かったです...

  • Logicool Webカメラ C525
    なんか中途半端な性能のWebカメラ...
    価格重視なら低価格なC270、性能重視なら...C910とかがおススメ?

  • Slack
    IT企業御用達のチャットツールです!
    今回はこのチャットツールで指示を出し、遠隔撮影させます。
    アカウントの作成は事前に済ませておいてくださいね!

  • 備品
    マウス、キーボード、モニター、電源ケーブル、HDMIケーブル、PC、MicroSDカード...など
    これらはRaspberry Piを使用するのに必要です。

下準備

以下の記事を参考に、Raspberry PiにNOOBSをインストール。
第56回「改めましてラズベリーパイの基本!(1) Raspberry Pi NOOBSインストール 2017年度版」

次に、プログラムを記述するためのエディターのインストール。
ラズベリーパイを使ってみる – 歴史あるエディタ emacs をインストールする –
端末にこれを打ち込みます。

$ sudo apt-get install emacs

各自お好みのテキストエディタを入れてください!
vimとか聞いたことないよ!って人は、emacsが無難かと思います。
ただ多少の癖はあります...
Emacsの使い方

python3にslackbotライブラリをインストール

$ sudo apt-get install python3-pip
$ sudo pip3 install slackbot
$ sudo apt-get install python3-opencv

ダウンロード成功!的な表示があれば大丈夫です。
もし、あとでうまくいかなかった場合、

$ sudo apt-get install slacker

も入れてみてください。

slackbotの設定

slackbotを動かすにあたって、以下のようなディレクトリ構造にします。

  • slack
    • run.py
    • slackbot_settings.py
    • plugins
      • __init__.py
      • take_picture.py

slackとpluginsはディレクトリになっています。
まず、ディレクトリを作ります。今回は、ホームディレクトリ直下に作成します。

$ cd ~/
$ mkdir slack
$ cd slack/
$ mkdir plugins

これで完成しました。次に、必要なPythonプログラムを作成します。

$ touch run.py slackbot_settings.py
$ cd plugins/
$ touch __init__.py take_picture.py

これで空のPythonファイルが作成できました!
これ以降はディレクトリ移動の記述をしないので、ここまでの作業で「cdって何??」と感じた人は、以下の記事を参考にしてください。
cdコマンド——ディレクトリの移動

Pythonプログラムの作成

まず、run.pyを仕上げます。slackディレクトリへ移動し、

$ emacs run.py & 

そして、出てきたエディタに以下を記述。

run.py

from slackbot.bot import Bot

def main():
    bot = Bot()
    bot.run()

if __name__ == '__main__':
    printf('launch slackbot')
    main()

同様にslackbot_settings.pyも作成します。

$ emacs slackbot_settings.py & 
slackbot_settings.py
API_TOKEN = "xoxv-156423218-651873211325-Asf44a4ds5f45AS552" #参考例です。各自で取得したトークン値を入力してください。

DEFAULT_REPLY = "わかりませーん..."

PLUGINS = ['plugins']

なお、Botの取得&トークンの作成は、以下のページを参考にしました。
PythonによるSlack bot作成
slackのbotを作る 入門編
Raspberry Piでslackbotを飼う

そして、pluginsディレクトリに移動し、take_picture.pyを作成します。

take_picture.py
from slackbot.bot import respond_to
from slackbot.bot import listen_to
from slackbot.bot import default_reply
from slacker import Slacker
import os
import cv2
import time

@respond_to('写真')
def picture_func(message):
    message.reply('撮影中...')


    #take_picture
    cap = cv2.VideoCapture(0)
    cap.read()
    time.sleep(1)

    ret, frame = cap.read()
    cv2.imwrite("/home/pi/slack/plugins/picture.jpg",frame)
    time.sleep(2)
    cap.release()
    time.sleep(2)


    #upload_picture

    TOKEN = "xoxv-156423218-651873211325-Asf44a4ds5f45AS552"
    #先ほどのトークンと同じものを記述
    CHANNEL = "APODV2HW1"
    #取得方法は後述

    file = "/home/pi/slack/plugins/picture.jpg"
    filename = 'webcam'

    message.reply('撮影完了...!')
    time.sleep(1)
    slacker = Slacker(TOKEN)
    slacker.files.upload(file_=file, channels=CHANNEL)

CHANNELの値は、PCでslackを開いたときのリンクの' 'で囲まれた部分です。私は#generalのCHANNEL値を取得しました。

https://app.slack.com/client/MQ18ALEJ/'APODV2HW1'/files

実行方法

slackディレクトリに移動し、

python3 run.py

を実行するだけです。そして、slackで以下のように指示すると写真が撮れます。

ちなみに、raspbotは自作Botの名前です。そしてiPhoneから命令出してます。早朝の真っ暗な部屋でモニターを撮影させています。

解説

run.py

実行プログラムです。このプログラムを実行すると、自作したBotが実行されます。

$ python3 run.py 

slackbot_settings.py

自作したBotが必要とするデータを格納しておくプログラムです。

  • API_TOKEN
    自作したBotの識別値

  • DEFAULT_REPLY
    このBot宛てのメッセージで、定義していない言葉が送られてきたときの反応

  • PLUGINS
    自作Botの機能拡張を行うプログラムの保存場所。この例では、~/slack/plugins/ディレクトリ内にあるプログラムも、run.pyの実行と同時に実行されます。

__init__.py

中身は空のプログラムです。

take_picture.py

ここで、自作Bot宛てに送られてきたメッセージ内容の判定、写真の撮影、slack上にアップロードのすべての処理を行っています。

  • @respond_to(' ') ' '内に囲まれた言葉(この例だと'写真')が送られてきた場合、以下に記述した処理(写真の撮影とアップロード)を行う。

-time.sleep(1)
()内に入れた秒数だけ次の処理の開始を遅らせる。少数も代入可能。

  • cap = cv2.VideoCapture(0)
    webカメラの割り当てを行う。()内に入れた数値で、どのカメラを使用するか決める。
    なお、1つしかカメラが接続されていない場合は0または-1を代入する必要がある。

  • ret, frame = cap.read()
    retにはTrue / False、frameには画像データが返される。

  • cv2.imwrite("/home/pi/slack/plugins/picture.jpg",frame)
    画像を指定した名前で指定したディレクトリに保存する。

  • cap.release()
    カメラの解放。

  • slacker.files.upload(file_=file, channels=CHANNEL)
    Slacker(TOKEN).files.upload(file_="/home/pi/slack/plugins/picture.jpg"
    , channels=CHANNEL)ということ。
    要するに画像アップロード処理。

補足説明

試行錯誤しながら作成したので、不要な部分が結構ありそうですが、多めに見てください...

__init__.py

このプログラムが置かれているディレクトリはパッケージとして扱われるそうです。あと、ここに初期化処理を記述することもできます。
なお、Python3.3以降ではこれが無くても、パッケージとして認識するそうなので、おそらく作成しなくても実行できると思いますが...慣習的なものなので作成しました。

' 'と" "の違い

Pythonにおいて、違いはありません。ごちゃ混ぜになってますが問題はありません。

take_picture部分の処理

take_picture.py
    cap = cv2.VideoCapture(0)
    cap.read()
    time.sleep(1)

    ret, frame = cap.read()

この部分では、1枚目の写真を撮った後1秒待ち、2枚目の写真を撮影し保存しています。このような処理をしている理由ですが、どこかでLogicoolのカメラはこのようにしたほうが良い、というような記事を見たからです。(どこのページだったか忘れたのでリンクはありません...ごめんなさいm(_ _)m)
そこで、実際に比較実験をしたところ、C525では目に見える差がありませんでした。よって気分でこの方法を使用しています。
もし、1秒でも短縮したい場合は、

take_picture.py
    cap = cv2.VideoCapture(0)
    #cap.read()
    #time.sleep(1)

    ret, frame = cap.read()

このようにコメントアウトでもしてください。

slackerについて

当初、画像アップロード処理中にエラーが多発していました。

requests.post(url = 'https://~~~ ',params = param, files = file)

で画像アップロード処理を行っていたんですが、デバッグをしたところ、この関数がうまく機能していなかったので、slackerでアップロード処理を行いました。ただし、requests.post()のほうが一般的っぽいです。

ipアドレスの固定化問題

sshログイン環境を整えるため、Raspberry Piのプライベートipアドレスを固定したところ、slackへの接続ができなくなってしまいました...slack側で設定をいじれば繋がる可能性がありますが、残念ながらslackに詳しくないため、ipアドレスの固定化を断念して使っています。

最後に

長文にお付き合いいただき、ありがとうございました!
おそらくこれで作れると思いますが、もし何かミスがあったらご指摘お願いします...!

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5