MRuslanR commited on
Commit
f7e17ff
·
1 Parent(s): 6b225d2

Initial commit

Browse files
Files changed (4) hide show
  1. app.py +98 -0
  2. config.py +47 -0
  3. requirements.txt +54 -0
  4. video_processing.py +55 -0
app.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ from video_processing import enhance_video
4
+ from config import EXAMPLES
5
+
6
+ st.set_page_config(
7
+ page_title="Сверточный Видоусилитель",
8
+ page_icon="🎬",
9
+ layout="wide"
10
+ )
11
+
12
+
13
+ def main():
14
+ st.title("🎬 Сверточный Видоусилитель")
15
+
16
+ if 'current_filter' not in st.session_state:
17
+ st.session_state.current_filter = "Повышение резкости"
18
+ st.session_state.kernel = EXAMPLES["Повышение резкости"]
19
+
20
+ # Секция загрузки файла
21
+ uploaded_file = st.file_uploader("📤 Загрузите видео файл", type=["mp4", "avi", "mov"])
22
+
23
+ # Панель управления фильтрами
24
+ with st.sidebar:
25
+ st.header("⚙ Настройки свертки")
26
+
27
+ # Отображение текущего фильтра
28
+ st.markdown(f"**Активный фильтр:** `{st.session_state.current_filter}`")
29
+ kernel_input = st.text_input(
30
+ "Матрица 3x3 (9 чисел через запятую):",
31
+ value=", ".join(map(str, st.session_state.kernel.flatten())),
32
+ help="Пример: -1, -1, -1, -1, 9, -1, -1, -1, -1",
33
+ key="kernel_input"
34
+ )
35
+
36
+ st.subheader("📚 Пресеты фильтров")
37
+ cols = st.columns(2)
38
+ for idx, (name, example) in enumerate(EXAMPLES.items()):
39
+ with cols[idx % 2]:
40
+ is_active = name == st.session_state.current_filter
41
+ btn_label = f"✅ {name}" if is_active else f"⚙️ {name}"
42
+ if st.button(
43
+ btn_label,
44
+ help=f"Матрица: {example.tolist()}",
45
+ use_container_width=True
46
+ ):
47
+ st.session_state.current_filter = name
48
+ st.session_state.kernel = example
49
+ st.rerun()
50
+
51
+ if uploaded_file:
52
+ if st.button("🚀 ПРИМЕНИТЬ СВЕРТОЧНЫЙ ФИЛЬТР", use_container_width=True, type="primary"):
53
+ try:
54
+ if not kernel_input.strip():
55
+ st.error("❌ Выберите фильтр или введите свою матрицу!")
56
+ return
57
+
58
+ kernel_values = [float(x.strip()) for x in kernel_input.split(',')]
59
+
60
+ if len(kernel_values) != 9:
61
+ st.error("❌ Требуется ровно 9 значений через запятую!")
62
+ return
63
+
64
+ if all(abs(x) < 0.0001 for x in kernel_values):
65
+ st.error("❌ Матрица не может быть нулевой!")
66
+ return
67
+
68
+ kernel = np.array(kernel_values).reshape(3, 3)
69
+ st.session_state.kernel = kernel
70
+ st.session_state.current_filter = "Пользовательский"
71
+
72
+ with st.spinner("🔎 Применяем сверточный фильтр..."):
73
+ processed_path = enhance_video(uploaded_file, kernel)
74
+
75
+ col1, col2 = st.columns(2)
76
+ with col1:
77
+ st.subheader("Исходное видео")
78
+ st.video(uploaded_file)
79
+
80
+ with col2:
81
+ st.subheader("Результат обработки")
82
+ st.video(processed_path)
83
+
84
+ with open(processed_path, "rb") as f:
85
+ st.download_button(
86
+ label="💾 Скачать результат",
87
+ data=f,
88
+ file_name="conv_video.mp4",
89
+ mime="video/mp4",
90
+ use_container_width=True
91
+ )
92
+
93
+ except Exception as e:
94
+ st.error(f"⚠️ Критическая ошибка: {str(e)}")
95
+
96
+
97
+ if __name__ == "__main__":
98
+ main()
config.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ EXAMPLES = {
4
+ # Базовые фильтры
5
+ "Повышение резкости": np.array([
6
+ [-1, -1, -1],
7
+ [-1, 9, -1],
8
+ [-1, -1, -1]
9
+ ]),
10
+ "Гауссово размытие": np.array([
11
+ [0.0625, 0.125, 0.0625],
12
+ [0.125, 0.25, 0.125],
13
+ [0.0625, 0.125, 0.0625]
14
+ ]),
15
+ "Детектор краёв": np.array([
16
+ [0, 1, 0],
17
+ [1, -4, 1],
18
+ [0, 1, 0]
19
+ ]),
20
+
21
+ # Новые фильтры
22
+ "Эффект тиснения": np.array([
23
+ [-2, -1, 0],
24
+ [-1, 1, 1],
25
+ [0, 1, 2]
26
+ ]),
27
+ "Контурная резкость": np.array([
28
+ [0, -1, 0],
29
+ [-1, 5, -1],
30
+ [0, -1, 0]
31
+ ]),
32
+ "Точечное размытие": np.array([
33
+ [0, 0.2, 0],
34
+ [0.2, 0.2, 0.2],
35
+ [0, 0.2, 0]
36
+ ]),
37
+ "Повышение контраста": np.array([
38
+ [0, -1, 0],
39
+ [-1, 5, -1],
40
+ [0, -1, 0]
41
+ ]),
42
+ "Эффект рельефа": np.array([
43
+ [1, 1, 0],
44
+ [1, 0, -1],
45
+ [0, -1, -1]
46
+ ])
47
+ }
requirements.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ altair==5.5.0
2
+ attrs==25.1.0
3
+ blinker==1.9.0
4
+ cachetools==5.5.1
5
+ certifi==2025.1.31
6
+ charset-normalizer==3.4.1
7
+ click==8.1.8
8
+ decorator==5.1.1
9
+ filelock==3.17.0
10
+ fsspec==2025.2.0
11
+ gitdb==4.0.12
12
+ GitPython==3.1.44
13
+ idna==3.10
14
+ imageio==2.37.0
15
+ imageio-ffmpeg==0.6.0
16
+ Jinja2==3.1.5
17
+ jsonschema==4.23.0
18
+ jsonschema-specifications==2024.10.1
19
+ markdown-it-py==3.0.0
20
+ MarkupSafe==3.0.2
21
+ mdurl==0.1.2
22
+ moviepy==2.1.2
23
+ mpmath==1.3.0
24
+ narwhals==1.25.1
25
+ networkx==3.4.2
26
+ numpy==2.2.2
27
+ opencv-python==4.11.0.86
28
+ packaging==24.2
29
+ pandas==2.2.3
30
+ pillow==10.4.0
31
+ proglog==0.1.10
32
+ protobuf==5.29.3
33
+ pyarrow==19.0.0
34
+ pydeck==0.9.1
35
+ Pygments==2.19.1
36
+ python-dateutil==2.9.0.post0
37
+ python-dotenv==1.0.1
38
+ pytz==2025.1
39
+ referencing==0.36.2
40
+ requests==2.32.3
41
+ rich==13.9.4
42
+ rpds-py==0.22.3
43
+ six==1.17.0
44
+ smmap==5.0.2
45
+ streamlit==1.42.0
46
+ sympy==1.13.1
47
+ tenacity==9.0.0
48
+ toml==0.10.2
49
+ torch==2.6.0
50
+ tornado==6.4.2
51
+ tqdm==4.67.1
52
+ typing_extensions==4.12.2
53
+ tzdata==2025.1
54
+ urllib3==2.3.0
video_processing.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import tempfile
4
+ import os
5
+ from moviepy import VideoFileClip
6
+
7
+
8
+ def enhance_video(video_file, kernel):
9
+ # Сохранение во временный файл
10
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as temp_input:
11
+ temp_input.write(video_file.getbuffer())
12
+ input_path = temp_input.name
13
+
14
+ # Обработка видео
15
+ cap = cv2.VideoCapture(input_path)
16
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
17
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
18
+ fps = cap.get(cv2.CAP_PROP_FPS)
19
+
20
+ # Подготовка выходного файла
21
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as temp_output:
22
+ output_path = temp_output.name
23
+ out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height))
24
+
25
+ while cap.isOpened():
26
+ ret, frame = cap.read()
27
+ if not ret:
28
+ break
29
+ processed_frame = cv2.filter2D(frame, -1, kernel)
30
+ out.write(processed_frame)
31
+
32
+ cap.release()
33
+ out.release()
34
+
35
+ # Микширование аудио
36
+ final_output = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4').name
37
+ video_clip = VideoFileClip(output_path)
38
+ audio_clip = VideoFileClip(input_path).audio
39
+
40
+ if audio_clip:
41
+ video_clip.audio = audio_clip
42
+
43
+ video_clip.write_videofile(
44
+ final_output,
45
+ codec='libx264',
46
+ audio_codec='aac',
47
+ logger=None
48
+ )
49
+
50
+ # Очистка временных файлов
51
+ for path in [input_path, output_path]:
52
+ if os.path.exists(path):
53
+ os.remove(path)
54
+
55
+ return final_output