Raspberry Pi+PythonでLINE通知付きセキュリティカメラを自作する方法【1万円以下】
Raspberry PiとPythonを使った自作セキュリティカメラを作りたいと思っていませんか?「外出中に自宅の様子が気になる」「不審者が来たらすぐに知りたい」——そんな悩みを、1万円以下・Pythonコード数十行で解決できます。
この記事では、Raspberry Pi+OpenCVによる動体検知とLINE通知を組み合わせたIoTセキュリティシステムの作り方を、初〜中級者向けにステップごとに丁寧に解説します。完成すれば、不審な動きを検知した瞬間にLINEへ画像付き通知が届く本格的なシステムの出来上がりです!
⚠️ 重要:LINE Notifyは2025年3月末で正式にサービス終了しました。本記事では後継のLINE Messaging APIを使って解説します。
Raspberry Piセキュリティカメラに必要なものリスト
ハードウェア一覧
- Raspberry Pi 4(または3B+)
- Raspberry Pi Camera Module v2(または互換カメラ)
- microSDカード(16GB以上・Class10推奨)
- 電源アダプター(USB-C、5V/3A)
ソフトウェア・サービス一覧
- Raspberry Pi OS(最新版 Bookworm推奨)
- Python 3.8以上
- OpenCV(動体検知ライブラリ)
- LINE Messaging API(無料枠:月200通)
カメラモジュールはAmazonで2,000〜3,000円程度で購入できます。Raspberry Pi本体(5,000〜7,000円前後)と合わせても合計1万円前後でセキュリティカメラが完成します。市販のIPカメラ(1〜3万円)と比べてもコスパは抜群です。
【手順1】LINE Messaging APIのチャンネルを準備する
LINE Developersコンソールで、通知用の「Messaging API」チャンネルを作成します。10分程度で完了します。
- LINE Developersコンソールにログインし、プロバイダーを新規作成(または既存のものを選択)
- 「Messaging API」チャンネルを新規作成
- チャンネル基本設定タブの下部で「チャンネルアクセストークン(長期)」を発行してメモしておく
- 作成したチャンネルをLINEアプリで友だち追加(チャンネル基本設定タブのQRコードから)
- 自分のuserIdを取得する(Webhookを一時的に有効化し、友だち追加時に送られてくるイベントのJSONから
source.userIdを確認するのが簡単です)
チャンネルアクセストークンとuserIdの2つをPythonスクリプトに設定することで、Raspberry PiからLINEへ通知を送れるようになります。
【手順2】Raspberry Piの開発環境をセットアップする
Raspberry Pi OSのインストールが完了したら、OpenCVをはじめとする必要なPythonライブラリをインストールします。ターミナルで以下のコマンドを順番に実行してください。
# システムのアップデート(必ず最初に実行)
sudo apt update && sudo apt full-upgrade -y
# OpenCV・requests・picamera2をaptでインストール
# Bookworm以降はPEP 668によりシステム全体へのpip installが拒否されるため、aptを使う
sudo apt install -y python3-opencv python3-requests python3-picamera2
インストール完了後、カメラモジュールが正しく認識されているか確認しましょう。以下のコマンドを実行してプレビューウィンドウが開けばカメラの接続はOKです。
rpicam-hello
カメラが認識されない場合は、Bookworm以降はカメラが自動検出されるため、sudo raspi-configの「Interface Options」に「Camera」項目はありません。rpicam-hello --list-camerasでカメラが一覧に表示されるか確認してください。
【手順3】OpenCVで動体検知+LINE通知Pythonスクリプトを作成する
いよいよ動体検知とLINE通知を組み合わせたメインのPythonスクリプトを作成します。仕組みはシンプルで、連続する2フレームの差分をOpenCVで計算し、変化量が閾値を超えたら動体と判定してLINEに画像付き通知を送信します。
import cv2
import requests
import time
import os
from picamera2 import Picamera2
from datetime import datetime
# ===== 設定エリア =====
CHANNEL_ACCESS_TOKEN = "ここにMessaging APIのチャンネルアクセストークンを貼り付ける"
LINE_USER_ID = "ここに自分のuserIdを貼り付ける"
THRESHOLD = 3000 # 動体検知の感度(数値が小さいほど敏感・誤検知注意)
COOL_TIME = 30 # 通知クールタイム(秒)連続通知を防止
SAVE_PATH = "/home/pi/security/"
# =====================
# 保存先ディレクトリの作成
os.makedirs(SAVE_PATH, exist_ok=True)
def send_line_notify(message, image_path=None):
"""LINE Messaging APIでプッシュ通知を送信する関数(テキストのみ)
image_pathはローカル保存パスの案内用。画像そのものをLINEに添付するには、
originalContentUrlに指定できる公開HTTPS URLへ画像を置く必要があるため、
本記事の基本実装ではテキスト通知のみを行う(応用編を参照)。"""
url = "https://api.line.me/v2/bot/message/push"
headers = {
"Authorization": f"Bearer {CHANNEL_ACCESS_TOKEN}",
"Content-Type": "application/json",
}
if image_path:
message = f"{message}\n画像: {image_path}"
payload = {
"to": LINE_USER_ID,
"messages": [{"type": "text", "text": message}],
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
print(f"[LINE通知] 送信成功: {message}")
else:
print(f"[LINE通知] 送信失敗: ステータスコード {response.status_code} / {response.text}")
def detect_motion():
"""動体検知のメインループ"""
picam2 = Picamera2()
config = picam2.create_preview_configuration(
main={"size": (640, 480), "format": "RGB888"}
)
picam2.configure(config)
picam2.start()
time.sleep(2) # カメラ安定待ち
print("[セキュリティカメラ] 動体検知を開始します...")
prev_frame = None
last_notify = 0 # 最後に通知した時刻
try:
while True:
# フレーム取得とグレースケール変換
frame = picam2.capture_array()
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray_frame = cv2.GaussianBlur(gray_frame, (21, 21), 0)
if prev_frame is None:
prev_frame = gray_frame
continue
# フレーム差分で動体を検知
diff = cv2.absdiff(prev_frame, gray_frame)
_, thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)
motion_score = cv2.countNonZero(thresh)
if motion_score > THRESHOLD:
current_time = time.time()
# クールタイムが経過していれば通知
if current_time - last_notify > COOL_TIME:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
image_path = f"{SAVE_PATH}motion_{timestamp}.jpg"
# Picamera2の"RGB888"は配列上BGR順なので、そのまま保存できる
cv2.imwrite(image_path, frame)
message = f"\n🚨 動体を検知しました!\n日時: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\nスコア: {motion_score}"
send_line_notify(message, image_path)
last_notify = current_time
print(f"[検知] スコア: {motion_score} / 画像保存: {image_path}")
prev_frame = gray_frame
time.sleep(0.5) # CPU負荷軽減
except KeyboardInterrupt:
print("\n[セキュリティカメラ] 停止しました。")
finally:
picam2.stop()
cv2.destroyAllWindows()
if __name__ == "__main__":
detect_motion()
スクリプトの主要パラメーターを調整する
スクリプト上部の設定エリアにある3つのパラメーターを環境に合わせてチューニングしましょう。
| パラメーター | デフォルト値 | 説明・調整の目安 |
|---|---|---|
THRESHOLD |
3000 | 動体検知の感度。室内なら2000〜4000、屋外(風・木の揺れあり)なら15000〜30000が目安 |
COOL_TIME |
30秒 | 連続通知を防ぐクールタイム。頻繁に通知が届く場合は60〜120秒に延ばす |
SAVE_PATH |
/home/pi/security/ | 検知画像の保存先。SDカード容量に注意し、定期的な削除スクリプトの併用を推奨 |
【手順4】スクリプトをSystemdで自動起動させる
毎回手動でスクリプトを起動するのは不便です。Systemdサービスとして登録することで、Raspberry Pi起動時に自動でセキュリティカメラが立ち上がるようになります。
# サービスファイルを作成
sudo nano /etc/systemd/system/security-camera.service
エディタが開いたら、以下の内容を貼り付けてください(UserとExecStartのパスは環境に合わせて変更)。
[Unit]
Description=Raspberry Pi Security Camera with LINE Notify
After=network.target
[Service]
User=pi
WorkingDirectory=/home/pi
ExecStart=/usr/bin/python3 /home/pi/security_camera.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
# サービスを有効化して起動
sudo systemctl daemon-reload
sudo systemctl enable security-camera.service
sudo systemctl start security-camera.service
# 動作状態の確認
sudo systemctl status security-camera.service
Active: active (running) と表示されれば自動起動の設定は完了です。これでRaspberry Piの電源を入れるだけでセキュリティカメラが稼働します。
動体検知の精度を上げるチューニングテクニック
基本的なシステムが完成したら、OpenCVのパラメーター調整で動体検知の精度をさらに高めましょう。
輪郭検出で人物・物体を絞り込む
現在の実装はピクセル差分の総量で判定していますが、cv2.findContours()を追加することで動いている物体の輪郭サイズを基準にでき、虫や照明変化による誤検知を大幅に減らせます。
# 輪郭検出で人物サイズの動体のみ検知
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# 輪郭の面積が小さい場合は無視(虫・ノイズ対策)
if cv2.contourArea(contour) < 1500:
continue
# 人物サイズの動体を検知した場合のみ通知処理へ
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# → 通知処理をここに移動
夜間・暗所での検知精度を高める
暗所での誤検知が多い場合は、ガウシアンブラーのカーネルサイズを大きく(例:41×41)してノイズを除去するか、Raspberry Pi NoIRカメラと赤外線LEDを組み合わせる方法が有効です。
よくある質問・トラブルシューティング
Q. LINE通知が届かない
A. 以下の順番で確認してください。①トークンが正しくコピーされているか(前後にスペースが入っていないか)②Raspberry PiがWi-Fiまたは有線LANでインターネットに接続されているか③response.status_codeをprintして401(認証エラー)か400(リクエストエラー)かを特定する。
Q. 誤検知が多すぎる(通知が頻繁に届く)
A. THRESHOLDの値を段階的に上げてください(3000→8000→15000)。屋外設置の場合は木の葉の揺れや光の変化が誤検知の主原因になるため、15000〜30000程度が現実的な設定値です。またCOOL_TIMEを60秒以上に延ばすことで通知頻度も抑えられます。
Q. Raspberry Pi 5でも動作するか
A. 動作します。Raspberry Pi 5はCSIコネクタの仕様が変更されているため、公式のFPC変換ケーブルが別途必要になる場合があります。picamera2のバージョンを最新(sudo apt update && sudo apt install --only-upgrade -y python3-picamera2)にしてから動作確認することを推奨します。
応用:検知画像もLINEに直接添付する
本記事の基本実装では、検知時にLINEへ送るのはテキスト通知のみで、画像はRaspberry Pi上(SAVE_PATH)に保存されます。画像そのものをLINEメッセージに添付するには、画像を一時的に公開HTTPS URLで配信できるようにする必要があります(例:Flaskで画像を配信し、Cloudflare Tunnelで外部公開する)。LINE Messaging APIの実装全般(チャンネル作成からメッセージ送信まで)は「PythonでLINE Messaging APIを使ってBot・通知を自作する方法【完全ガイド2026】」でより詳しく解説しています。
まとめ:Raspberry Pi+PythonでセキュリティカメラをDIYしよう
この記事で解説した手順をおさらいします。
- ✅ LINE Messaging APIのチャンネルを準備してPythonから通知を送れる状態にする
- ✅ OpenCV・picamera2をインストールしてRaspberry Piの開発環境を整える
- ✅ フレーム差分による動体検知スクリプトを作成・動作確認する
- ✅ Systemdで自動起動を設定して運用を安定させる
- ✅ 輪郭検出・感度調整で誤検知を減らしてチューニングする
Raspberry PiとPythonを使った自作セキュリティカメラは、IoT・電子工作の入門プロジェクトとして最適です。OpenCVの動体検知やLINE APIの活用を通じて、実践的なPythonプログラミングスキルも身につきます。ぜひ自宅のセキュリティ強化に役立ててください!
次のステップとして、Raspberry Pi + PythonでIoT温湿度ダッシュボードを自作する方法もあわせてご覧ください。
📡 Arduinoをもっと深く学ぼう!
Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。
📚 関連記事
- Raspberry Pi + PythonでIoTダッシュボードを自作|DHT11温湿度センサーで自宅をリアルタイム監視— Raspberry Pi+Pythonでのセンサー活用とリアルタイム監視の実装方法
- ArduinoとPython連携で作るIoT入門|センサーデータをリアルタイム可視化しよう— Pythonでのセンサーデータリアルタイム処理の基礎
- 【初心者OK】PythonとTeachable Machineでじゃんけんを認識!AIと対戦するカメラアプリの作り方— OpenCV+Pythonのカメラ処理とAI連携の実装パターン
- Pythonで動く顔にモザイクをかける方法|OpenCVコピペスクリプト完全解説— OpenCVによるリアルタイムカメラ映像処理の具体例
こちらも読まれています
📡 Arduinoをもっと深く学ぼう!
Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。
📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。




