train_utility/src/yolo_webui/static/index.html
2026-08-05 10:14:17 +04:00

541 lines
32 KiB
HTML
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>YOLO Train Studio</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
<link rel="stylesheet" href="/static/style.css?v=6">
</head>
<body>
<header class="app-header">
<div class="header-logo">
<svg class="logo-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</svg>
<div class="logo-text" style="margin-right: 2rem;">
<h1>YOLO Train Studio</h1>
<span>Интерфейс обучения модели</span>
</div>
<div class="view-tabs" style="display: flex; gap: 10px;">
<button class="view-btn active" data-view="train-view">Обучение</button>
<button class="view-btn" data-view="export-view">Экспорт</button>
</div>
</div>
<div class="header-actions">
<a href="http://localhost:5000" target="_blank" rel="noopener noreferrer" class="mlflow-link" id="mlflow-header-link">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="link-icon">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
Открыть MLflow UI
</a>
</div>
</header>
<main class="app-workspace">
<div id="train-view" class="workspace-view active">
<!-- Configuration Card -->
<section class="pane" id="config-pane">
<!-- Session Controls -->
<div class="session-controls">
<div class="session-header">
<svg class="session-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
<polyline points="17 21 17 13 7 13 7 21"></polyline>
<polyline points="7 3 7 8 15 8"></polyline>
</svg>
<h3>Профили конфигурации</h3>
</div>
<div class="session-body">
<div class="session-row">
<div class="session-field">
<label for="session-select">Активный профиль</label>
<select id="session-select">
<option value="">По умолчанию (Последний запуск)</option>
</select>
</div>
<button type="button" id="session-delete-btn" class="btn-action btn-delete" disabled title="Удалить выбранный профиль">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="btn-icon-small"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
</button>
</div>
<div class="session-row">
<div class="session-field">
<label for="session-name">Сохранить текущие настройки как профиль</label>
<input type="text" id="session-name" pattern="[A-Za-z0-9_-]+" autocomplete="off" placeholder="Введите имя профиля...">
</div>
<button type="button" id="session-save-btn" class="btn-action btn-save" title="Сохранить настройки">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="btn-icon-small"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline></svg>
</button>
</div>
</div>
</div>
<div class="tabs">
<button class="tab-btn active" data-tab="general">Основное</button>
<button class="tab-btn" data-tab="training">Обучение</button>
<button class="tab-btn" data-tab="augmentation">Аугментация</button>
<button class="tab-btn" data-tab="mlflow">MLflow</button>
</div>
<form id="config-form" class="form-container">
<!-- GENERAL TAB -->
<div class="tab-content active" id="tab-general">
<div class="form-section-title">Модель и Данные</div>
<div class="field">
<label for="task">Тип задачи</label>
<select id="task" name="task">
<option value="detect">Detect (Детекция)</option>
<option value="segment">Segment (Сегментация)</option>
<option value="classify">Classify (Классификация)</option>
<option value="pose">Pose (Позы)</option>
<option value="obb">OBB (Ориентированные боксы)</option>
</select>
</div>
<div class="field">
<label for="model-select">Выбор модели</label>
<select id="model-select">
<!-- Populated dynamically via JS based on task -->
</select>
</div>
<div class="field" id="model-custom-wrapper" style="display: none;">
<label for="model">Имя весов или путь к модели вручную</label>
<input type="text" id="model" name="model" placeholder="например, yolo11n.pt или /workspace/runs/.../best.pt">
</div>
<div class="field">
<label for="dataset-select">Выбор датасета</label>
<select id="dataset-select">
<option value="">Поиск локальных датасетов...</option>
</select>
</div>
<div class="field" id="dataset-custom-wrapper" style="display: none;">
<label for="dataset">Путь к датасету вручную</label>
<input type="text" id="dataset" name="dataset" placeholder="например, coco8.yaml или /workspace/datasets/custom">
</div>
<div class="form-section-title">Разделение данных (Train/Val)</div>
<div class="toggle-row">
<div class="toggle-label">
<h3>Автоматическое разделение</h3>
<p>Разделить датасет на train/val перед запуском</p>
</div>
<label class="switch-container">
<input type="checkbox" id="split-enabled">
<span class="switch-slider"></span>
</label>
</div>
<div class="row split-fields">
<div class="field">
<label for="split-ratio">Доля train (0.1…0.95)</label>
<input type="number" id="split-ratio" name="split-ratio" step="0.05" min="0.1" max="0.95" value="0.8">
</div>
<div class="field">
<label for="split-classes">Файл классов (classes.txt / YAML)</label>
<input type="text" id="split-classes" name="split-classes" placeholder="Автопоиск">
</div>
</div>
</div>
<!-- TRAINING TAB -->
<div class="tab-content" id="tab-training">
<div class="form-section-title">Гиперпараметры</div>
<div class="row">
<div class="field">
<label for="epochs">Количество эпох</label>
<input type="number" id="epochs" name="epochs" min="1" value="100">
</div>
<div class="field">
<label for="image-size">Размер изображения</label>
<input type="number" id="image-size" name="image-size" min="32" value="640">
</div>
<div class="field">
<label for="batch-size">Размер батча (Batch)</label>
<input type="number" id="batch-size" name="batch-size" min="-1" value="16">
</div>
</div>
<div class="row">
<div class="field">
<label for="device">Устройство (Device)</label>
<input type="text" id="device" name="device" placeholder="cpu, 0, 0,1">
</div>
<div class="field">
<label for="workers">Потоки загрузки (Workers)</label>
<input type="number" id="workers" name="workers" min="0" value="8">
</div>
<div class="field">
<label for="patience">Ожидание (Patience)</label>
<input type="number" id="patience" name="patience" min="0" value="100">
</div>
</div>
<div class="row">
<div class="field">
<label for="project">Каталог результатов</label>
<input type="text" id="project" name="project" value="runs/train">
</div>
<div class="field">
<label for="run-name">Имя запуска</label>
<input type="text" id="run-name" name="run-name" placeholder="experiment-01">
</div>
</div>
</div>
<!-- AUGMENTATION TAB -->
<div class="tab-content" id="tab-augmentation">
<div class="toggle-row">
<div class="toggle-label">
<h3>Пользовательские аугментации</h3>
<p>Передавать параметры аугментации в Ultralytics</p>
</div>
<label class="switch-container">
<input type="checkbox" id="augmentation-enabled" checked>
<span class="switch-slider"></span>
</label>
</div>
<div class="augmentation-fields">
<div class="form-section-title">Цветовые (HSV)</div>
<div class="row">
<div class="field">
<label for="hsv-h">HSV Hue (0…1)</label>
<input type="number" id="hsv-h" name="hsv-h" step="0.005" min="0" max="1" value="0.015">
</div>
<div class="field">
<label for="hsv-s">HSV Saturation (0…1)</label>
<input type="number" id="hsv-s" name="hsv-s" step="0.05" min="0" max="1" value="0.7">
</div>
<div class="field">
<label for="hsv-v">HSV Value/Brightness (0…1)</label>
<input type="number" id="hsv-v" name="hsv-v" step="0.05" min="0" max="1" value="0.4">
</div>
</div>
<div class="form-section-title">Геометрические</div>
<div class="row">
<div class="field">
<label for="degrees">Поворот (град.)</label>
<input type="number" id="degrees" name="degrees" step="0.5" min="0" value="0.0">
</div>
<div class="field">
<label for="translate">Смещение (0…1)</label>
<input type="number" id="translate" name="translate" step="0.05" min="0" max="1" value="0.1">
</div>
<div class="field">
<label for="scale">Масштаб (0…1)</label>
<input type="number" id="scale" name="scale" step="0.05" min="0" max="1" value="0.5">
</div>
</div>
<div class="row">
<div class="field">
<label for="shear">Сдвиг (град.)</label>
<input type="number" id="shear" name="shear" step="0.5" min="0" value="0.0">
</div>
<div class="field">
<label for="perspective">Перспектива (0…1)</label>
<input type="number" id="perspective" name="perspective" step="0.001" min="0" max="1" value="0.0">
</div>
<div class="field">
<label for="close-mosaic">Закрыть mosaic (эпох)</label>
<input type="number" id="close-mosaic" name="close-mosaic" min="0" value="10">
</div>
</div>
<div class="row">
<div class="field">
<label for="flipud">Flip вверх/вниз</label>
<input type="number" id="flipud" name="flipud" step="0.1" min="0" max="1" value="0.0">
</div>
<div class="field">
<label for="fliplr">Flip влево/вправо</label>
<input type="number" id="fliplr" name="fliplr" step="0.1" min="0" max="1" value="0.5">
</div>
<div class="field">
<label for="bgr">RGB ↔ BGR (0…1)</label>
<input type="number" id="bgr" name="bgr" step="0.1" min="0" max="1" value="0.0">
</div>
</div>
<div class="form-section-title">Составные</div>
<div class="row">
<div class="field">
<label for="mosaic">Mosaic (0…1)</label>
<input type="number" id="mosaic" name="mosaic" step="0.1" min="0" max="1" value="1.0">
</div>
<div class="field">
<label for="mixup">MixUp (0…1)</label>
<input type="number" id="mixup" name="mixup" step="0.1" min="0" max="1" value="0.0">
</div>
<div class="field">
<label for="cutmix">CutMix (0…1)</label>
<input type="number" id="cutmix" name="cutmix" step="0.1" min="0" max="1" value="0.0">
</div>
</div>
<div class="row">
<div class="field">
<label for="copy-paste">Copy-paste (0…1)</label>
<input type="number" id="copy-paste" name="copy-paste" step="0.1" min="0" max="1" value="0.0">
</div>
<div class="field">
<label for="erasing">Erasing (0…1)</label>
<input type="number" id="erasing" name="erasing" step="0.05" min="0" max="1" value="0.4">
</div>
<div class="field">
<label for="copy-paste-mode">Режим Copy-paste</label>
<select id="copy-paste-mode" name="copy-paste-mode">
<option value="flip">Flip</option>
<option value="mixup">Mixup</option>
</select>
</div>
</div>
<div class="field">
<label for="auto-augment">AutoAugment политика (classify)</label>
<select id="auto-augment" name="auto-augment">
<option value="none">Отключено</option>
<option value="randaugment">RandAugment</option>
<option value="autoaugment">AutoAugment</option>
<option value="augmix">AugMix</option>
</select>
</div>
</div>
</div>
<!-- MLFLOW TAB -->
<div class="tab-content" id="tab-mlflow">
<div class="toggle-row">
<div class="toggle-label">
<h3>Интеграция MLflow</h3>
<p>Записывать параметры, метрики и checkpoints</p>
</div>
<label class="switch-container">
<input type="checkbox" id="mlflow-enabled" checked>
<span class="switch-slider"></span>
</label>
</div>
<div class="mlflow-fields">
<div class="field">
<label for="tracking-uri">Tracking URI</label>
<input type="text" id="tracking-uri" name="tracking-uri" value="sqlite:///mlflow.db" placeholder="http://127.0.0.1:5000">
</div>
<div class="row">
<div class="field">
<label for="experiment-name">Название эксперимента</label>
<input type="text" id="experiment-name" name="experiment-name" value="yolo-webui">
</div>
<div class="field">
<label for="mlflow-run-name">Имя запуска (Run Name)</label>
<input type="text" id="mlflow-run-name" name="mlflow-run-name" placeholder="Автоматически">
</div>
</div>
</div>
</div>
</form>
</section>
<!-- Monitoring Card -->
<section class="pane" id="run-pane">
<!-- Status Card -->
<div id="status-card" class="status-idle">
<div class="status-header">
<div class="status-indicator">
<span class="status-dot"></span>
<h2 id="status-title">ГОТОВО К ЗАПУСКУ</h2>
</div>
<div class="status-timer" id="status-timer">00:00:00</div>
</div>
<p id="status-text">Проверьте параметры и начните обучение.</p>
<div class="progress-container">
<div class="progress-bar-wrapper">
<div class="progress-bar-fill" id="progress-bar-fill" style="width: 0%"></div>
</div>
<div class="progress-meta">
<span id="progress-text">Эпохи: 0 / 100</span>
<span id="progress-eta">ETA: --:--:--</span>
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="action-buttons">
<button type="button" id="start-btn" class="btn btn-primary">
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M8 5v14l11-7z"></path>
</svg>
Начать обучение
</button>
<button type="button" id="stop-btn" class="btn btn-danger" disabled>
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"></path>
</svg>
Остановить
</button>
</div>
<!-- Logs Box -->
<div class="log-card">
<div class="log-header">
<h3>Журнал</h3>
<div class="log-actions">
<label class="checkbox-inline">
<input type="checkbox" id="autoscroll" checked>
Автопрокрутка
</label>
<button type="button" id="clear-log-btn" class="btn-text">Очистить</button>
</div>
</div>
<div class="log-body" id="log-container">
<div class="log-line log-level-info">Интерфейс готов. Ожидание запуска...</div>
</div>
</div>
</section>
</div> <!-- End train-view -->
<div id="export-view" class="workspace-view">
<!-- Export Configuration Card -->
<section class="pane" id="export-config-pane">
<div class="tabs">
<button type="button" class="export-tab-btn active" style="flex: 1; background: var(--accent-gradient); border: none; border-radius: 6px; color: #fff; font-family: var(--font-sans); font-size: 0.9rem; font-weight: 600; padding: 0.6rem; cursor: default; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);">Настройки экспорта</button>
</div>
<form id="export-form" class="form-container">
<div style="display: block;">
<div class="form-section-title">Параметры модели</div>
<div class="field">
<label for="export-model-select">Модель для экспорта</label>
<select id="export-model-select">
<option value="">Поиск моделей...</option>
</select>
</div>
<div class="field" id="export-model-custom-wrapper" style="display: none;">
<label for="export-model">Имя весов или путь к модели вручную</label>
<input type="text" id="export-model" name="export-model" placeholder="например, /workspace/runs/.../best.pt">
</div>
<div class="field">
<label for="export-format">Формат экспорта</label>
<select id="export-format" name="export-format">
<option value="onnx">ONNX (.onnx)</option>
<option value="engine">TensorRT (.engine)</option>
<option value="openvino">OpenVINO (_openvino_model/)</option>
<option value="torchscript">TorchScript (.torchscript)</option>
<option value="coreml">CoreML (.mlpackage)</option>
<option value="tflite">TFLite (.tflite)</option>
<option value="saved_model">TensorFlow SavedModel (_saved_model/)</option>
<option value="pb">TensorFlow GraphDef (.pb)</option>
</select>
</div>
<div class="form-section-title">Опции</div>
<div class="row">
<div class="field">
<label for="export-imgsz">Размер изображения (imgsz)</label>
<input type="number" id="export-imgsz" name="export-imgsz" value="640" min="32" max="8192" step="1" required>
</div>
<div class="field">
<label for="export-batch" title="Максимальный размер батча. Важен при Dynamic=True для TensorRT.">Макс. батч (batch)</label>
<input type="number" id="export-batch" name="export-batch" value="1" min="1" max="1024" step="1" required>
</div>
<div class="field">
<label for="export-workspace" title="Размер памяти для сборки TensorRT (ГБ).">Workspace (ГБ)</label>
<input type="number" id="export-workspace" name="export-workspace" value="4" min="1" max="64" step="0.5" required>
</div>
</div>
<div class="row">
<div class="toggle-row" style="padding: 10px 0;">
<div class="toggle-label">
<h3>FP16 (Half)</h3>
<p>Использовать полуточность</p>
</div>
<label class="switch-container">
<input type="checkbox" id="export-half">
<span class="switch-slider"></span>
</label>
</div>
<div class="toggle-row" style="padding: 10px 0;">
<div class="toggle-label">
<h3>INT8</h3>
<p>Квантование до INT8</p>
</div>
<label class="switch-container">
<input type="checkbox" id="export-int8">
<span class="switch-slider"></span>
</label>
</div>
<div class="toggle-row" style="padding: 10px 0;">
<div class="toggle-label">
<h3>Dynamic</h3>
<p>Динамические оси</p>
</div>
<label class="switch-container">
<input type="checkbox" id="export-dynamic">
<span class="switch-slider"></span>
</label>
</div>
<div class="toggle-row" style="padding: 10px 0;">
<div class="toggle-label" title="Только для ONNX. Оптимизирует и упрощает граф модели.">
<h3>Simplify</h3>
<p>Упростить граф (ONNX)</p>
</div>
<label class="switch-container">
<input type="checkbox" id="export-simplify">
<span class="switch-slider"></span>
</label>
</div>
</div>
</div>
</form>
</section>
<!-- Export Monitoring Card -->
<section class="pane" id="export-run-pane">
<div id="export-status-card" class="status-idle">
<div class="status-header">
<div class="status-indicator">
<span class="status-dot"></span>
<h2 id="export-status-title">ГОТОВО К ЭКСПОРТУ</h2>
</div>
</div>
<p id="export-status-text">Выберите модель и формат для начала.</p>
</div>
<!-- Action Buttons -->
<div class="action-buttons">
<button type="button" id="export-start-btn" class="btn btn-primary">
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M8 5v14l11-7z"></path>
</svg>
Начать экспорт
</button>
<button type="button" id="export-stop-btn" class="btn btn-danger" disabled>
<svg viewBox="0 0 24 24" fill="currentColor" class="btn-icon">
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"></path>
</svg>
Остановить
</button>
</div>
<!-- Logs Box -->
<div class="log-card" style="flex: 1;">
<div class="log-header">
<h3>Журнал экспорта</h3>
<div class="log-actions">
<label class="checkbox-inline">
<input type="checkbox" id="export-autoscroll" checked>
Автопрокрутка
</label>
<button type="button" id="export-clear-log-btn" class="btn-text">Очистить</button>
</div>
</div>
<div class="log-body" id="export-log-container">
<div class="log-line log-level-info">Ожидание запуска экспорта...</div>
</div>
</div>
</section>
</div> <!-- End export-view -->
</main>
<script src="/static/app.js?v=6"></script>
</body>
</html>