今、話題の人工知能(AI)などで人気のPython。初心者に優しいとか言われていますが、全然優しくない! という事を、つらつら、愚痴っていきます

261.ラズパイ無双[8_VideoCapture]

»

初回:2022/6/15

 Raspberry Pi (ラズベリーパイ、通称"ラズパイ")で何か作ってみようという新シリーズです。今回からは『openCV』関連のシステム作りに取り掛かりたいと思います。まずは、カメラ画像の取込と表示の基本パターンを作ってみます。

P子「まずは基礎からって事ね」※1

【目次】

1.基本パターン

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cv2        # openCV のimport

################################################
# 動作確認用のテストプログラムです。
def main():
 cap = cv2.VideoCapture(0)   # デバイス 0 からの画像読取

 try:
  while True :
   ret,frame=cap.read()   # 戻り値は、読取成否と画像

   cv2.imshow('testCamera',frame) # 画面に画像を表示

   k = cv2.waitKey(10)    # キーボード入力待ち(10ms)
                # これがないと、画像が表示されない
   if k == ord('q') or k == 27: # q または、ESC で終了
    break

 except KeyboardInterrupt :   # Ctl+Cが押されたらループを終了
  print( "\nCtl+C Stop" )
 except Exception as ex:
  print( ex )      # 例外処理の内容をコンソールに表示
  import traceback
  traceback.print_exc()   # Exception のトレース
 finally :
  if cap is not None : cap.release() # 動画やカメラデバイスを閉じる
  cv2.destroyAllWindows()   # すべてのウィンドウを閉じる
  print( "終了" )

################################################
if __name__ == '__main__':
 main()

 コメントを入れていますので、解説は不要でしょう。

 cv2.VideoCapture(0) の 0 は、デバイス番号で、ラズパイにUSBカメラを1台付けた場合は、大抵0番で構いません。2台、3台とつないだ場合は、この番号が変わります。
 よく、1,2,3...と増えると言われていますが、私の環境では、2づつ(0,2,4...)という感じで増えましたので、そのあたりは色々試してみてください。

 ちなみに、USBカメラとデバイス番号の関係は、固定ではなく、認識順の様です。これを自動設定できるスクリプト等もあるようですが、ラズパイのOSによって変化するみたいなので、一筋縄ではいかなさそうです。

2.動画ファイルの読取

 動画ファイルを読み込む場合はVideoCapture()の引数に動画ファイルのパスを指定します。

 例) cap = cv2.VideoCapture('sample_video.mp4')

 動画ファイルのパスは、絶対パスでも相対パスでもOKです。動画の読取と、USBカメラからの入力を同じように扱えるというのは、非常に便利です。

≪一部抜粋≫
def main():
 file = "output.avi"
 cap = cv2.VideoCapture(file)   # ファイルのアドレスを指定します。

 cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

try:
#  while True : # ret でファイルの終了を判断する
  for i in range(cnt) :    # フレーム数だけループを回す
   ret,frame=cap.read()   # 戻り値は、読取成否と画像
 #  if not ret :       # ファイルから読め無くなれば終了
 #   break

   cv2.imshow('testCamera',frame) # 画面に画像を表示

   k = cv2.waitKey(10)   # キーボード入力待ち(10ms)
               # これがないと、画像が表示されない
   if k == ord('q') or k == 27: # q または、ESC で終了
    break
 ・・・・

 ファイルから読み取る場合は、カメラと異なり無制限ではありません。whileでループする場合は、cap.read()の戻り値で終了を判断します。
 または、先にフレーム数を求めておき、forループで回す方法もあります。

3.静止画ファイルの読取

 静止画を読み取る場合は、imread を使用します。

 例) img = cv2.imread('Lenna.png')

 Lenna.png というのは、画像処理の分野での標準画像と言われている画像です。

 ≪参考資料≫
  https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%8A_(%E7%94%BB%E5%83%8F%E3%83%87%E3%83%BC%E3%82%BF)
  レナ (画像データ)
  出典: フリー百科事典『ウィキペディア(Wikipedia)』

4.静止画ファイルの書込み

 読み取った画像を、openCV で色々と加工した後セーブしたいことがあると思います。まずは、静止画の保存方法からです。

 例) cv2.imwrite('Lenna.jpeg', img)

 先ほど読み取った『Lenna.png』を、jpeg形式で保存します。画像ファイルのフォーマットは、ファイルのパスの拡張子から自動的に決定されます。

≪一部抜粋≫
def main():
 try:
  img = cv2.imread('Lenna.png')

  height, width, ch = img.shape  # 画像の幅、高さ、チャネル
  size = width * height # img.size の画素数(カラーの場合 3倍)

  # 情報表示
  print("幅:", width)
  print("高さ:", height)
  print("チャンネル数:", ch)
  print("画素数:", size)
  print("データ型:", img.dtype)

  cv2.imshow('testCamera',img)  # 画面に画像を表示

  k = cv2.waitKey(0)     # 0 で無制限に待つ
  if k == ord('q') or k == 27:  # q または、ESC で終了
   return

  cv2.imwrite('Lenna.jpeg', img)  # 画像の書き出し
 ・・・・
 # VideoCapture が未使用なので、cap.release() 不要
 finally :
  cv2.destroyAllWindows()    # すべてのウィンドウを閉じる
  print( "終了" )

 ≪参考資料≫
  https://algorithm.joho.info/programming/python/opencv-image-width-height-channel-pixcels-py/
  【Python/OpenCV】画像の高さ・幅・チャンネル数・画素数を調べる方法

5.動画ファイルの書込み

 動画ファイルの生成は少し難しいです。というほどの事もありませんが、1行で済むというものではありません。

 ≪一部抜粋≫  cap = cv2.VideoCapture(0)    # デバイス 0 からの画像読取

 # 幅と高さとフレームレートを取得
 w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
 h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 fps = int(cap.get(cv2.CAP_PROP_FPS))

 fourcc = cv2.VideoWriter_fourcc(*'XVID')
 writer = cv2.VideoWriter('output.avi',fourcc, fps, (w,h))

# # 'M','P','4','V' または、*'MP4V' を指定します。
# fourcc = cv2.VideoWriter_fourcc('M','P','4','V')
# writer = cv2.VideoWriter('output.mp4',fourcc, fps, (w,h))

 try:
  while True :
   ret,frame=cap.read()   # 戻り値は、読取成否と画像

   writer.write(frame)    # イメージを書き込む

   cv2.imshow('testCamera',frame) # 画面に画像を表示

   k = cv2.waitKey(10)    # キーボード入力待ち(10ms)
           # これがないと、画像が表示されない
   if k == ord('q') or k == 27: # q または、ESC で終了
    break
 ・・・・
 # VideoWriter をオープンしているので、writer.release() が必要
 finally :
  if writer is not None : writer.release() # 動画やカメラデバイスを閉じる
  if cap is not None : cap.release() # 動画やカメラデバイスを閉じる
  cv2.destroyAllWindows()    # すべてのウィンドウを閉じる
  print( "終了" )

6.ストリーミングからの読取

 ネットワーク・カメラなどのRTSP(Real Time Streaming Protocol)の映像を読み取る場合も簡単です。

 例) rtsp = rtsp://user:password@ip:port/ipcam_h264.sdp
    cap = cv2.VideoCapture(rtsp)

 ≪参考資料≫
  https://www.roboticsware.com/dev-jp/faq/faq-96/
  ネットワークカメラに接続するためのURL

 httpプロトコルのストリーミングデータの受信も同様に簡単です。

 例) url = http://192.168.X.X:port/stream
    cap = cv2.VideoCapture(url)

 httpプロトコルのストリーミングデータの生成(ストリーミングサーバー)については、このシリーズ内で作成しますので、お楽しみに。

7.YouTubeからの読取

 YouTube の動画を読み取る場合は、追加のモジュールが必要です。
 pafy は、Youtube動画のURLをVideoCaptureで受信できるURLに変換できます。見るだけなら、これだけで十分です。
 youtube_dl は、YouTubeの動画をダウンロード・セーブできます。

$ pip install pafy
$ sudo pip install --upgrade youtube_dl

≪一部抜粋≫
import pafy
 # キャプチャするYouTube動画のURLを設定します
 url = "https://youtu.be/PaCyCcWseO4"

 video = pafy.new(url)
 best = video.getbest(preftype="mp4")
 cap = cv2.VideoCapture(best.url)

 ≪参考資料≫
  https://qiita.com/suo-takefumi/items/4c63399e39edecdcf323
  YouTube動画をOpenCVでキャプチャするスクリプト

 openCV で画像や動画を取り込むことができれば、各種画像処理を行うことができます。これは、本当にすごい事だと思います。

ほな、さいなら

======= <<注釈>>=======

※1 P子「まずは基礎からって事ね」
 P子とは、私があこがれているツンデレPythonの仮想女性の心の声です。

Comment(0)

コメント

コメントを投稿する