LoginSignup
33
30

More than 3 years have passed since last update.

OpenCVの動画コーデック

Posted at

はじめに

なめらかな動画をとるためには、フレームレートを上げる必要があります。
動画圧縮のコーデックによっては、フレームレートが上がらないことがあります。
そこで、OpenCVでのコーデック情報の取得と、コーデックの変更方法についてメモとして記載します。

参考:
OpenCVのカメラ読み込みを高速化し、遅延時間も短くする
OpenCVからWebカメラの「解像度」「FPS」及び、「フォーマット(コーディック)」を設定する方法

動作環境

Win10 Pro 64 bit
Python 3.7
Anaconda
OpenCV 4.2 (conda-forgeでインストール)

動画コーデック

動画を保存する際に、データ量が非常に大きいためにデータの圧縮を行います。この圧縮アルゴリズムがコーデックです。圧縮アルゴリズムにはいろいろあり、そのアルゴリズムに基づいて動画の拡張子(.mp4、.avi)が決まります。

参考:
動画コーデックをマスターしよう
【コーデック】とは?動画・音声コーデックそしてコンテナ(動画形式)

動画コーデックの種類

代表的なものとしては、
H.264(.mp4)・・・ 高画質動画の主流となっている規格
MPEG-2(.mpg)・・・テレビのデジタル放送を中心に利用
MPEG-4(.mpg .mp4)・・・モバイル機器でのネット動画の視聴を想定し開発された規格
など

参考:
OpenCVのVideoWriterを使って画像から動画を作る。
動画コーデックの種類と違い(H.264・VP9・MPEG・Xvid・DivX・WMV等)【比較】

OpenCVでカメラのコーデックを調べる

OpenCVでは、カメラの設定条件を調べたり、機種によっては設定することができます。

参考:
Python, OpenCVで動画を読み込み(ファイル・カメラ映像)
Pythonでカメラを制御する【研究用】

OpenCVにおけるコーデックの確認方法

import cv2

cap = cv2.VideoCapture(0)   #カメラ番号を指定

#戻り値はDuble型なのでInt型に変換する
fourcc_int = int(cap.get(cv2.CAP_PROP_FOURCC))
cap.release()

print("fourcc_int",fourcc_int)
#>>>fourcc_int 842094158

#Four codec characterに変換する方法1
fourcc = list((fourcc_int.to_bytes(4, 'little').decode('utf-8')))
print(fourcc)
#>>>['N', 'V', '1', '2']

print("fourcc_string",fourcc_int.to_bytes(4, 'little').decode('utf-8'))
#>>>fourcc_string NV12

#Four codec charactersに変換する方法2
fourcc = [chr((fourcc_int >> 8 * i) & 0xFF) for i in range(4)]
print(fourcc)
#>>>['N', 'V', '1', '2']

print("fourcc_string", "".join([chr((fourcc_int >> 8 * i) & 0xFF) for i in range(4)]))
#>>>fourcc_string NV12

Four codec文字列変換の解説


"""
詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識
によると以下のようなビットの並びになる。

char fourcc[] ={
                (char)f,            #最初の文字0-7ビット
                (char)(f >>8),      #次の文字8-15ビット
                (char)(f >>16),     #次の文字16-23ビット
                (char)(f >>24),     #次の文字24-31ビット
                '\0'                #'\0'で終了
                }
"""
方法1

参考:
Binary変換
文字列、Byte、Binary

#整数を表すバイト列を返す。4文字なので4Byte
# byteorder が "little" なので、最上位のバイトがバイト配列の最後に来る。
print("fourcc_Byte",fourcc_int.to_bytes(4, 'little'))
#>>>fourcc_Byte b'NV12'

# utf-8でdecodeして文字列に変換
print('utf-8',fourcc_int.to_bytes(4, 'little').decode('utf-8'))
#>>>utf-8 NV12

#最後にまとめると
fourcc = fourcc_int.to_bytes(4, 'little').decode('utf-8')
print(fourcc)
#>>>NV12


#整数型を2進数で表してみます。
print("fourcc_binary",bin(fourcc_int))
#>>>fourcc_binary 0b110010001100010101011001001110

# binaryで確認してみる
print(bin(ord("N")))
#>>>0b1001110
print(bin(ord("V")))
#>>>0b1010110
print(bin(ord("1")))
#>>>0b110001
print(bin(ord("2")))
#>>>0b110010
print(bin(ord("2")),bin(ord("1")),bin(ord("V")),bin(ord("N")))
#>>>0b110010 0b110001 0b1010110 0b1001110 #最初の0bは2進数の意味
print(bin(fourcc_int))
#>>>0b 110010 00110001 01010110 01001110
方法2

参考:
https://github.com/opencv/opencv/blob/master/samples/python/video_v4l2.py
ビット演算子
Python ビット演算 超入門

print((fourcc_int >> 8 *0)& 0xFF)
#>>>78 -> N

"""
x >> n xのn ビット右シフト
x & y xとyのビット単位論理積
0xFF:255 の16進数(8Bit=1Byte)
example:
'N' 0b01001110
01001110
   &
11111111
--------
01001110
2+4+8+64=78

"""

#N = 78 か確認
print(ord('N'))
#>>>78
print((fourcc_int >> 8 *1)& 0xFF)
#>>>86 -> V

#List内包表現
print([chr((fourcc_int >> 8 * i) & 0xFF) for i in range(4)])
#>>>['N', 'V', '1', '2']
#文字列形式に変換
print("".join([chr((fourcc_int >> 8 * i) & 0xFF) for i in range(4)]))
#>>>NV12

NV21は、非圧縮フォーマットなので解像度の大きな映像を高フレームレートで転送するのには向きません。
参考:
Webカメラからh264動画を取得した〜い〜その2〜
4:2:0 ビデオ ピクセル形式

ちなみに、OpenCVでカメラ撮影を抜けるときに使う以下の書き方もビット演算です。

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

参考:
python - str - cv2.waitKey(1)の0xFFは何ですか?

OpenCVにおけるコーデックの設定方法

参考:
USBカメラのMotion-JPEG を Python + OpenCV + VideoCapture でキャプチャーする方法

import cv2

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)     #カメラの仕様を確認
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1080)     #カメラの仕様を確認

cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"MJPG"))   #カメラの仕様を確認
#cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M','J','P','G'))
# *"MJPG"または、'M','J','P','G'は同じです。

cap.set(cv2.CAP_PROP_FPS, 30)   #カメラの仕様を確認

fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
fourcc = fourcc.to_bytes(4, 'little').decode('utf-8')
print("FOURCC=" + str(fourcc))

fps    = int(cap.get(cv2.CAP_PROP_FPS))
print("FPS=" + str(fps))

cap.release()

コーデック名 引数 拡張子
MP4S ('M', 'P', '4', 'S') .mp4
MP4V ('M', 'P', '4', 'V') .mp4
DIV3 ('D', 'I', 'V', '3') .avi
DIVX ('D', 'I', 'V', 'X') .avi
IYUV ('I', 'Y', 'U', 'V') .avi
MJPG ('M', 'J', 'P', 'G') .avi
XVID ('X', 'V', 'I', 'D') .avi
H263 ('H', '2', '6', '3') .wmv
mp4v ('m', 'p', '4', 'v') .mov

動画を直接撮影してフレームレート測定

参考:
Python, OpenCVで動画再生時のFPS(フレームレート)を測定・表示

import datetime
import cv2

def movie_capture_save_fps(camera_number=0,set_time=5):
    """
    カメラのFPS測定用 Set_timeの間動画を撮り続けその時のfpsをコンソールに出力

    saved file name:year_month_day_hour_minutes_second.mp4

    :param 
    camera_number: camera number. Default  0
    set_time:measurement time unit second  default 5s

    *** ffmpeg install or opencv version over 4.0

    """

    now = datetime.datetime.now()

    # 注意コーデックによっては、保存形式が異なる場合があるのでその時は変更する。
    filename = now.strftime('%y_%m_%d_%H_%M_%S') + '.mp4'
    # filename = now.strftime('%y_%m_%d_%H_%M_%S') + '.avi'

    # Capture image
    cap = cv2.VideoCapture(camera_number) 
    # cap = cv2.VideoCapture(camera_number, cv2.CAP_DSHOW)

    #camera info
    fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
    fps = int(cap.get(cv2.CAP_PROP_FPS))                    # カメラのFPSを取得
    w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))              # カメラの横幅を取得
    h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))             # カメラの縦幅を取得

    print("Current: fourcc:{} fps:{} width:{} height:{}".format(fourcc.to_bytes(4, 'little').decode('utf-8'), fps, w, h))

    #  Set Codec, fps  
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
    cap.set(cv2.CAP_PROP_FOURCC, fourcc)
    # # fourcc = cv2.VideoWriter_fourcc('a', 'v', 'c', '1') 
    # # fourcc = cv2.VideoWriter_fourcc('H', '2', '6', '4')      
    # # fourcc = cv2.VideoWriter_fourcc('Y','U','Y','V')          
    fps = cap.set(cv2.CAP_PROP_FPS,30)

    out = cv2.VideoWriter(filename, fourcc, fps, (w ,h))
    tm = cv2.TickMeter() # fps測定用
    tme = cv2.TickMeter() #Set_time測定用
    tm.start()
    tme.start()
    count = 0
    max_count = 10
    fps = 0
    elasp_time=0


    while (cap.isOpened()):
        ret, frame = cap.read()
        # Resize the window
        # windowsize = (800, 600)
        # frame = cv2.resize(frame, windowsize)

        if ret is True:

            # Display the resulting frame
            # cv2.imshow('frame', frame)

            # Write the frame
            out.write(frame)
            tme.stop()
            elasp_time = tme.getTimeSec()
            tme.start()

            if count == max_count:
                tm.stop()
                time_el = tm.getTimeSec()
                fps = max_count / time_el
                elasp_time = elasp_time + time_el
                tm.reset()
                tm.start()
                count = 0

            print('FPS: {:.2f}, 1/FPS[ms]: {:.2f}, movie:{:.2f} '.format(fps,(1/(fps+0.01))*1000,elasp_time))
            #1/(fps+0.01)は0で割る止まってしまうため便宜上fps+0.01としている。

            count += 1

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

            if elasp_time > set_time:
                print('Break by Time out')
                ret = False
                break
        else:
            break

    # Release everything if job is finished
    tm.stop()
    tm.reset()
    tme.stop()
    tme.reset()
    cap.release()
    out.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    movie_capture_save_fps(camera_number=0,set_time=5)

 その他 (関連情報)

VideoCapturePropertiesの一覧

OpenCV document
https://docs.opencv.org/4.2.0/d4/d15/group__videoio__flags__base.html#gaeb8dd9c89c10a5c63c139bf7c4f5704d

引数 説明
cv.CAP_PROP_POS_MSEC Current position of the video file in milliseconds.
cv.CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
cv.CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0=start of the film, 1=end of the film.
cv.CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
cv.CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
cv.CAP_PROP_FPS Frame rate.
cv.CAP_PROP_FOURCC 4-character code of codec. see VideoWriter::fourcc .
cv.CAP_PROP_FRAME_COUNT Number of frames in the video file.
cv.CAP_PROP_FORMAT Format of the Mat objects (see Mat::type()) returned by VideoCapture::retrieve(). Set value -1 to fetch undecoded RAW video streams (as Mat 8UC1).
cv.CAP_PROP_MODE Backend-specific value indicating the current capture mode.
cv.CAP_PROP_BRIGHTNESS Brightness of the image (only for those cameras that support).
cv.CAP_PROP_CONTRAST Contrast of the image (only for cameras).
cv.CAP_PROP_SATURATION Saturation of the image (only for cameras).
cv.CAP_PROP_HUE Hue of the image (only for cameras).
cv.CAP_PROP_GAIN Gain of the image (only for those cameras that support).
cv.CAP_PROP_EXPOSURE Exposure (only for those cameras that support).
cv.CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB.
cv.CAP_PROP_WHITE_BALANCE_BLUE_U Currently unsupported.
cv.CAP_PROP_RECTIFICATION Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently).
cv.CAP_PROP_MONOCHROME
cv.CAP_PROP_SHARPNESS
cv.CAP_PROP_AUTO_EXPOSURE DC1394: exposure control done by camera, user can adjust reference level using this feature.
cv.CAP_PROP_GAMMA
cv.CAP_PROP_TEMPERATURE
cv.CAP_PROP_TRIGGER
cv.CAP_PROP_TRIGGER_DELAY
cv.CAP_PROP_WHITE_BALANCE_RED_V
cv.CAP_PROP_ZOOM
cv.CAP_PROP_FOCUS
cv.CAP_PROP_GUID
cv.CAP_PROP_ISO_SPEED
cv.CAP_PROP_BACKLIGHT
cv.CAP_PROP_PAN
cv.CAP_PROP_TILT
cv.CAP_PROP_ROLL
cv.CAP_PROP_IRIS
cv.CAP_PROP_SETTINGS Pop up video/camera filter dialog (note: only supported by DSHOW backend currently. The property value is ignored)
cv.CAP_PROP_BUFFERSIZE
cv.CAP_PROP_AUTOFOCUS
cv.CAP_PROP_SAR_NUM Sample aspect ratio: num/den (num)
cv.CAP_PROP_SAR_DEN Sample aspect ratio: num/den (den)
cv.CAP_PROP_BACKEND Current backend (enum VideoCaptureAPIs). Read-only property.
cv.CAP_PROP_CHANNEL Video input or Channel Number (only for those cameras that support)
cv.CAP_PROP_AUTO_WB enable/ disable auto white-balance
cv.CAP_PROP_WB_TEMPERATURE white-balance color temperature
cv.CAP_PROP_CODEC_PIXEL_FORMAT (read-only) codec's pixel format. 4-character code - see VideoWriter::fourcc . Subset of AV_PIX_FMT_* or -1 if unknown
動画ファイルのコーデックを調べる方法

MediaInfoOnline

33
30
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
33
30