maxorange commited on
Commit
63b708d
·
verified ·
1 Parent(s): 7f2e2e2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +212 -0
app.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import re
4
+ from PIL import Image, ImageDraw, ImageFilter, ImageEnhance, ImageFont
5
+ from moviepy.video.VideoClip import VideoClip
6
+
7
+
8
+ # Функция для добавления слабого эффекта сепии
9
+ def apply_sepia(image, intensity=0.3):
10
+ sepia_image = Image.new("RGB", image.size)
11
+ pixels = image.load()
12
+ sepia_pixels = sepia_image.load()
13
+
14
+ for y in range(image.height):
15
+ for x in range(image.width):
16
+ r, g, b = pixels[x, y]
17
+ tr = int(0.393 * r + 0.769 * g + 0.189 * b)
18
+ tg = int(0.349 * r + 0.686 * g + 0.168 * b)
19
+ tb = int(0.272 * r + 0.534 * g + 0.131 * b)
20
+ sepia_pixels[x, y] = (
21
+ int(r * (1 - intensity) + tr * intensity),
22
+ int(g * (1 - intensity) + tg * intensity),
23
+ int(b * (1 - intensity) + tb * intensity),
24
+ )
25
+ return sepia_image
26
+
27
+
28
+ # Функция для добавления эффекта старой плёнки
29
+ def add_film_effect(image, frame_number, fps):
30
+ image = apply_sepia(image, intensity=0.3) # Слабый эффект сепии
31
+ draw = ImageDraw.Draw(image)
32
+ width, height = image.size
33
+
34
+ # Эффект зернистости
35
+ noise = np.random.randint(0, 64, (height, width, 3), dtype='uint8')
36
+ noise_image = Image.fromarray(noise, 'RGB')
37
+ image = Image.blend(image, noise_image, alpha=0.1)
38
+
39
+ # Эффект случайных царапин
40
+ if frame_number % (fps // 2) == 0: # Царапины реже
41
+ for _ in range(np.random.randint(1, 3)):
42
+ x1 = np.random.randint(0, width)
43
+ y1 = np.random.randint(0, height)
44
+ x2 = x1 + np.random.randint(-10, 10)
45
+ y2 = y1 + np.random.randint(-height // 4, height // 4)
46
+ draw.line([(x1, y1), (x2, y2)], fill="white", width=1)
47
+
48
+ # Эффект вертикальных полос
49
+ if frame_number % (fps // 3) == 0: # Полосы реже
50
+ for _ in range(np.random.randint(1, 2)):
51
+ stripe_x = np.random.randint(0, width)
52
+ stripe_width = np.random.randint(1, 3)
53
+ draw.rectangle([(stripe_x, 0), (stripe_x + stripe_width, height)], fill=(255, 255, 255, 50))
54
+
55
+ # Эффект мерцания (изменение яркости)
56
+ if frame_number % (fps // 4) == 0: # Мерцание реже
57
+ brightness_factor = 0.95 + 0.05 * np.random.random()
58
+ enhancer = ImageEnhance.Brightness(image)
59
+ image = enhancer.enhance(brightness_factor)
60
+
61
+ # Усиление контраста
62
+ contrast_enhancer = ImageEnhance.Contrast(image)
63
+ image = contrast_enhancer.enhance(1.2)
64
+
65
+ # Размытость для усиления эффекта
66
+ image = image.filter(ImageFilter.GaussianBlur(radius=0.3))
67
+ return np.array(image)
68
+
69
+
70
+ # Основная функция создания анимации
71
+ def create_film_effect(image_path, output_path, duration=1, fps=24):
72
+ base_image = Image.open(image_path).convert("RGB")
73
+ width, height = base_image.size
74
+
75
+ def make_frame(t):
76
+ frame_number = int(t * fps)
77
+
78
+ # Уменьшенная тряска кадра
79
+ offset_x = np.random.randint(-1, 2) # Сокращённое смещение
80
+ offset_y = np.random.randint(-1, 2)
81
+ jittered_image = Image.new("RGB", (width, height), "black")
82
+ jittered_image.paste(base_image, (offset_x, offset_y))
83
+ return add_film_effect(jittered_image, frame_number, fps)
84
+
85
+ # Создание видео из кадров
86
+ animation = VideoClip(make_frame, duration=duration)
87
+ animation.write_videofile(output_path, fps=fps)
88
+
89
+
90
+ def create_image_with_text(phrase, bottom_text1="НЕЙРОННЫЕ", bottom_text2="ХРОНИКИ"):
91
+ words = phrase.split()
92
+ word1 = words[0].upper()
93
+ word2 = words[1]
94
+ word2 = word2[0].upper() + word2[1:-1].lower() + word2[-1].upper()
95
+
96
+ img_size = 512
97
+ image = Image.new('RGB', (img_size, img_size), 'black')
98
+ draw = ImageDraw.Draw(image)
99
+
100
+ def get_impact_font(text, max_width, max_height, initial_size=100):
101
+ size = initial_size
102
+ font = ImageFont.truetype("impact.ttf", size)
103
+ while size > 1:
104
+ font = ImageFont.truetype("impact.ttf", size)
105
+ bbox = draw.textbbox((0, 0), text, font=font)
106
+ if bbox[2] - bbox[0] <= max_width and bbox[3] - bbox[1] <= max_height:
107
+ return font, bbox
108
+ size -= 1
109
+ return ImageFont.truetype("impact.ttf", 1), draw.textbbox((0, 0), text,
110
+ font=ImageFont.truetype("impact.ttf", 1))
111
+
112
+ def get_arial_font(text, max_width, max_height, initial_size=100):
113
+ size = initial_size
114
+ font = ImageFont.truetype("arialbd.ttf", size)
115
+ while size > 1:
116
+ font = ImageFont.truetype("arialbd.ttf", size)
117
+ bbox = draw.textbbox((0, 0), text, font=font)
118
+ if bbox[2] - bbox[0] <= max_width and bbox[3] - bbox[1] <= max_height:
119
+ return font, bbox
120
+ size -= 1
121
+ return ImageFont.truetype("arialbd.ttf", 1), draw.textbbox((0, 0), text,
122
+ font=ImageFont.truetype("arialbd.ttf", 1))
123
+
124
+ initial_font1, initial_bbox = get_impact_font(word1, img_size // 2, img_size // 6)
125
+ text1_width = initial_bbox[2] - initial_bbox[0]
126
+ text1_height = initial_bbox[3] - initial_bbox[1]
127
+
128
+ padding = 40
129
+ square_size = max(text1_width + padding * 2, text1_height + padding * 2)
130
+ square_position = ((img_size - square_size) // 2, (img_size - square_size) // 2)
131
+
132
+ draw.rectangle(
133
+ [square_position, (square_position[0] + square_size, square_position[1] + square_size)],
134
+ fill='red'
135
+ )
136
+
137
+ text1_position = (
138
+ (img_size - text1_width) // 2,
139
+ square_position[1] + padding // 2
140
+ )
141
+ draw.text(text1_position, word1, font=initial_font1, fill='black')
142
+
143
+ bottom_font, bottom_bbox = get_arial_font(bottom_text1, square_size - padding, square_size // 8, initial_size=33)
144
+ bottom_text1_width = bottom_bbox[2] - bottom_bbox[0]
145
+ bottom_text1_height = bottom_bbox[3] - bottom_bbox[1]
146
+
147
+ bottom_font2, bottom_bbox2 = get_arial_font(bottom_text2, square_size - padding, square_size // 8, initial_size=33)
148
+ bottom_text2_width = bottom_bbox2[2] - bottom_bbox2[0]
149
+ bottom_text2_height = bottom_bbox2[3] - bottom_bbox2[1]
150
+
151
+ spacing = 1 # Расстояние между строками Современные хроники
152
+
153
+ bottom_text1_position = (
154
+ (img_size - bottom_text1_width) // 2,
155
+ square_position[1] + square_size - padding - bottom_text1_height * 2 - spacing
156
+ )
157
+ bottom_text2_position = (
158
+ (img_size - bottom_text2_width) // 2,
159
+ bottom_text1_position[1] + bottom_text1_height + spacing
160
+ )
161
+
162
+ draw.text(bottom_text1_position, bottom_text1, font=bottom_font, fill='white')
163
+ draw.text(bottom_text2_position, bottom_text2, font=bottom_font2, fill='white')
164
+
165
+ font2, _ = get_impact_font(word2, square_size * 1.5, square_size // 2, initial_size=150)
166
+
167
+ kerning_offset = -3
168
+ total_width = 0
169
+ letter_widths = []
170
+ for letter in word2:
171
+ bbox = draw.textbbox((0, 0), letter, font=font2)
172
+ letter_width = bbox[2] - bbox[0]
173
+ letter_widths.append(letter_width)
174
+ total_width += letter_width
175
+
176
+ total_width += kerning_offset * (len(word2) - 1)
177
+ start_x = (img_size - total_width) // 2
178
+ text_height = draw.textbbox((0, 0), word2, font=font2)[3] - draw.textbbox((0, 0), word2, font=font2)[1]
179
+ y_position = (img_size - text_height) // 2 - 20 # Поднимаем второе слово вверх
180
+
181
+ current_x = start_x
182
+ for i, letter in enumerate(word2):
183
+ draw.text((current_x, y_position), letter, font=font2, fill='white')
184
+ current_x += letter_widths[i] + kerning_offset
185
+
186
+ return image
187
+
188
+
189
+ def greet(text, duration):
190
+ text = text.replace("-", " ").replace("gate", "нейро")
191
+ print(text)
192
+ if len(text.split()) == 1:
193
+ text = f"Нейро {text}"
194
+
195
+ # create image
196
+ print("create image")
197
+ clear_text = re.sub(r'[^a-zA-Zа-яА-ЯёЁ ]', '', text)
198
+ image = create_image_with_text(clear_text)
199
+ image.save("output5.png")
200
+
201
+ # create video
202
+ print("create video")
203
+ create_film_effect("output5.png", "output_film_effect.mp4", duration=duration)
204
+
205
+ return ["output_film_effect.mp4", "output5.png"]
206
+
207
+
208
+ demo = gr.Interface(fn=greet, inputs=[
209
+ gr.Text(label="Text", value="Операция лесополоса"),
210
+ gr.Slider(value=1)], outputs=[gr.Video(), gr.Image()])
211
+
212
+ demo.queue(api_open=True).launch(show_error=True, show_api=True)