-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSlice.py
145 lines (113 loc) · 4.11 KB
/
Slice.py
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
138
139
140
141
142
143
144
import os
import cv2
from skimage.metrics import structural_similarity
def ssim(frame1, frame2):
"""Calculate Structural Similarity (SSIM) between two frames"""
frame1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
frame2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
frame1 = cv2.resize(frame1, (512, 512))
frame2 = cv2.resize(frame2, (512, 512))
return structural_similarity(frame1, frame2)
def read_frames(video_path, size=1000):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print("Error opening video file")
return
while True:
frames = []
for _ in range(size):
ret, frame = cap.read()
if not ret:
break
frames.append(frame)
if not frames:
break
yield frames
cap.release()
def slice_frames(frames,ssim_threshold):
start = 0
end = start + 1
total_length = len(frames)
borders = []
while end != total_length:
left = end
right = total_length - 1
while left != right:
mid = int((left + right)/2)
ssim_val = ssim(frames[start], frames[mid])
if ssim_val > ssim_threshold: # indicating that the same scene
left = mid + 1
else:
right = mid
borders.append(left)
start = left
end = start + 1
return borders
def frames_to_video(video_path, borders, output_path):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print("Error opening video file")
return
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = None
segment_count = 1
frame_count = 0
current_border = 0
while True:
ret, frame = cap.read()
frame_count += 1
if not ret:
break
if current_border < len(borders) and frame_count > borders[current_border]:
if video_writer:
video_writer.release()
segment_path = os.path.join(output_path, f"segment_{segment_count}.mp4")
video_writer = cv2.VideoWriter(segment_path, fourcc, fps, (width, height))
segment_count += 1
current_border += 1
if video_writer:
video_writer.write(frame)
else:
segment_path = os.path.join(output_path, f"segment_{segment_count}.mp4")
video_writer = cv2.VideoWriter(segment_path, fourcc, fps, (width, height))
segment_count += 1
current_border += 1
if video_writer:
video_writer.release()
cap.release()
def segment_scenes(video_path, read_size, min_interval, ssim_threshold, output_path):
last_frame = None # Used to determine if two segments are connected
generator = read_frames(video_path, read_size)
final_borders = []
offset = 0
for frames in generator:
first_frame = frames[0]
print(f"Read {len(frames)} frames over")
borders = slice_frames(frames, ssim_threshold)
# Check if the last frame of the previous segment is similar to the first frame of the current segment
if last_frame is not None and ssim(first_frame, last_frame) >= ssim_threshold:
final_borders.pop()
final_borders.extend(b + offset for b in borders)
offset += read_size
last_frame = frames[-1]
last = 0
filtered_borders = []
# Filter borders based on the minimum interval
for item in final_borders:
if item - last < min_interval:
continue
else:
last = item
filtered_borders.append(item)
print(filtered_borders)
frames_to_video(video_path, filtered_borders, output_path)
if __name__ == '__main__':
read_size = 500
min_interval = 100 # Set the minimum interval value
ssim_threshold = 0.50 # Set the threshold for SSIM
video_path = "test_input/test.mp4"
output_path = "test_output"
segment_scenes(video_path, read_size, min_interval, ssim_threshold, output_path)