-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVideo-to-ScopeWAV.py
112 lines (85 loc) · 3.35 KB
/
Video-to-ScopeWAV.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
import cv2
import numpy as np
from scipy.io.wavfile import write
from scipy.spatial import KDTree
from tkinter import filedialog, Tk, Button, Label
import os
root = Tk()
root.title("Video to Oscilloscope WAV Converter")
video_path = filedialog.askopenfilename(title="Select video file")
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise IOError("Cannot open video file")
fps = cap.get(cv2.CAP_PROP_FPS)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
if frame_height >= frame_width:
height = 256
width = round(frame_width / frame_height * height)
else:
width = 256
height = round(frame_height / frame_width * width)
sampling_rate = 88200
sound_channels = 2
samp_per_frame = round(sampling_rate / fps)
bits_per_sample = 8
edge_points = []
def sort_edge_points(points):
if len(points) <= 1:
return points
tree = KDTree(points)
sorted_points = [points[0]]
points = np.delete(points, 0, axis=0)
while len(points) > 1:
last_point = sorted_points[-1]
dist, idx = tree.query(last_point, k=2)
next_idx = idx[1] if idx[0] == 0 else idx[0]
sorted_points.append(points[next_idx])
points = np.delete(points, next_idx, axis=0)
tree = KDTree(points)
sorted_points.append(points[0])
return np.array(sorted_points)
def process_frame(frame_idx=0):
ret, frame = cap.read()
if not ret:
print("End of video or error reading frame.")
cap.release()
cv2.destroyAllWindows()
start_conversion_button.config(state="normal")
return
else:
print("Processing frame: %d" % (frame_idx))
frame = cv2.resize(frame, (width, height), interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
y, x = np.where(edges != 0)
points = np.column_stack((x, height - y))
points = sort_edge_points(points)
edge_points.append(points)
cv2.imshow('Edges', edges)
cv2.waitKey(1)
root.after(1, lambda: process_frame(frame_idx + 1))
start_button = Button(root, text="Start Processing", command=lambda: process_frame())
start_button.config(height=2, width=20)
start_button.pack()
def start_conversion():
wav_data = np.zeros((len(edge_points) * samp_per_frame, sound_channels), dtype=np.uint8)
for frame_idx, points in enumerate(edge_points):
if len(points) > 0:
for j in range(samp_per_frame):
idx = int(j * len(points) / samp_per_frame)
wav_data[frame_idx * samp_per_frame + j, 0] = int(points[idx, 0] / width * 255)
wav_data[frame_idx * samp_per_frame + j, 1] = int(points[idx, 1] / height * 255)
else:
wav_data[frame_idx * samp_per_frame:(frame_idx + 1) * samp_per_frame, :] = 128
output_path = os.path.splitext(video_path)[0] + '_output.wav'
write(output_path, sampling_rate, wav_data)
print(f"WAV file has been saved as '{output_path}'.")
label.config(text="Conversion Completed!")
start_conversion_button = Button(root, text="Start Conversion", state="disabled", command=start_conversion)
start_conversion_button.config(height=2, width=20)
start_conversion_button.pack()
label = Label(root, text="")
label.pack()
root.mainloop()