document.addEventListener("DOMContentLoaded", () => { const imageInput = document.getElementById("imageInput"); const previewScroll = document.getElementById("preview-scroll"); const resultSection = document.getElementById("result-section"); const selectedImage = document.getElementById("selected-image"); const genreResults = document.getElementById("genre-results"); const styleResults = document.getElementById("style-results"); const loader = document.getElementById("loader"); const backgroundBlur = document.getElementById("background-blur"); let previews = []; imageInput.addEventListener("change", () => { previewScroll.innerHTML = ""; previews = []; Array.from(imageInput.files).forEach((file, index) => { const reader = new FileReader(); reader.onload = e => { const box = document.createElement("div"); box.className = "image-box"; const img = document.createElement("img"); img.src = e.target.result; img.className = "preview-image"; img.onclick = () => { previews.forEach(p => p.img.classList.remove("selected")); img.classList.add("selected"); showResult(img.src); analyzeImage(file); backgroundBlur.style.backgroundImage = `url(${img.src})`; }; const label = document.createElement("small"); label.className = "filename"; label.textContent = file.name; box.appendChild(img); box.appendChild(label); previewScroll.appendChild(box); previews.push({ img, file }); }; reader.readAsDataURL(file); }); }); function showResult(imgSrc) { resultSection.style.display = "block"; selectedImage.src = imgSrc; resetCamState(); } function analyzeImage(file) { const genreColors = ['#00ff88', '#00c4ff', '#ffaa00', '#ff5555', '#a0f', '#f0f']; const styleColors = ['#00c4ff', '#00ff88', '#ffcc00', '#f06', '#0ff', '#f99']; const paletteDiv = document.getElementById("color-palette"); const formData = new FormData(); formData.append("file", file); paletteDiv.innerHTML = ""; loader.style.display = "block"; fetch("/predict_all_combined", { method: "POST", body: formData }) .then(async res => { if (!res.ok) { const text = await res.text(); throw new Error(`Сервер вернул ${res.status}: ${text}`); } return res.json(); }) .then(data => { genreResults.innerHTML = ""; styleResults.innerHTML = ""; // Примеры миниатюр window.styleExampleMap = {}; data.style_top3.forEach(s => { window.styleExampleMap[s.label] = s.examples; }); window.genreExampleMap = {}; data.genre_top3.forEach(g => { window.genreExampleMap[g.label] = g.examples; }); // Диаграммы renderDonutChart("genreChart", data.genre_top3, genreColors, "Жанры"); renderDonutChart("styleChart", data.style_top3, styleColors, "Стили"); // Топ-10 жанров data.genre_top3.slice(0, 10).forEach(g => { genreResults.innerHTML += `
Размер: ${data.metadata.width} × ${data.metadata.height}
Средняя насыщенность: ${data.metadata.avg_saturation}
Средняя яркость: ${data.metadata.avg_brightness}
Контраст: ${data.metadata.contrast}
`; metaBlock.appendChild(baseInfo); } if (data.metadata && data.metadata.color_statistics) { const statBlock = document.createElement("div"); statBlock.style.marginTop = "20px"; statBlock.style.background = "#111"; statBlock.style.border = "1px solid #333"; statBlock.style.padding = "12px"; statBlock.style.borderRadius = "6px"; statBlock.style.color = "#ccc"; statBlock.style.fontSize = "13px"; const rgb = data.metadata.color_statistics.rgb; const hsv = data.metadata.color_statistics.hsv; statBlock.innerHTML = `Среднее: R=${rgb.mean.R.toFixed(4)}, G=${rgb.mean.G.toFixed(4)}, B=${rgb.mean.B.toFixed(4)}
Дисперсия: R=${rgb.variance.R.toFixed(4)}, G=${rgb.variance.G.toFixed(4)}, B=${rgb.variance.B.toFixed(4)}
Корреляции: R-G=${rgb.correlation.RG.toFixed(4)}, R-B=${rgb.correlation.RB.toFixed(4)}, G-B=${rgb.correlation.GB.toFixed(4)}
Среднее: H=${hsv.mean.H.toFixed(4)}, S=${hsv.mean.S.toFixed(4)}, V=${hsv.mean.V.toFixed(4)}
Дисперсия: H=${hsv.variance.H.toFixed(4)}, S=${hsv.variance.S.toFixed(4)}, V=${hsv.variance.V.toFixed(4)}
Корреляции: H-S=${hsv.correlation.HS.toFixed(4)}, H-V=${hsv.correlation.HV.toFixed(4)}, S-V=${hsv.correlation.SV.toFixed(4)}
`; const metaBlock = document.getElementById("image-meta-info"); metaBlock.appendChild(statBlock); } if (data.metadata && data.metadata.brightness_stats) { const stats = data.metadata.brightness_stats; const statEl = document.getElementById("brightness-statistics"); statEl.innerHTML = `Среднее значение (Mean): ${stats.mean.toFixed(4)}
Медиана (Median): ${stats.median.toFixed(4)}
Минимум: ${stats.min.toFixed(4)}
Максимум: ${stats.max.toFixed(4)}
Стандартное отклонение: ${stats.std.toFixed(4)}
Мода (наиболее частое значение): ${stats.mode.toFixed(4)}
Энергия (сумма квадратов): ${stats.energy.toFixed(4)}
Энтропия (сложность распределения): ${stats.entropy.toFixed(4)}
`; } if (data.metadata && data.metadata.texture_features) { const t = data.metadata.texture_features; const texBlock = document.createElement("div"); texBlock.style.marginTop = "20px"; texBlock.style.background = "#111"; texBlock.style.border = "1px solid #333"; texBlock.style.padding = "12px"; texBlock.style.borderRadius = "6px"; texBlock.style.color = "#ccc"; texBlock.style.fontSize = "13px"; texBlock.innerHTML = `Контраст: ${t.contrast.toFixed(4)}
Гомогенность: ${t.homogeneity.toFixed(4)}
Энергия: ${t.energy.toFixed(4)}
Энтропия: ${t.entropy.toFixed(4)}
Корреляция: ${t.correlation.toFixed(4)}
`; document.getElementById("image-meta-info").appendChild(texBlock); } graphChart.setOption({ tooltip: { show: false }, legend: [ { data: ['Изображение', 'Жанр', 'Стиль'], textStyle: { color: '#aaa' } } ], series: [{ type: 'graph', layout: 'force', roam: true, draggable: true, label: { show: true, formatter: '{b}', fontSize: 11, color: '#eee' }, edgeSymbol: ['circle', 'arrow'], edgeSymbolSize: [4, 6], force: { repulsion: 250, edgeLength: [80, 160] }, categories: [ { name: 'Изображение', itemStyle: { color: '#ffaa00' } }, { name: 'Жанр', itemStyle: { color: '#00ff88' } }, { name: 'Стиль', itemStyle: { color: '#00c4ff' } } ], data: fullNodes, links: fullLinks, lineStyle: { color: 'source', curveness: 0.2, opacity: 0.6 } }] }); graphChart.on('mouseover', params => { if (params.dataType === 'node' && params.data.name !== 'Изображение') { const { name, category, value } = params.data; const rect = document.getElementById('graph-container').getBoundingClientRect(); let description = ''; if (category === 1) { description = genreDescriptions[name] || 'Жанр: описание отсутствует.'; } else if (category === 2) { description = styleDescriptions[name] || 'Стиль: описание отсутствует.'; } tooltipEl.innerHTML = `