Files
opendan/src/aios/utils/video_utils.py
T
2023-12-04 19:06:33 +08:00

123 lines
3.4 KiB
Python

import base64
from typing import List, Tuple
import cv2
import numpy as np
def precess_image(image):
'''
Graying and GaussianBlur
:param image: The image matrix,np.array
:return: The processed image matrix,np.array
'''
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_image = cv2.GaussianBlur(gray_image, (3, 3), 0)
return gray_image
def abs_diff(pre_image, curr_image):
'''
Calculate absolute difference between pre_image and curr_image
:param pre_image:The image in past frame,np.array
:param curr_image:The image in current frame,np.array
:return:
'''
gray_pre_image = precess_image(pre_image)
gray_curr_image = precess_image(curr_image)
diff = cv2.absdiff(gray_pre_image, gray_curr_image)
res, diff = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cnt_diff = np.sum(np.sum(diff))
return cnt_diff
def exponential_smoothing(alpha, s):
'''
Primary exponential smoothing
:param alpha: Smoothing factor,num
:param s: List of data,list
:return: List of data after smoothing,list
'''
s_temp = [s[0]]
print(s_temp)
for i in range(1, len(s), 1):
s_temp.append(alpha * s[i - 1] + (1 - alpha) * s_temp[i - 1])
return s_temp
def extract_frames(video_path: str, resize: Tuple[int, int] = None, smooth=False, alpha=0.07, window=25) -> List[str]:
"""Extract frames from video."""
frames = []
vidcap = cv2.VideoCapture(video_path)
diff = []
frm = 0
pre_image = np.array([])
cur_image = np.array([])
while True:
frm = frm + 1
success, image = vidcap.read()
if not success:
break
if frm == 1:
pre_image = image
cur_image = image
else:
pre_image = cur_image
cur_image = image
diff.append(abs_diff(pre_image, cur_image))
if smooth:
diff = exponential_smoothing(alpha, diff)
diff = np.array(diff)
mean = np.mean(diff)
dev = np.std(diff)
diff = (diff - mean) / dev
idx = []
for i, d in enumerate(diff):
ub = len(diff) - 1
lb = 0
if not i - window // 2 < lb:
lb = i - window // 2
if not i + window // 2 > ub:
ub = i + window // 2
comp_window = diff[lb: ub]
if d >= max(comp_window):
idx.append(i)
tmp = np.array(idx)
tmp = tmp + 1
idx = set(tmp.tolist())
vidcap.release()
vidcap = cv2.VideoCapture(video_path)
i = 0
frm = 0
while vidcap.isOpened() and i < 10:
frm = frm + 1
success, image = vidcap.read()
if not success:
break
if frm not in idx:
continue
if resize is not None:
dest_width, dest_height = resize
width, height = image.shape[:2]
if width > dest_width or height > dest_height:
width_rate = dest_width / width
height_rate = dest_height / height
rate = min(width_rate, height_rate)
dest_width = int(width * rate)
dest_height = int(height * rate)
image = cv2.resize(image, (dest_width, dest_height), interpolation=cv2.INTER_AREA)
_, buffer = cv2.imencode(".jpg", image)
frames.append(f"data:image/jpg;base64,{base64.b64encode(buffer).decode('utf-8')}")
i += 1
vidcap.release()
return frames