MENU
阿久澤のブログ
  • お問い合わせ
  • プロフィール

TP-Link|ネットワークカメラのRTSP映像を受信するexeファイルの作成

2024 7/13
テクノロジー・WEB周り
2024年7月13日
目次

目的

①下記の記事を参考にTP-Linkのネットワークカメラ4台をLAN内・OBSで視聴していたが、頻繁に画面が停止し、都度クリックして受信を再開させる必要があった。
https://qiita.com/takashima-yoi/items/4ae7bd535ddee91a33a9

②ispyなどのほかのソフトでは再現しないのでOBSの問題と思われる。

③全画面/4分割レイアウトでRTSP映像を常時表示できる既存ソフトはないため、自分でなんとかしたい。

概要

以下の要件を満たすexeファイルをChatGPTで生成する。

  • 1920*1080の映像を4つ受信し、左上・右上・左下・右下にレイアウト・リアルタイム再生する。
  • RTSPのURLはiniファイルで管理し、必要に応じて変更できるようにする。

生成プロンプト

GPT-4oで生成した。

以下のEXEファイルを生成したいです。できますか。

■機能
・rtspの映像データを受信し、ウィンドウ上に表示させる。
・映像データは4系統で受信する。
・受信するRTSPのURLは同ファイル下のiniファイルに入力する。
・映像データはFHD(1920*1080)で受信する。以下のレイアウトで表示したい。
  ①②
  ③④
・ウィンドウサイズに合わせて、①②③④はリサイズされること。

完成したもの・使い方

STEP
Pythonの公式サイトからPythonをインストール

以下からDL・インストールする。
インストール時に「Add Python to PATH」にチェックを入れることを忘れないように。
https://www.python.org/downloads

STEP
ライブラリのインストール

cmd>こちらのコマンドを実行する。

pip install opencv-python configparser pyinstaller
STEP
スクリプトの作成

任意の箇所にファイル名:display_rtsp.pyを作成し、以下をコピー。

import cv2
import configparser
import numpy as np

# INIファイルからRTSP URLを読み取る
config = configparser.ConfigParser()
config.read('streams.ini')

streams = [
    config.get('RTSP', 'stream1'),
    config.get('RTSP', 'stream2'),
    config.get('RTSP', 'stream3'),
    config.get('RTSP', 'stream4')
]

# 各ストリームに対応するVideoCaptureオブジェクトを作成
caps = [cv2.VideoCapture(url) for url in streams]

for i, cap in enumerate(caps):
    if not cap.isOpened():
        print(f"Failed to open stream {i+1}: {streams[i]}")
        exit(1)

def resize_frame(frame, size):
    return cv2.resize(frame, size)

# ウィンドウを作成(修正点1)
cv2.namedWindow('RTSP Streams', cv2.WINDOW_NORMAL)
cv2.resizeWindow('RTSP Streams', 1920, 1080)

while True:
    frames = []
    for cap in caps:
        ret, frame = cap.read()
        if not ret:
            continue
        frames.append(frame)
    
    if len(frames) < 4:
        continue

    # ウィンドウサイズを取得(修正点2)
    screen_width = cv2.getWindowImageRect('RTSP Streams')[2]
    screen_height = cv2.getWindowImageRect('RTSP Streams')[3]
    frame_width = screen_width // 2
    frame_height = screen_height // 2

    # 各フレームをリサイズ
    frames_resized = [resize_frame(frame, (frame_width, frame_height)) for frame in frames]

    # 4フレームを1つのウィンドウに配置
    top_row = np.hstack((frames_resized[0], frames_resized[1]))
    bottom_row = np.hstack((frames_resized[2], frames_resized[3]))
    combined_frame = np.vstack((top_row, bottom_row))

    cv2.imshow('RTSP Streams', combined_frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

for cap in caps:
    cap.release()
cv2.destroyAllWindows()
※Geminiによるコードレビュー:OK

コードレビュー

1. 全体的な印象

  • 要件を満たすコードであることは確認できました。
  • iniファイルからRTSP URLを読み込み、4つのストリームを別々のVideoCaptureオブジェクトで取得している点、フレームサイズをウィンドウサイズに合わせてリサイズしている点など、良い実装です。
  • いくつかの改善点と、潜在的な問題点が見受けられますので、以下に詳細を説明します。

2. 具体的な改善点

2.1 エラー処理

  • VideoCapture.isOpened()を使用して、ストリームが開けなかった場合のエラー処理を行っていますが、エラーメッセージにストリーム番号が含まれていません。
    • どのストリームが開けなかったのかを特定できるように、エラーメッセージにストリーム番号を含めるようにしましょう。
    • 例:print(f"Failed to open stream {i+1}: {streams[i]}")

2.2 フレーム取得のエラー処理

  • cap.read()でフレームを取得していますが、retがFalseの場合のエラー処理がありません。
    • フレーム取得に失敗した場合も、適切なエラー処理を行うようにしましょう。
    • 例:if not ret: continue

2.3 ウィンドウサイズの取得

  • cv2.getWindowImageRect('RTSP Streams')を使用してウィンドウサイズを取得していますが、この関数は非推奨です。
    • 代わりに、cv2.getWinProperty('RTSP Streams', cv2.WND_PROP_FRAME_WIDTH)とcv2.getWinProperty('RTSP Streams', cv2.WND_PROP_FRAME_HEIGHT)を使用して、フレームの幅と高さを取得するようにしましょう。

2.4 フレームのリサイズ

  • フレームのリサイズ処理で、np.hstackとnp.vstackを使用していますが、この方法ではメモリ使用量が多くなります。
    • cv2.resizeとcv2.hconcatを使用して、直接結合する方法の方が効率的です。

3. 潜在的な問題点

3.1 マルチスレッド処理

  • 4つのストリームを同時に処理していますが、マルチスレッド処理ではないため、CPU使用率が高くなる可能性があります。
    • 処理速度が遅くなる場合、マルチスレッド処理を検討しましょう。

3.2 フレームレート

  • フレームレートの制限が設けられていません。
    • 必要に応じて、cap.set(cv2.CAP_PROP_FPS, fps)`を使用してフレームレートを設定するようにしましょう。

4. その他

  • コード全体の可読性を向上させるために、コメントを追加することをおすすめします。
  • コードフォーマットを統一すると、読みやすくなります。

5. 改善例

Python

import cv2
import configparser
import numpy as np

# INIファイルからRTSP URLを読み取る
config = configparser.ConfigParser()
config.read('streams.ini')

streams = [
    config.get('RTSP', 'stream1'),
    config.get('RTSP', 'stream2'),
    config.get('RTSP', 'stream3'),
    config.get('RTSP', 'stream4')
]

def get_frame_size(window_name):
    width = cv2.getWinProperty(window_name, cv2.WND_PROP_FRAME_WIDTH)
    height = cv2.getWinProperty(window_name, cv2.WND_PROP_FRAME_HEIGHT)
    return width, height

def resize_frame(frame, size):
    return cv2.resize(frame, size)

def combine_frames(frames, frame_width, frame_height):
    top_row = np.hstack((resize_frame(frames[0], (frame_width, frame_height)),
                         resize_frame(frames[1], (frame_width, frame_height))))
    bottom_row = np.hstack((resize_frame(frames[2], (frame_width, frame_height)),
                         resize_frame(frames[3], (frame_width, frame_height))))
    combined_frame = np.vstack((top_row, bottom_row))
    return combined_frame

# 各ストリームに対応するVideoCaptureオブジェクトを作成
caps = [cv2.VideoCapture(url) for url in streams]

for i, cap in enumerate(caps):
    if not cap.isOpened():
        print(f"Failed to open stream {i+1}: {streams[i]}")
        exit(1)

# ウィンドウを作成
cv2.namedWindow('RTSP Streams', cv2.WINDOW_NORMAL)

while True:
    frames = []
STEP
exeファイル生成

cmdから下記コマンドを入力し、exeファイルを生成する。
※cmd上でディレクトリ指定してから行うこと。

pyinstaller --onefile display_rtsp.py
STEP
iniファイル作成

distフォルダ中にdisplay_rtsp.exeが生成される。
exeファイルと同層にファイル:streams.iniを作成し、以下を入力。

[RTSP]
stream1 = rtsp://example.com/stream1
stream2 = rtsp://example.com/stream2
stream3 = rtsp://example.com/stream3
stream4 = rtsp://example.com/stream4

※RTSPのURLは任意で修正

STEP
実行

クリックすると動作する。

感想

要件がクリアできて大満足。
ChatGPTの恩恵を感じる。

テクノロジー・WEB周り
  • 食べた:小麦の奴隷のカレーパン
  • 食べた:カリーマハール

コメント

コメント一覧 (1件)

  • akuzawa より:
    2024年7月15日 12:36 PM

    1台のカメラが落ちると全台止まる状態になっていた。要修正。

    返信

コメントする コメントをキャンセル

email confirm*

post date*

日本語が含まれない投稿は保存できませんのでご注意ください。(スパム対策)

カテゴリー
  • おすすめ (5)
  • お金・投資 (18)
  • テクノロジー・WEB周り (26)
  • モノ・買う・売る (46)
  • 一建設・リーブルガーデン (1)
  • 日記・考えの整理 (90)
  • 読む・観る (23)
  • 食べる・飲む (25)
アーカイブ
  • 2025年6月 (1)
  • 2025年5月 (5)
  • 2025年4月 (6)
  • 2025年3月 (3)
  • 2025年2月 (4)
  • 2025年1月 (5)
  • 2024年12月 (3)
  • 2024年10月 (14)
  • 2024年9月 (27)
  • 2024年8月 (29)
  • 2024年7月 (33)
  • 2024年6月 (41)
  • 2024年5月 (47)
  • 2024年4月 (11)
阿久澤
Webマーケター
群馬県前橋市在住のWebマーケター。
自社のSEOや広告運用を担当している。
→プロフィールへ
→お問い合わせへ
  1. ホーム
  2. テクノロジー・WEB周り
  3. TP-Link|ネットワークカメラのRTSP映像を受信するexeファイルの作成

© 阿久澤
※当ブログは広告を使用していません

目次