Spaces:
Sleeping
Sleeping
MinAA commited on
Commit ·
8dc8851
1
Parent(s): 0c72405
init
Browse files
app.py
CHANGED
|
@@ -6,7 +6,8 @@ from transformers import (
|
|
| 6 |
)
|
| 7 |
import torch
|
| 8 |
from torch.nn.functional import cosine_similarity
|
| 9 |
-
from PIL import Image
|
|
|
|
| 10 |
import functools
|
| 11 |
import warnings
|
| 12 |
import time
|
|
@@ -134,8 +135,15 @@ def measure_time_and_save(task_name):
|
|
| 134 |
if isinstance(result, str):
|
| 135 |
output = result
|
| 136 |
elif isinstance(result, tuple) and len(result) == 2:
|
| 137 |
-
#
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
else:
|
| 140 |
output = str(result)[:500]
|
| 141 |
except Exception as e:
|
|
@@ -360,6 +368,8 @@ def speech_recognition(audio, model_name):
|
|
| 360 |
def speech_synthesis(text, model_name):
|
| 361 |
"""Синтез речи"""
|
| 362 |
try:
|
|
|
|
|
|
|
| 363 |
if "speecht5" in model_name.lower():
|
| 364 |
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan
|
| 365 |
import torch
|
|
@@ -381,17 +391,85 @@ def speech_synthesis(text, model_name):
|
|
| 381 |
with torch.no_grad():
|
| 382 |
speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)
|
| 383 |
|
| 384 |
-
|
| 385 |
audio_data = speech.numpy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 386 |
sample_rate = 16000
|
| 387 |
return (sample_rate, audio_data)
|
| 388 |
else:
|
| 389 |
# Для других моделей используем стандартный pipeline
|
| 390 |
tts = get_pipeline("text-to-speech", model_name)
|
| 391 |
result = tts(text)
|
| 392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 393 |
except Exception as e:
|
| 394 |
-
|
|
|
|
|
|
|
| 395 |
|
| 396 |
# ==================== ЗАДАЧИ С ИЗОБРАЖЕНИЯМИ ====================
|
| 397 |
|
|
@@ -401,12 +479,91 @@ def object_detection(image, model_name):
|
|
| 401 |
try:
|
| 402 |
detector = get_pipeline("object-detection", model_name)
|
| 403 |
result = detector(image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
output = "Обнаруженные объекты:\n"
|
| 405 |
-
for item in result:
|
| 406 |
-
|
| 407 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 408 |
except Exception as e:
|
| 409 |
-
return f"Ошибка: {str(e)}"
|
| 410 |
|
| 411 |
@measure_time_and_save("Сегментация изображений")
|
| 412 |
def image_segmentation(image, model_name):
|
|
@@ -414,12 +571,88 @@ def image_segmentation(image, model_name):
|
|
| 414 |
try:
|
| 415 |
segmenter = get_pipeline("image-segmentation", model_name)
|
| 416 |
result = segmenter(image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
output = "Сегменты:\n"
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
except Exception as e:
|
| 422 |
-
return f"Ошибка: {str(e)}"
|
| 423 |
|
| 424 |
@measure_time_and_save("Сопоставление изображение-текст")
|
| 425 |
def image_text_matching(image, text, model_name):
|
|
@@ -711,8 +944,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 711 |
with gr.Column():
|
| 712 |
text_classifier_input = gr.Textbox(
|
| 713 |
label="Введите текст для классификации",
|
| 714 |
-
placeholder="
|
| 715 |
-
value="
|
| 716 |
)
|
| 717 |
text_classifier_model = gr.Dropdown(
|
| 718 |
choices=[
|
|
@@ -737,13 +970,13 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 737 |
with gr.Column():
|
| 738 |
zs_text_input = gr.Textbox(
|
| 739 |
label="Введите текст",
|
| 740 |
-
placeholder="
|
| 741 |
-
value="
|
| 742 |
)
|
| 743 |
zs_text_labels = gr.Textbox(
|
| 744 |
label="Кандидаты (через запятую)",
|
| 745 |
-
placeholder="
|
| 746 |
-
value="
|
| 747 |
)
|
| 748 |
zs_text_model = gr.Dropdown(
|
| 749 |
choices=[
|
|
@@ -768,8 +1001,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 768 |
with gr.Column():
|
| 769 |
text_gen_input = gr.Textbox(
|
| 770 |
label="Промпт",
|
| 771 |
-
placeholder="
|
| 772 |
-
value="
|
| 773 |
)
|
| 774 |
text_gen_length = gr.Slider(20, 200, value=50, step=10, label="Максимальная длина")
|
| 775 |
text_gen_model = gr.Dropdown(
|
|
@@ -791,8 +1024,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 791 |
with gr.Column():
|
| 792 |
unmasker_input = gr.Textbox(
|
| 793 |
label="Текст с [MASK]",
|
| 794 |
-
placeholder="
|
| 795 |
-
value="
|
| 796 |
)
|
| 797 |
unmasker_model = gr.Dropdown(
|
| 798 |
choices=[
|
|
@@ -817,8 +1050,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 817 |
with gr.Column():
|
| 818 |
ner_input = gr.Textbox(
|
| 819 |
label="Введите текст",
|
| 820 |
-
placeholder="
|
| 821 |
-
value="
|
| 822 |
)
|
| 823 |
ner_model = gr.Dropdown(
|
| 824 |
choices=[
|
|
@@ -843,13 +1076,13 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 843 |
with gr.Column():
|
| 844 |
qa_question = gr.Textbox(
|
| 845 |
label="Вопрос",
|
| 846 |
-
placeholder="
|
| 847 |
-
value="
|
| 848 |
)
|
| 849 |
qa_context = gr.Textbox(
|
| 850 |
label="Контекст",
|
| 851 |
-
placeholder="
|
| 852 |
-
value="
|
| 853 |
lines=3
|
| 854 |
)
|
| 855 |
qa_model = gr.Dropdown(
|
|
@@ -875,8 +1108,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 875 |
with gr.Column():
|
| 876 |
summarizer_input = gr.Textbox(
|
| 877 |
label="Текст для суммаризации",
|
| 878 |
-
placeholder="
|
| 879 |
-
value="
|
| 880 |
lines=5
|
| 881 |
)
|
| 882 |
summarizer_max = gr.Slider(20, 200, value=50, step=10, label="Максимальная длина")
|
|
@@ -996,8 +1229,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 996 |
)
|
| 997 |
zs_audio_labels = gr.Textbox(
|
| 998 |
label="Кандидаты (через запятую)",
|
| 999 |
-
placeholder="
|
| 1000 |
-
value="
|
| 1001 |
)
|
| 1002 |
zs_audio_model = gr.Dropdown(
|
| 1003 |
choices=["laion/clap-htsat-unfused"],
|
|
@@ -1043,8 +1276,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1043 |
with gr.Column():
|
| 1044 |
tts_input = gr.Textbox(
|
| 1045 |
label="Введите текст для синтеза",
|
| 1046 |
-
placeholder="
|
| 1047 |
-
value="
|
| 1048 |
lines=3
|
| 1049 |
)
|
| 1050 |
tts_model = gr.Dropdown(
|
|
@@ -1088,10 +1321,11 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1088 |
obj_det_btn = gr.Button("Обнаружить объекты", variant="primary")
|
| 1089 |
with gr.Column():
|
| 1090 |
obj_det_output = gr.Textbox(label="Результат", lines=8)
|
|
|
|
| 1091 |
obj_det_btn.click(
|
| 1092 |
object_detection,
|
| 1093 |
inputs=[obj_det_input, obj_det_model],
|
| 1094 |
-
outputs=obj_det_output
|
| 1095 |
)
|
| 1096 |
|
| 1097 |
with gr.Accordion("Сегментация изображений", open=False):
|
|
@@ -1113,10 +1347,11 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1113 |
seg_btn = gr.Button("Сегментировать", variant="primary")
|
| 1114 |
with gr.Column():
|
| 1115 |
seg_output = gr.Textbox(label="Результат", lines=8)
|
|
|
|
| 1116 |
seg_btn.click(
|
| 1117 |
image_segmentation,
|
| 1118 |
inputs=[seg_input, seg_model],
|
| 1119 |
-
outputs=seg_output
|
| 1120 |
)
|
| 1121 |
|
| 1122 |
with gr.Accordion("Сопоставление изображение-текст", open=False):
|
|
@@ -1128,8 +1363,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1128 |
)
|
| 1129 |
itm_text = gr.Textbox(
|
| 1130 |
label="Введите текст",
|
| 1131 |
-
placeholder="
|
| 1132 |
-
value="
|
| 1133 |
)
|
| 1134 |
itm_model = gr.Dropdown(
|
| 1135 |
choices=[
|
|
@@ -1183,8 +1418,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1183 |
)
|
| 1184 |
vqa_question = gr.Textbox(
|
| 1185 |
label="Вопрос",
|
| 1186 |
-
placeholder="
|
| 1187 |
-
value="
|
| 1188 |
)
|
| 1189 |
vqa_model = gr.Dropdown(
|
| 1190 |
choices=[
|
|
@@ -1213,8 +1448,8 @@ with gr.Blocks(title="Трансформеры Hugging Face", theme=gr.themes.So
|
|
| 1213 |
)
|
| 1214 |
zs_image_labels = gr.Textbox(
|
| 1215 |
label="Кандидаты (через запятую)",
|
| 1216 |
-
placeholder="
|
| 1217 |
-
value="
|
| 1218 |
)
|
| 1219 |
zs_image_model = gr.Dropdown(
|
| 1220 |
choices=[
|
|
|
|
| 6 |
)
|
| 7 |
import torch
|
| 8 |
from torch.nn.functional import cosine_similarity
|
| 9 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 10 |
+
import numpy as np
|
| 11 |
import functools
|
| 12 |
import warnings
|
| 13 |
import time
|
|
|
|
| 135 |
if isinstance(result, str):
|
| 136 |
output = result
|
| 137 |
elif isinstance(result, tuple) and len(result) == 2:
|
| 138 |
+
# Проверяем тип второго элемента
|
| 139 |
+
if isinstance(result[1], Image.Image):
|
| 140 |
+
# Результат с изображением (текст, изображение)
|
| 141 |
+
output = result[0] if isinstance(result[0], str) else str(result[0])[:500]
|
| 142 |
+
elif isinstance(result[1], (tuple, list)) and len(result[1]) == 2:
|
| 143 |
+
# Аудио результат (sample_rate, audio_data)
|
| 144 |
+
output = f"Аудио файл сгенерирован (sample_rate: {result[0]})"
|
| 145 |
+
else:
|
| 146 |
+
output = str(result)[:500]
|
| 147 |
else:
|
| 148 |
output = str(result)[:500]
|
| 149 |
except Exception as e:
|
|
|
|
| 368 |
def speech_synthesis(text, model_name):
|
| 369 |
"""Синтез речи"""
|
| 370 |
try:
|
| 371 |
+
import numpy as np
|
| 372 |
+
|
| 373 |
if "speecht5" in model_name.lower():
|
| 374 |
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech, SpeechT5HifiGan
|
| 375 |
import torch
|
|
|
|
| 391 |
with torch.no_grad():
|
| 392 |
speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)
|
| 393 |
|
| 394 |
+
# Конвертируем в numpy и нормализуем
|
| 395 |
audio_data = speech.numpy()
|
| 396 |
+
# Убеждаемся, что это 1D массив
|
| 397 |
+
if len(audio_data.shape) > 1:
|
| 398 |
+
audio_data = audio_data.flatten()
|
| 399 |
+
# Нормализуем в диапазон [-1, 1] если нужно
|
| 400 |
+
if audio_data.dtype != np.float32:
|
| 401 |
+
audio_data = audio_data.astype(np.float32)
|
| 402 |
+
# Нормализуем если значения выходят за пределы [-1, 1]
|
| 403 |
+
max_val = np.abs(audio_data).max()
|
| 404 |
+
if max_val > 1.0:
|
| 405 |
+
audio_data = audio_data / max_val
|
| 406 |
+
|
| 407 |
sample_rate = 16000
|
| 408 |
return (sample_rate, audio_data)
|
| 409 |
else:
|
| 410 |
# Для других моделей используем стандартный pipeline
|
| 411 |
tts = get_pipeline("text-to-speech", model_name)
|
| 412 |
result = tts(text)
|
| 413 |
+
|
| 414 |
+
# Pipeline может возвращать словарь или кортеж
|
| 415 |
+
if isinstance(result, dict):
|
| 416 |
+
# Стандартный формат: {"audio": array, "sampling_rate": int}
|
| 417 |
+
audio_data = result.get("audio", result.get("raw", None))
|
| 418 |
+
sample_rate = result.get("sampling_rate", result.get("sample_rate", 22050))
|
| 419 |
+
|
| 420 |
+
if audio_data is None:
|
| 421 |
+
raise ValueError("Не удалось извлечь аудио данные из результата pipeline")
|
| 422 |
+
|
| 423 |
+
# Конвертируем в numpy array если нужно
|
| 424 |
+
if isinstance(audio_data, torch.Tensor):
|
| 425 |
+
audio_data = audio_data.numpy()
|
| 426 |
+
elif not isinstance(audio_data, np.ndarray):
|
| 427 |
+
audio_data = np.array(audio_data)
|
| 428 |
+
|
| 429 |
+
# Убеждаемся, что это 1D массив
|
| 430 |
+
if len(audio_data.shape) > 1:
|
| 431 |
+
audio_data = audio_data.flatten()
|
| 432 |
+
|
| 433 |
+
# Нормализуем в float32
|
| 434 |
+
if audio_data.dtype != np.float32:
|
| 435 |
+
audio_data = audio_data.astype(np.float32)
|
| 436 |
+
|
| 437 |
+
# Нормализуем если значения выходят за пределы [-1, 1]
|
| 438 |
+
max_val = np.abs(audio_data).max()
|
| 439 |
+
if max_val > 1.0:
|
| 440 |
+
audio_data = audio_data / max_val
|
| 441 |
+
|
| 442 |
+
return (sample_rate, audio_data)
|
| 443 |
+
elif isinstance(result, tuple) and len(result) == 2:
|
| 444 |
+
# Уже в правильном формате (sample_rate, audio_data)
|
| 445 |
+
sample_rate, audio_data = result
|
| 446 |
+
|
| 447 |
+
# Конвертируем в numpy если нужно
|
| 448 |
+
if isinstance(audio_data, torch.Tensor):
|
| 449 |
+
audio_data = audio_data.numpy()
|
| 450 |
+
elif not isinstance(audio_data, np.ndarray):
|
| 451 |
+
audio_data = np.array(audio_data)
|
| 452 |
+
|
| 453 |
+
# Убеждаемся, что это 1D массив
|
| 454 |
+
if len(audio_data.shape) > 1:
|
| 455 |
+
audio_data = audio_data.flatten()
|
| 456 |
+
|
| 457 |
+
# Нормализуем в float32
|
| 458 |
+
if audio_data.dtype != np.float32:
|
| 459 |
+
audio_data = audio_data.astype(np.float32)
|
| 460 |
+
|
| 461 |
+
# Нормализуем если значения выходят за пределы [-1, 1]
|
| 462 |
+
max_val = np.abs(audio_data).max()
|
| 463 |
+
if max_val > 1.0:
|
| 464 |
+
audio_data = audio_data / max_val
|
| 465 |
+
|
| 466 |
+
return (sample_rate, audio_data)
|
| 467 |
+
else:
|
| 468 |
+
raise ValueError(f"Неожиданный формат результата от pipeline: {type(result)}")
|
| 469 |
except Exception as e:
|
| 470 |
+
# В случае ошибки возвращаем None, чтобы Gradio мог обработать это
|
| 471 |
+
# Но также логируем ошибку в историю через декоратор
|
| 472 |
+
raise Exception(f"Ошибка синтеза речи: {str(e)}")
|
| 473 |
|
| 474 |
# ==================== ЗАДАЧИ С ИЗОБРАЖЕНИЯМИ ====================
|
| 475 |
|
|
|
|
| 479 |
try:
|
| 480 |
detector = get_pipeline("object-detection", model_name)
|
| 481 |
result = detector(image)
|
| 482 |
+
|
| 483 |
+
# Создаем копию изображения для визуализации
|
| 484 |
+
img_with_boxes = image.copy()
|
| 485 |
+
draw = ImageDraw.Draw(img_with_boxes)
|
| 486 |
+
|
| 487 |
+
# Цвета для разных объектов
|
| 488 |
+
colors = ['red', 'blue', 'green', 'yellow', 'orange', 'purple', 'cyan', 'magenta']
|
| 489 |
+
|
| 490 |
output = "Обнаруженные объекты:\n"
|
| 491 |
+
for i, item in enumerate(result):
|
| 492 |
+
box = item['box']
|
| 493 |
+
label = item['label']
|
| 494 |
+
score = item['score']
|
| 495 |
+
|
| 496 |
+
# Обрабатываем различные форматы координат
|
| 497 |
+
if isinstance(box, dict):
|
| 498 |
+
# Словарь с ключами 'xmin', 'ymin', 'xmax', 'ymax'
|
| 499 |
+
xmin = box.get('xmin', box.get('x1', 0))
|
| 500 |
+
ymin = box.get('ymin', box.get('y1', 0))
|
| 501 |
+
xmax = box.get('xmax', box.get('x2', 0))
|
| 502 |
+
ymax = box.get('ymax', box.get('y2', 0))
|
| 503 |
+
elif isinstance(box, (list, tuple)) and len(box) >= 4:
|
| 504 |
+
# Список [xmin, ymin, xmax, ymax] или [xcenter, ycenter, width, height]
|
| 505 |
+
if box[2] > box[0] and box[3] > box[1]:
|
| 506 |
+
# Вероятно [xmin, ymin, xmax, ymax]
|
| 507 |
+
xmin, ymin, xmax, ymax = box[0], box[1], box[2], box[3]
|
| 508 |
+
else:
|
| 509 |
+
# Вероятно [xcenter, ycenter, width, height]
|
| 510 |
+
xcenter, ycenter, width, height = box[0], box[1], box[2], box[3]
|
| 511 |
+
xmin = xcenter - width / 2
|
| 512 |
+
ymin = ycenter - height / 2
|
| 513 |
+
xmax = xcenter + width / 2
|
| 514 |
+
ymax = ycenter + height / 2
|
| 515 |
+
else:
|
| 516 |
+
# Неизвестный формат, пропускаем
|
| 517 |
+
output += f"{label}: уверенность {score:.4f}, координаты {box}\n"
|
| 518 |
+
continue
|
| 519 |
+
|
| 520 |
+
# Проверяем и ограничиваем координаты границами изображения
|
| 521 |
+
img_width, img_height = img_with_boxes.size
|
| 522 |
+
xmin = max(0, min(xmin, img_width))
|
| 523 |
+
ymin = max(0, min(ymin, img_height))
|
| 524 |
+
xmax = max(0, min(xmax, img_width))
|
| 525 |
+
ymax = max(0, min(ymax, img_height))
|
| 526 |
+
|
| 527 |
+
# Проверяем, что координаты валидны
|
| 528 |
+
if xmax <= xmin or ymax <= ymin:
|
| 529 |
+
output += f"{label}: уверенность {score:.4f}, координаты {box} (некорректные)\n"
|
| 530 |
+
continue
|
| 531 |
+
|
| 532 |
+
# Рисуем прямоугольник
|
| 533 |
+
color = colors[i % len(colors)]
|
| 534 |
+
draw.rectangle([xmin, ymin, xmax, ymax], outline=color, width=3)
|
| 535 |
+
|
| 536 |
+
# Добавляем текст с меткой и уверенностью
|
| 537 |
+
text = f"{label}: {score:.2f}"
|
| 538 |
+
try:
|
| 539 |
+
# Пытаемся использовать системный шрифт
|
| 540 |
+
font = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 16)
|
| 541 |
+
except:
|
| 542 |
+
try:
|
| 543 |
+
font = ImageFont.load_default()
|
| 544 |
+
except:
|
| 545 |
+
font = None
|
| 546 |
+
|
| 547 |
+
# Получаем размер текста
|
| 548 |
+
if font:
|
| 549 |
+
bbox = draw.textbbox((0, 0), text, font=font)
|
| 550 |
+
text_width = bbox[2] - bbox[0]
|
| 551 |
+
text_height = bbox[3] - bbox[1]
|
| 552 |
+
else:
|
| 553 |
+
text_width = len(text) * 6
|
| 554 |
+
text_height = 12
|
| 555 |
+
|
| 556 |
+
# Рисуем фон для текста (проверяем границы)
|
| 557 |
+
text_y = max(0, ymin - text_height - 4)
|
| 558 |
+
text_x_end = min(img_width, xmin + text_width + 4)
|
| 559 |
+
draw.rectangle([xmin, text_y, text_x_end, ymin], fill=color)
|
| 560 |
+
draw.text((xmin + 2, text_y + 2), text, fill='white', font=font)
|
| 561 |
+
|
| 562 |
+
output += f"{label}: уверенность {score:.4f}, координаты {box}\n"
|
| 563 |
+
|
| 564 |
+
return output, img_with_boxes
|
| 565 |
except Exception as e:
|
| 566 |
+
return f"Ошибка: {str(e)}", image
|
| 567 |
|
| 568 |
@measure_time_and_save("Сегментация изображений")
|
| 569 |
def image_segmentation(image, model_name):
|
|
|
|
| 571 |
try:
|
| 572 |
segmenter = get_pipeline("image-segmentation", model_name)
|
| 573 |
result = segmenter(image)
|
| 574 |
+
|
| 575 |
+
# Создаем копию изображения для визуализации
|
| 576 |
+
img_with_segments = image.copy().convert("RGBA")
|
| 577 |
+
|
| 578 |
+
# Генерируем цвета для сегментов
|
| 579 |
+
np.random.seed(42) # Для воспроизводимости
|
| 580 |
+
|
| 581 |
output = "Сегменты:\n"
|
| 582 |
+
overlay = Image.new("RGBA", image.size, (0, 0, 0, 0))
|
| 583 |
+
draw = ImageDraw.Draw(overlay)
|
| 584 |
+
|
| 585 |
+
for i, item in enumerate(result):
|
| 586 |
+
label = item['label']
|
| 587 |
+
score = item['score']
|
| 588 |
+
|
| 589 |
+
# Генерируем полупрозрачный цвет для сегмента
|
| 590 |
+
color = tuple(np.random.randint(0, 255, 3)) + (128,) # RGBA с прозрачностью
|
| 591 |
+
|
| 592 |
+
# Проверяем наличие маски
|
| 593 |
+
if 'mask' in item:
|
| 594 |
+
mask = item['mask']
|
| 595 |
+
|
| 596 |
+
# Преобразуем маску в numpy array
|
| 597 |
+
if isinstance(mask, Image.Image):
|
| 598 |
+
mask_array = np.array(mask)
|
| 599 |
+
elif isinstance(mask, np.ndarray):
|
| 600 |
+
mask_array = mask
|
| 601 |
+
else:
|
| 602 |
+
mask_array = np.array(mask)
|
| 603 |
+
|
| 604 |
+
# Нормализуем маску, если нужно
|
| 605 |
+
if mask_array.dtype != np.uint8:
|
| 606 |
+
if mask_array.max() <= 1.0:
|
| 607 |
+
mask_array = (mask_array * 255).astype(np.uint8)
|
| 608 |
+
else:
|
| 609 |
+
mask_array = mask_array.astype(np.uint8)
|
| 610 |
+
|
| 611 |
+
# Создаем цветную маску
|
| 612 |
+
if len(mask_array.shape) == 2: # Grayscale mask
|
| 613 |
+
# Создаем RGBA маску
|
| 614 |
+
colored_mask = np.zeros((mask_array.shape[0], mask_array.shape[1], 4), dtype=np.uint8)
|
| 615 |
+
# Применяем цвет только там, где маска не равна нулю
|
| 616 |
+
mask_bool = mask_array > 0
|
| 617 |
+
colored_mask[mask_bool, :3] = color[:3]
|
| 618 |
+
colored_mask[mask_bool, 3] = 128 # Альфа-канал
|
| 619 |
+
elif len(mask_array.shape) == 3 and mask_array.shape[2] == 1:
|
| 620 |
+
# Маска с одним каналом
|
| 621 |
+
colored_mask = np.zeros((mask_array.shape[0], mask_array.shape[1], 4), dtype=np.uint8)
|
| 622 |
+
mask_bool = mask_array[:, :, 0] > 0
|
| 623 |
+
colored_mask[mask_bool, :3] = color[:3]
|
| 624 |
+
colored_mask[mask_bool, 3] = 128
|
| 625 |
+
else:
|
| 626 |
+
# Многоканальная маска
|
| 627 |
+
colored_mask = np.zeros((mask_array.shape[0], mask_array.shape[1], 4), dtype=np.uint8)
|
| 628 |
+
# Используем первый канал как маску
|
| 629 |
+
if mask_array.shape[2] >= 1:
|
| 630 |
+
mask_bool = mask_array[:, :, 0] > 0
|
| 631 |
+
colored_mask[mask_bool, :3] = color[:3]
|
| 632 |
+
colored_mask[mask_bool, 3] = 128
|
| 633 |
+
|
| 634 |
+
# Убеждаемся, что размеры совпадают
|
| 635 |
+
if colored_mask.shape[:2] == img_with_segments.size[::-1]:
|
| 636 |
+
mask_img = Image.fromarray(colored_mask, mode='RGBA')
|
| 637 |
+
overlay = Image.alpha_composite(overlay, mask_img)
|
| 638 |
+
elif colored_mask.shape[:2] != overlay.size[::-1]:
|
| 639 |
+
# Изменяем размер маски, если нужно
|
| 640 |
+
mask_img = Image.fromarray(colored_mask, mode='RGBA')
|
| 641 |
+
mask_img = mask_img.resize(overlay.size, Image.Resampling.LANCZOS)
|
| 642 |
+
overlay = Image.alpha_composite(overlay, mask_img)
|
| 643 |
+
|
| 644 |
+
output += f"{label}: уверенность {score:.4f}\n"
|
| 645 |
+
|
| 646 |
+
# Накладываем overlay на исходное изображение
|
| 647 |
+
if overlay.size == img_with_segments.size:
|
| 648 |
+
img_with_segments = Image.alpha_composite(img_with_segments, overlay)
|
| 649 |
+
|
| 650 |
+
# Конвертируем обратно в RGB для отображения
|
| 651 |
+
img_with_segments = img_with_segments.convert("RGB")
|
| 652 |
+
|
| 653 |
+
return output, img_with_segments
|
| 654 |
except Exception as e:
|
| 655 |
+
return f"Ошибка: {str(e)}", image
|
| 656 |
|
| 657 |
@measure_time_and_save("Сопоставление изображение-текст")
|
| 658 |
def image_text_matching(image, text, model_name):
|
|
|
|
| 944 |
with gr.Column():
|
| 945 |
text_classifier_input = gr.Textbox(
|
| 946 |
label="Введите текст для классификации",
|
| 947 |
+
placeholder="I love this app!",
|
| 948 |
+
value="I love this app!"
|
| 949 |
)
|
| 950 |
text_classifier_model = gr.Dropdown(
|
| 951 |
choices=[
|
|
|
|
| 970 |
with gr.Column():
|
| 971 |
zs_text_input = gr.Textbox(
|
| 972 |
label="Введите текст",
|
| 973 |
+
placeholder="I just finished reading a great book",
|
| 974 |
+
value="I just finished reading a great book"
|
| 975 |
)
|
| 976 |
zs_text_labels = gr.Textbox(
|
| 977 |
label="Кандидаты (через запятую)",
|
| 978 |
+
placeholder="positive, negative, neutral",
|
| 979 |
+
value="positive, negative, neutral"
|
| 980 |
)
|
| 981 |
zs_text_model = gr.Dropdown(
|
| 982 |
choices=[
|
|
|
|
| 1001 |
with gr.Column():
|
| 1002 |
text_gen_input = gr.Textbox(
|
| 1003 |
label="Промпт",
|
| 1004 |
+
placeholder="In the distant future",
|
| 1005 |
+
value="In the distant future"
|
| 1006 |
)
|
| 1007 |
text_gen_length = gr.Slider(20, 200, value=50, step=10, label="Максимальная длина")
|
| 1008 |
text_gen_model = gr.Dropdown(
|
|
|
|
| 1024 |
with gr.Column():
|
| 1025 |
unmasker_input = gr.Textbox(
|
| 1026 |
label="Текст с [MASK]",
|
| 1027 |
+
placeholder="I love [MASK] programming",
|
| 1028 |
+
value="I love [MASK] programming"
|
| 1029 |
)
|
| 1030 |
unmasker_model = gr.Dropdown(
|
| 1031 |
choices=[
|
|
|
|
| 1050 |
with gr.Column():
|
| 1051 |
ner_input = gr.Textbox(
|
| 1052 |
label="Введите текст",
|
| 1053 |
+
placeholder="My name is John, I work at Microsoft in Seattle",
|
| 1054 |
+
value="My name is John, I work at Microsoft in Seattle"
|
| 1055 |
)
|
| 1056 |
ner_model = gr.Dropdown(
|
| 1057 |
choices=[
|
|
|
|
| 1076 |
with gr.Column():
|
| 1077 |
qa_question = gr.Textbox(
|
| 1078 |
label="Вопрос",
|
| 1079 |
+
placeholder="What color is the sky?",
|
| 1080 |
+
value="What color is the sky?"
|
| 1081 |
)
|
| 1082 |
qa_context = gr.Textbox(
|
| 1083 |
label="Контекст",
|
| 1084 |
+
placeholder="The sky is blue due to light scattering",
|
| 1085 |
+
value="The sky is blue due to light scattering in the atmosphere",
|
| 1086 |
lines=3
|
| 1087 |
)
|
| 1088 |
qa_model = gr.Dropdown(
|
|
|
|
| 1108 |
with gr.Column():
|
| 1109 |
summarizer_input = gr.Textbox(
|
| 1110 |
label="Текст для суммаризации",
|
| 1111 |
+
placeholder="Enter a long text...",
|
| 1112 |
+
value="Artificial intelligence is a field of computer science that focuses on creating intelligent machines. Machine learning is a subset of artificial intelligence that enables systems to automatically learn and improve from experience.",
|
| 1113 |
lines=5
|
| 1114 |
)
|
| 1115 |
summarizer_max = gr.Slider(20, 200, value=50, step=10, label="Максимальная длина")
|
|
|
|
| 1229 |
)
|
| 1230 |
zs_audio_labels = gr.Textbox(
|
| 1231 |
label="Кандидаты (через запятую)",
|
| 1232 |
+
placeholder="music, speech, noise",
|
| 1233 |
+
value="music, speech, noise"
|
| 1234 |
)
|
| 1235 |
zs_audio_model = gr.Dropdown(
|
| 1236 |
choices=["laion/clap-htsat-unfused"],
|
|
|
|
| 1276 |
with gr.Column():
|
| 1277 |
tts_input = gr.Textbox(
|
| 1278 |
label="Введите текст для синтеза",
|
| 1279 |
+
placeholder="Hello, this is a speech synthesis test",
|
| 1280 |
+
value="Hello, this is a speech synthesis test",
|
| 1281 |
lines=3
|
| 1282 |
)
|
| 1283 |
tts_model = gr.Dropdown(
|
|
|
|
| 1321 |
obj_det_btn = gr.Button("Обнаружить объекты", variant="primary")
|
| 1322 |
with gr.Column():
|
| 1323 |
obj_det_output = gr.Textbox(label="Результат", lines=8)
|
| 1324 |
+
obj_det_image = gr.Image(label="Изображение с результатами", type="pil")
|
| 1325 |
obj_det_btn.click(
|
| 1326 |
object_detection,
|
| 1327 |
inputs=[obj_det_input, obj_det_model],
|
| 1328 |
+
outputs=[obj_det_output, obj_det_image]
|
| 1329 |
)
|
| 1330 |
|
| 1331 |
with gr.Accordion("Сегментация изображений", open=False):
|
|
|
|
| 1347 |
seg_btn = gr.Button("Сегментировать", variant="primary")
|
| 1348 |
with gr.Column():
|
| 1349 |
seg_output = gr.Textbox(label="Результат", lines=8)
|
| 1350 |
+
seg_image = gr.Image(label="Изображение с результатами", type="pil")
|
| 1351 |
seg_btn.click(
|
| 1352 |
image_segmentation,
|
| 1353 |
inputs=[seg_input, seg_model],
|
| 1354 |
+
outputs=[seg_output, seg_image]
|
| 1355 |
)
|
| 1356 |
|
| 1357 |
with gr.Accordion("Сопоставление изображение-текст", open=False):
|
|
|
|
| 1363 |
)
|
| 1364 |
itm_text = gr.Textbox(
|
| 1365 |
label="Введите текст",
|
| 1366 |
+
placeholder="a cat sitting on the grass",
|
| 1367 |
+
value="a cat sitting on the grass"
|
| 1368 |
)
|
| 1369 |
itm_model = gr.Dropdown(
|
| 1370 |
choices=[
|
|
|
|
| 1418 |
)
|
| 1419 |
vqa_question = gr.Textbox(
|
| 1420 |
label="Вопрос",
|
| 1421 |
+
placeholder="What is in the image?",
|
| 1422 |
+
value="What is in the image?"
|
| 1423 |
)
|
| 1424 |
vqa_model = gr.Dropdown(
|
| 1425 |
choices=[
|
|
|
|
| 1448 |
)
|
| 1449 |
zs_image_labels = gr.Textbox(
|
| 1450 |
label="Кандидаты (через запятую)",
|
| 1451 |
+
placeholder="cat, dog, bird",
|
| 1452 |
+
value="cat, dog, bird"
|
| 1453 |
)
|
| 1454 |
zs_image_model = gr.Dropdown(
|
| 1455 |
choices=[
|