Lovish Singla commited on
Commit
2e176bb
·
unverified ·
0 Parent(s):

Add files via upload

Browse files
Files changed (2) hide show
  1. app.py +170 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ from sklearn.cluster import KMeans
5
+ from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input
6
+ from tensorflow.keras.preprocessing import image
7
+ import tempfile
8
+ import os
9
+
10
+ # Function to extract VGG16 features from a frame
11
+ def extract_vgg_features(frame):
12
+ frame = cv2.resize(frame, (224, 224))
13
+ img_array = image.img_to_array(frame)
14
+ img_array = np.expand_dims(img_array, axis=0)
15
+ img_array = preprocess_input(img_array)
16
+ features = VGG16(weights="imagenet", include_top=False, pooling="avg").predict(img_array)
17
+ return features.flatten()
18
+
19
+ # Function to compute histogram difference
20
+ def histogram_difference(frame1, frame2):
21
+ hist1 = cv2.calcHist([frame1], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
22
+ hist2 = cv2.calcHist([frame2], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
23
+ hist1 = cv2.normalize(hist1, hist1).flatten()
24
+ hist2 = cv2.normalize(hist2, hist2).flatten()
25
+ return cv2.compareHist(hist1, hist2, cv2.HISTCMP_BHATTACHARYYA)
26
+
27
+ # Function to detect scene changes using histogram comparison
28
+ def detect_scene_changes(video_path, threshold=0.2):
29
+ cap = cv2.VideoCapture(video_path)
30
+ prev_frame = None
31
+ scene_change_frames = []
32
+
33
+ while True:
34
+ ret, frame = cap.read()
35
+ if not ret:
36
+ break
37
+
38
+ if prev_frame is not None:
39
+ diff = histogram_difference(prev_frame, frame)
40
+ if diff > threshold:
41
+ scene_change_frames.append(frame)
42
+
43
+ prev_frame = frame
44
+
45
+ cap.release()
46
+ return scene_change_frames[:5] # Limit to 20 frames
47
+
48
+ # Function to select frames based on motion
49
+ def motion_based_selection(video_path, num_frames=5):
50
+ cap = cv2.VideoCapture(video_path)
51
+ prev_frame = None
52
+ motion_scores = []
53
+
54
+ while True:
55
+ ret, frame = cap.read()
56
+ if not ret:
57
+ break
58
+
59
+ if prev_frame is not None:
60
+ diff = cv2.absdiff(prev_frame, frame)
61
+ motion_score = np.mean(diff)
62
+ motion_scores.append((frame, motion_score))
63
+
64
+ prev_frame = frame
65
+
66
+ cap.release()
67
+
68
+ # Sort frames by motion score and select top frames
69
+ motion_scores.sort(key=lambda x: x[1], reverse=True)
70
+ selected_frames = [x[0] for x in motion_scores[:num_frames]]
71
+ return selected_frames
72
+
73
+ # Function to cluster frames using VGG16 features
74
+ def cluster_frames(video_path, num_clusters=5):
75
+ cap = cv2.VideoCapture(video_path)
76
+ frames = []
77
+ features = []
78
+
79
+ while True:
80
+ ret, frame = cap.read()
81
+ if not ret:
82
+ break
83
+
84
+ frames.append(frame)
85
+ feature = extract_vgg_features(frame)
86
+ features.append(feature)
87
+
88
+ cap.release()
89
+
90
+ # Perform K-Means clustering
91
+ kmeans = KMeans(n_clusters=num_clusters, random_state=42)
92
+ clusters = kmeans.fit_predict(features)
93
+
94
+ # Select one frame from each cluster
95
+ selected_frames = []
96
+ for cluster_id in range(num_clusters):
97
+ cluster_indices = np.where(clusters == cluster_id)[0]
98
+ centroid_index = cluster_indices[0] # Select the first frame in the cluster
99
+ selected_frames.append(frames[centroid_index])
100
+
101
+ return selected_frames
102
+
103
+ # Function to convert video to 15 FPS
104
+ def convert_to_15fps(video_path, output_path):
105
+ cap = cv2.VideoCapture(video_path)
106
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
107
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
108
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
109
+
110
+ # Define the codec and create VideoWriter object
111
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
112
+ out = cv2.VideoWriter(output_path, fourcc, 15, (width, height))
113
+
114
+ while True:
115
+ ret, frame = cap.read()
116
+ if not ret:
117
+ break
118
+
119
+ # Write the frame to the output video
120
+ out.write(frame)
121
+
122
+ # Skip frames to achieve 15 FPS
123
+ for _ in range(int(fps / 15) - 1):
124
+ cap.read()
125
+
126
+ cap.release()
127
+ out.release()
128
+
129
+ # Streamlit app
130
+ def main():
131
+ st.title("Video Frame Selection App")
132
+ st.write("Upload a 60-second video to extract the best 20 frames using three methods.")
133
+
134
+ # Upload video
135
+ uploaded_file = st.file_uploader("Upload a 60-second video", type=["mp4", "avi", "mov"])
136
+ if uploaded_file is not None:
137
+ # Save the uploaded video to a temporary file
138
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_file:
139
+ temp_file.write(uploaded_file.getbuffer())
140
+ temp_video_path = temp_file.name
141
+
142
+ # Convert the video to 15 FPS
143
+ output_video_path = "temp_15fps_video.mp4"
144
+ convert_to_15fps(temp_video_path, output_video_path)
145
+
146
+ # Motion-based selection
147
+ st.header("Motion-Based Frames")
148
+ motion_frames = motion_based_selection(output_video_path, num_frames=5)
149
+ for i, frame in enumerate(motion_frames):
150
+ st.image(frame, caption=f"Motion Frame {i + 1}", use_column_width=True)
151
+
152
+ # Scene change detection
153
+ st.header("Scene Change-Based Frames")
154
+ scene_change_frames = detect_scene_changes(output_video_path, threshold=0.2)
155
+ for i, frame in enumerate(scene_change_frames):
156
+ st.image(frame, caption=f"Scene Change Frame {i + 1}", use_column_width=True)
157
+
158
+ # Clustering-based selection
159
+ st.header("Clustering-Based Frames")
160
+ clustered_frames = cluster_frames(output_video_path, num_clusters=5)
161
+ for i, frame in enumerate(clustered_frames):
162
+ st.image(frame, caption=f"Clustered Frame {i + 1}", use_column_width=True)
163
+
164
+ # Clean up temporary files
165
+ os.unlink(temp_video_path)
166
+ os.unlink(output_video_path)
167
+
168
+ # Run the app
169
+ if __name__ == "__main__":
170
+ main()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ opencv-python
3
+ numpy
4
+ scikit-learn
5
+ tensorflow