-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.py
More file actions
137 lines (117 loc) · 4.74 KB
/
Copy pathindex.py
File metadata and controls
137 lines (117 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Open CV for looping through frames
import cv2
# os for working with directories
import os
# sys for looking at command line arguments
import sys
# datetime for converting images to time in video
import datetime
# numpy for calculating MSE between two images
import numpy as np
# tqdm for printing a progress bar
from tqdm import tqdm
def mse(imageA, imageB):
# Comparing the images gives us an error, use the mse as a trigger to save the image.
# https://www.pyimagesearch.com/2014/09/15/python-compare-two-images/
# the 'Mean Squared Error' between the two images is the
# sum of the squared difference between the two images;
# NOTE: the two images must have the same dimension
_, x, _ = imageA.shape
x = int(x*0.835)
# y = y*0.8
# I had an issue where the speaker on the zoom video flicked a lot, causing the repetition of frames. To tackle this, I only take the MSE of the cropped image, which should ignore the zoom video.
# image[0:y,0:x] is the inital size
imageA = imageA[:, 0:x]
imageB = imageB[:, :x]
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
# return the MSE, the lower the error, the more "similar" the two images are
return err
def predictTreshold(vidcap, frames_folder, success, image):
# Logsitics
fps = int(vidcap.get(cv2.CAP_PROP_FPS))
totalNoFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
durationInSeconds = float(totalNoFrames) / float(fps)
print('-'*20+' Logistics ' + '-'*20)
print("FPS: "+str(fps))
print("Total Frames: "+str(int(totalNoFrames)))
print("Length of Video: " + str(datetime.timedelta(seconds=durationInSeconds)))
print('-'*20+' Doing a Dry run for Treshold' + '-'*20)
totalError = []
prev = None
# analyzes every frame at 2s.
for fno in range(0, totalNoFrames, fps*5):
vidcap.set(cv2.CAP_PROP_POS_FRAMES, fno)
_, image = vidcap.read()
if not prev is None:
s = mse(image, prev)
# print(f"{t} Image error: {s}")
totalError.append(s)
prev = image
# 1991.726805678645
totalError = np.array(totalError)
treshold = 2 * np.std(totalError)
print('Using Predicted Treshold:'+str(treshold))
print('-----End of Testing----')
return treshold
def analyzeFrame(image, slideNo, threshold, frames_folder, timestamp, prev=None):
if not prev is None:
if mse(image, prev) > threshold:
slideNo += 1
# save frame as JPEG file
cv2.imwrite(
"%s/frame%d_timestamp-%s.jpg" % (frames_folder, slideNo, timestamp.replace(':', ';')), prev)
return image, slideNo
def grabFrames(vidcap, frames_folder, success, image, threshold=400):
# Logsitics
fps = int(vidcap.get(cv2.CAP_PROP_FPS))
totalNoFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
loop = tqdm(position=0, total=totalNoFrames, leave=False)
count = 0
prev = None
t = 0
# analyzes every frame at 2s.
factor = 2
for fno in range(0, totalNoFrames, fps*factor):
vidcap.set(cv2.CAP_PROP_POS_FRAMES, fno)
_, image = vidcap.read()
if not prev is None:
loop.update(fps*factor)
prev, t = analyzeFrame(image, t, threshold, frames_folder, str(
datetime.timedelta(seconds=fno//fps)), prev)
prev = image
t += 1
cv2.imwrite(
"%s/frame%d_timestamp-%s.jpg" % (frames_folder, t, (str(datetime.timedelta(seconds=count//fps)).replace(':', ';'))), prev)
# new approach
# total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
def main():
if (len(sys.argv) != 2):
print('Invalid number of Arguments')
sys.exit()
video_file_path = sys.argv[1]
if not os.path.isfile(video_file_path):
print('Video Path is incorrect')
sys.exit()
# Not sure if OpenCV is compatible with other types of videos
elif video_file_path[-4:] != '.mp4':
print("Video must be an mp4 file")
sys.exit()
vidcap = cv2.VideoCapture(video_file_path)
# Try Reading the video
success, image = vidcap.read()
if not success:
print("Error related to OpenCV capturing video")
sys.exit()
# Create Frames folder
frames_folder = video_file_path[:-4] + '_frames'
if not os.path.exists(frames_folder):
os.makedirs(frames_folder)
# hardcode the treshold if you feel like the predicted treshold isnt working properly.
treshold = predictTreshold(cv2.VideoCapture(video_file_path),
frames_folder, success, image)
grabFrames(cv2.VideoCapture(video_file_path),
frames_folder, success, image, treshold)
print('Conversion Completed')
if __name__ == "__main__":
main()