Numpy で動画の背景を取得する

其ノ壱 : 
  フレームの平均値を取ってみる。
  フレームを足してフレーム数で割る。雑。
  サンプルは OpenCV 付属の vtest.avi

  少し残像が残るが、そこそこな感が。

#coding:utf-8
import numpy as np
import cv2

def mean():
    FileName = r'OpenCV/samples/data/vtest.avi'
    
    cap= cv2.VideoCapture(FileName)     # (576, 768, 3) 795frame
    FrameCount = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    ret, frame = cap.read()
    img = np.zeros_like(frame, dtype='int32')
    i = 0
    while True:
        img += frame
        i += 1
        
        temp_img = np.uint8(img // i)
        cv2.putText(temp_img, str(i) + ' / ' + str(FrameCount),
                (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), thickness=2)
        cv2.imshow('image', temp_img)
        if cv2.waitKey(1) > 8:      # どれかキーを押せば終了
            break
        
        ret, frame = cap.read()
        if ret != 1:
            break

    cv2.destroyAllWindows()
    return 1

if __name__ == '__main__':
    mean()
其ノ弐 : 
  色を分割して蓄積し、最頻出の部分だけ再構築してみる。
  今回は四分割。
  300フレーム辺りで、ほぼ背景のみに。
  但し重い。

#coding:utf-8
import numpy as np
import cv2

def index():
    n = 4	# 四分割
    FileName = r'OpenCV/samples/data/vtest.avi'
    
    cap= cv2.VideoCapture(FileName)     # (576, 768, 3) 795frame
    FrameCount = np.int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    ret, frame = cap.read()
    Height, Width, Colors = frame.shape
    p = np.arange(frame.size)
    temp_img = np.zeros(Height * Width * Colors * n * 2, dtype='uint32')
    temp_img.shape = -1, n, 2   # (1327104, 4, 2)
    
    i = 0
    while True:
        frame.shape = -1        # (1327104,)
        a = frame // (256 // n)
        temp_img[p,a,0] += frame[p]
        temp_img[p,a,1] += 1
        i += 1
        
        q = np.argmax(temp_img[:,:,1],axis=1)
        temp_img2 = temp_img[p,q]
        img = temp_img2[:,0] // temp_img2[:,1]
        img.shape = Height, Width, Colors
        img = img.astype('uint8')
        
        cv2.putText(img, str(i) + ' / ' + str(FrameCount),
                (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), thickness=2)
        cv2.imshow('image', img)
        if cv2.waitKey(1) > 8:      # どれかキーを押せば終了
            break

        ret, frame = cap.read()
        if ret != 1:
            break

    cv2.destroyAllWindows()
    return 1

if __name__ == '__main__':
    index()