import cv2
import numpy as np

video = cv2.VideoCapture("cars.mp4")

# get first frame
ret, first_frame = video.read()
n_images_average = 120
width, height, _ = first_frame.shape
avg = np.zeros((width, height, n_images_average), dtype=float)

counter = 0

while True:
    ret, frame = video.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (55, 55), 0)

    if not ret:
        break

    avg[:, :, counter % n_images_average] = blur.astype(float)
    counter += 1

    avg_frame = np.median(avg, axis=2).astype(np.uint8)

    dif = cv2.absdiff(blur, avg_frame)
    mask_frame = cv2.threshold(dif, 25, 255, cv2.THRESH_BINARY)[1]

    # from w, h to w, h, 3
    blur = cv2.cvtColor(blur, cv2.COLOR_GRAY2BGR)
    avg_frame = cv2.cvtColor(avg_frame,cv2.COLOR_GRAY2BGR)

    #use mask to set to black the moving parts in the original frame
    mask_3c = cv2.cvtColor(mask_frame, cv2.COLOR_GRAY2BGR)
    framef = cv2.bitwise_and(frame, mask_3c)

    dif = cv2.cvtColor(dif, cv2.COLOR_GRAY2BGR)
    mask_frame = cv2.cvtColor(mask_frame, cv2.COLOR_GRAY2BGR)

    top_line = np.hstack([frame, blur, avg_frame])
    bottom_line = np.hstack([dif, mask_frame, framef])

    results = np.vstack([top_line, bottom_line])
    cv2.imshow('frame', results)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break