{"id":651,"date":"2026-02-21T03:49:25","date_gmt":"2026-02-20T19:49:25","guid":{"rendered":"http:\/\/www.artinfinity.cn\/?page_id=651"},"modified":"2026-02-23T01:03:37","modified_gmt":"2026-02-22T17:03:37","slug":"%e9%87%8f%e5%8c%96%e7%a0%94%e7%a9%b6%e5%b7%a5%e5%85%b7","status":"publish","type":"page","link":"http:\/\/www.artinfinity.cn\/?page_id=651","title":{"rendered":"\u91cf\u5316\u7814\u7a76\u5de5\u5177"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>\u753b\u9762\u89c6\u89c9\u7e41\u5bc6\u5ea6\u91cf\u5316\u5206\u6790\u5de5\u5177 V4<\/title>\n    <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js\"><\/script>\n    <style>\n        :root {\n            --bg-primary: #0f172a;\n            --bg-secondary: #1e293b;\n            --bg-card: #334155;\n            --text-primary: #f1f5f9;\n            --text-secondary: #94a3b8;\n            --accent-blue: #3b82f6;\n            --accent-green: #10b981;\n            --accent-yellow: #f59e0b;\n            --accent-red: #ef4444;\n            --border-color: #475569;\n        }\n\n        * { margin: 0; padding: 0; box-sizing: border-box; }\n\n        body {\n            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n            background: var(--bg-primary);\n            color: var(--text-primary);\n            min-height: 100vh;\n        }\n\n        .app-container {\n            display: grid;\n            grid-template-columns: 1fr 420px;\n            min-height: 100vh;\n        }\n\n        \/* \u5de6\u4fa7\u9762\u677f *\/\n        .left-panel {\n            padding: 20px;\n            display: flex;\n            flex-direction: column;\n            gap: 16px;\n            overflow-y: auto;\n            max-height: 100vh;\n        }\n\n        .header-title {\n            font-size: 20px;\n            font-weight: 600;\n            color: var(--accent-blue);\n            margin-bottom: 4px;\n        }\n\n        .header-desc {\n            font-size: 13px;\n            color: var(--text-secondary);\n        }\n\n        \/* \u4e0a\u4f20\u533a\u57df *\/\n        .upload-zone {\n            border: 2px dashed var(--border-color);\n            border-radius: 12px;\n            padding: 32px;\n            text-align: center;\n            cursor: pointer;\n            transition: all 0.2s;\n            background: var(--bg-secondary);\n        }\n\n        .upload-zone:hover {\n            border-color: var(--accent-blue);\n            background: rgba(59, 130, 246, 0.1);\n        }\n\n        .upload-zone input { display: none; }\n\n        .upload-icon {\n            width: 48px;\n            height: 48px;\n            fill: var(--text-secondary);\n            margin-bottom: 12px;\n        }\n\n        \/* \u9884\u89c8\u533a\u57df *\/\n        .preview-section {\n            display: none;\n            flex-direction: column;\n            gap: 12px;\n        }\n\n        .preview-section.active { display: flex; }\n\n        .preview-header {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n\n        .preview-title {\n            font-size: 14px;\n            color: var(--text-secondary);\n        }\n\n        .view-tabs {\n            display: flex;\n            gap: 6px;\n        }\n\n        .view-tab {\n            padding: 5px 10px;\n            border-radius: 6px;\n            font-size: 11px;\n            background: var(--bg-card);\n            color: var(--text-secondary);\n            border: none;\n            cursor: pointer;\n            transition: all 0.2s;\n        }\n\n        .view-tab.active {\n            background: var(--accent-blue);\n            color: white;\n        }\n\n        \/* \u753b\u5e03\u5bb9\u5668 - \u56fa\u5b9a\u56fe\u7247\u4f4d\u7f6e *\/\n        .canvas-wrapper {\n            position: relative;\n            width: 100%;\n            height: 450px;\n            background: var(--bg-secondary);\n            border-radius: 12px;\n            overflow: hidden;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n        }\n\n        .canvas-wrapper img {\n            max-width: 100%;\n            max-height: 100%;\n            object-fit: contain;\n            user-select: none;\n            -webkit-user-drag: none;\n        }\n\n        \/* \u9009\u6846\u753b\u5e03 - \u8986\u76d6\u5728\u56fe\u7247\u4e0a *\/\n        #selectionCanvas {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            cursor: crosshair;\n            z-index: 10;\n        }\n\n        \/* \u9009\u6846\u6837\u5f0f *\/\n        .selection-box {\n            position: absolute;\n            border: 2px dashed var(--accent-red);\n            background: rgba(239, 68, 68, 0.1);\n            pointer-events: none;\n            display: none;\n        }\n\n        .selection-box.active {\n            display: block;\n        }\n\n        \/* \u64cd\u4f5c\u63d0\u793a *\/\n        .selection-tip {\n            font-size: 12px;\n            color: var(--accent-yellow);\n            text-align: center;\n            padding: 8px;\n            background: rgba(245, 158, 11, 0.1);\n            border-radius: 6px;\n            margin-bottom: 8px;\n        }\n\n        \/* \u6309\u94ae\u7ec4 *\/\n        .button-group {\n            display: flex;\n            gap: 10px;\n            flex-wrap: wrap;\n        }\n\n        .btn {\n            flex: 1;\n            min-width: 90px;\n            padding: 10px 14px;\n            border: none;\n            border-radius: 8px;\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 5px;\n            transition: all 0.2s;\n        }\n\n        .btn svg { width: 14px; height: 14px; }\n\n        .btn-primary {\n            background: var(--accent-blue);\n            color: white;\n        }\n\n        .btn-primary:hover { background: #2563eb; }\n\n        .btn-secondary {\n            background: var(--bg-card);\n            color: var(--text-primary);\n        }\n\n        .btn-secondary:hover { background: #475569; }\n\n        .btn-warning {\n            background: var(--accent-yellow);\n            color: #000;\n        }\n\n        .btn-warning:hover { background: #d97706; }\n\n        .btn:disabled {\n            opacity: 0.5;\n            cursor: not-allowed;\n        }\n\n        \/* \u53f3\u4fa7\u9762\u677f *\/\n        .right-panel {\n            background: var(--bg-secondary);\n            border-left: 1px solid var(--border-color);\n            padding: 20px;\n            overflow-y: auto;\n            max-height: 100vh;\n        }\n\n        .dashboard-section {\n            margin-bottom: 20px;\n        }\n\n        .section-title {\n            font-size: 13px;\n            font-weight: 600;\n            color: var(--text-secondary);\n            margin-bottom: 12px;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n\n        \/* \u7efc\u5408\u8bc4\u5206\u663e\u793a - \u8fdb\u5ea6\u6761\u6837\u5f0f *\/\n        .score-display {\n            text-align: center;\n            padding: 10px 0;\n        }\n\n        .score-number {\n            font-size: 48px;\n            font-weight: 700;\n            color: var(--text-primary);\n            line-height: 1.2;\n            margin-bottom: 12px;\n        }\n\n        .score-bar-container {\n            width: 100%;\n            height: 16px;\n            background: var(--bg-card);\n            border-radius: 8px;\n            overflow: hidden;\n            position: relative;\n            margin-bottom: 6px;\n        }\n\n        .score-bar {\n            height: 100%;\n            width: 0%;\n            border-radius: 8px;\n            transition: width 0.5s ease, background 0.5s ease;\n        }\n\n        .score-bar.ultra-low { background: linear-gradient(90deg, #6366f1, #8b5cf6); }\n        .score-bar.low { background: linear-gradient(90deg, #10b981, #34d399); }\n        .score-bar.high { background: linear-gradient(90deg, #f59e0b, #fbbf24); }\n        .score-bar.ultra-high { background: linear-gradient(90deg, #ef4444, #f87171); }\n\n        .score-scale {\n            display: flex;\n            justify-content: space-between;\n            font-size: 10px;\n            color: var(--text-secondary);\n            padding: 0 2px;\n        }\n\n        .level-badge.ultra-low { background: rgba(99, 102, 241, 0.2); color: #818cf8; }\n        .level-badge.low { background: rgba(16, 185, 129, 0.2); color: var(--accent-green); }\n        .level-badge.high { background: rgba(245, 158, 11, 0.2); color: var(--accent-yellow); }\n        .level-badge.ultra-high { background: rgba(239, 68, 68, 0.2); color: var(--accent-red); }\n\n        .level-badge {\n            display: inline-block;\n            padding: 4px 12px;\n            border-radius: 12px;\n            font-size: 12px;\n            font-weight: 500;\n        }\n\n        .level-low { background: rgba(16, 185, 129, 0.2); color: var(--accent-green); }\n        .level-medium { background: rgba(245, 158, 11, 0.2); color: var(--accent-yellow); }\n        .level-high { background: rgba(239, 68, 68, 0.2); color: var(--accent-red); }\n\n        \/* \u8bc4\u5206\u8bf4\u660e *\/\n        .score-explanation {\n            background: var(--bg-card);\n            border-radius: 8px;\n            padding: 12px;\n            margin-top: 16px;\n            font-size: 11px;\n            color: var(--text-secondary);\n            line-height: 1.5;\n        }\n\n        .score-explanation-toggle {\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n            cursor: pointer;\n            color: var(--accent-blue);\n            font-size: 12px;\n            margin-bottom: 8px;\n        }\n\n        .score-explanation-toggle svg {\n            width: 14px;\n            height: 14px;\n            transition: transform 0.2s;\n        }\n\n        .score-explanation-toggle.open svg {\n            transform: rotate(180deg);\n        }\n\n        .score-formula {\n            display: none;\n            background: var(--bg-primary);\n            padding: 10px;\n            border-radius: 6px;\n            font-family: monospace;\n            font-size: 10px;\n            margin-top: 8px;\n        }\n\n        .score-formula.show { display: block; }\n\n        .formula-item {\n            display: flex;\n            justify-content: space-between;\n            padding: 3px 0;\n        }\n\n        \/* \u56fe\u8868\u5bb9\u5668 *\/\n        .radar-container {\n            width: 100%;\n            height: 180px;\n        }\n\n        .histogram-container {\n            width: 100%;\n            height: 100px;\n        }\n\n        \/* \u6307\u6807\u7f51\u683c *\/\n        .metrics-grid {\n            display: grid;\n            grid-template-columns: 1fr 1fr;\n            gap: 10px;\n        }\n\n        .metric-card {\n            background: var(--bg-card);\n            border-radius: 8px;\n            padding: 12px;\n        }\n\n        .metric-label {\n            font-size: 11px;\n            color: var(--text-secondary);\n            margin-bottom: 4px;\n            display: flex;\n            align-items: center;\n            gap: 4px;\n        }\n\n        .metric-help {\n            display: inline-flex;\n            align-items: center;\n            justify-content: center;\n            width: 14px;\n            height: 14px;\n            border-radius: 50%;\n            background: var(--border-color);\n            color: var(--text-secondary);\n            font-size: 10px;\n            cursor: help;\n            position: relative;\n            margin-left: 4px;\n        }\n\n        .metric-help:hover::after {\n            content: attr(data-tooltip);\n            position: absolute;\n            bottom: 100%;\n            left: 50%;\n            transform: translateX(-50%);\n            background: rgba(30, 41, 59, 0.98);\n            color: var(--text-primary);\n            padding: 12px 14px;\n            border-radius: 8px;\n            font-size: 11px;\n            z-index: 100;\n            box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n            white-space: normal;\n            max-width: 280px;\n            min-width: 200px;\n            line-height: 1.5;\n            border: 1px solid var(--border-color);\n            margin-bottom: 8px;\n            text-align: left;\n        }\n\n        \/* \u9632\u6b62tooltip\u8d85\u51fa\u5c4f\u5e55 *\/\n        .metric-help:hover::before {\n            content: '';\n            position: absolute;\n            bottom: 100%;\n            left: 50%;\n            transform: translateX(-50%);\n            border: 6px solid transparent;\n            border-top-color: rgba(30, 41, 59, 0.98);\n            margin-bottom: -4px;\n        }\n\n        .metric-value {\n            font-size: 18px;\n            font-weight: 600;\n            color: var(--text-primary);\n        }\n\n        \/* \u6570\u636e\u8868\u683c *\/\n        .table-section {\n            margin-top: 20px;\n            border-top: 1px solid var(--border-color);\n            padding-top: 16px;\n        }\n\n        .table-scroll {\n            max-height: 200px;\n            overflow-y: auto;\n        }\n\n        .data-table {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 11px;\n        }\n\n        .data-table th {\n            text-align: left;\n            padding: 8px 6px;\n            background: var(--bg-card);\n            color: var(--text-secondary);\n            font-weight: 500;\n            position: sticky;\n            top: 0;\n        }\n\n        .data-table td {\n            padding: 6px;\n            border-bottom: 1px solid var(--border-color);\n            vertical-align: middle;\n        }\n\n        .data-table .thumb {\n            width: 48px;\n            height: 36px;\n            object-fit: cover;\n            border-radius: 4px;\n            cursor: pointer;\n        }\n\n        .empty-tip {\n            text-align: center;\n            padding: 24px;\n            color: var(--text-secondary);\n            font-size: 12px;\n        }\n\n        \/* \u5bfc\u51fa\u6309\u94ae\u7ec4 *\/\n        .export-group {\n            display: flex;\n            gap: 8px;\n            margin-top: 12px;\n        }\n\n        .export-group .btn {\n            min-width: auto;\n            flex: 1;\n            padding: 8px 10px;\n            font-size: 11px;\n        }\n\n        \/* \u52a0\u8f7d\u52a8\u753b *\/\n        .loading-overlay {\n            position: fixed;\n            top: 0; left: 0; right: 0; bottom: 0;\n            background: rgba(15, 23, 42, 0.9);\n            display: none;\n            align-items: center;\n            justify-content: center;\n            z-index: 1000;\n        }\n\n        .loading-overlay.active { display: flex; }\n\n        .spinner {\n            width: 40px;\n            height: 40px;\n            border: 3px solid var(--border-color);\n            border-top-color: var(--accent-blue);\n            border-radius: 50%;\n            animation: spin 0.8s linear infinite;\n        }\n\n        @keyframes spin { to { transform: rotate(360deg); } }\n\n        \/* \u9690\u79c1\u63d0\u793a *\/\n        .privacy-tip {\n            background: rgba(16, 185, 129, 0.1);\n            border: 1px solid var(--accent-green);\n            border-radius: 8px;\n            padding: 10px;\n            margin-top: 12px;\n            font-size: 11px;\n            color: var(--accent-green);\n            display: flex;\n            align-items: center;\n            gap: 6px;\n        }\n\n        .privacy-tip svg { width: 14px; height: 14px; fill: var(--accent-green); }\n\n        \/* \u79fb\u52a8\u7aef\u9002\u914d *\/\n        @media (max-width: 900px) {\n            .app-container {\n                grid-template-columns: 1fr;\n            }\n\n            .right-panel {\n                border-left: none;\n                border-top: 1px solid var(--border-color);\n            }\n\n            .canvas-wrapper {\n                height: 300px;\n            }\n\n            .metrics-grid {\n                grid-template-columns: 1fr;\n            }\n        }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"loading-overlay\" id=\"loadingOverlay\">\n        <div class=\"spinner\"><\/div>\n    <\/div>\n\n    <div class=\"app-container\">\n        <!-- \u5de6\u4fa7\u9762\u677f -->\n        <div class=\"left-panel\">\n            <div>\n                <div class=\"header-title\">\u753b\u9762\u89c6\u89c9\u7e41\u5bc6\u5ea6\u7814\u7a76\u91cf\u5316\u5206\u6790\u5de5\u5177 \u7248\u672cV4 By-ZhaoYubo 2026<\/div>\n            <\/div>\n\n            <!-- \u4e0a\u4f20\u533a\u57df -->\n            <div class=\"upload-zone\" id=\"uploadZone\">\n                <input type=\"file\" id=\"fileInput\" accept=\"image\/jpeg,image\/png,image\/webp\">\n                <svg class=\"upload-icon\" viewBox=\"0 0 24 24\">\n                    <path d=\"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z\"\/>\n                <\/svg>\n                <div style=\"color: var(--text-primary); margin-bottom: 4px;\">\u70b9\u51fb\u6216\u62d6\u62fd\u4e0a\u4f20\u56fe\u7247<\/div>\n                <div style=\"color: var(--text-secondary); font-size: 12px;\">\u652f\u6301 JPG, PNG, WebP \u683c\u5f0f<\/div>\n            <\/div>\n\n            <!-- \u9884\u89c8\u533a\u57df -->\n            <div class=\"preview-section\" id=\"previewSection\">\n                <div class=\"selection-tip\" id=\"selectionTip\">\n                    \ud83d\uddb1\ufe0f \u5728\u56fe\u7247\u4e0a\u6309\u4f4f\u9f20\u6807\u5de6\u952e\u62d6\u52a8\uff0c\u7ed8\u5236\u9009\u6846\u6765\u9009\u62e9\u5206\u6790\u533a\u57df\n                <\/div>\n\n                <div class=\"preview-header\">\n                    <span class=\"preview-title\">\u9884\u89c8\u4e0e\u5206\u6790\u533a\u57df<\/span>\n                    <div class=\"view-tabs\">\n                        <button class=\"view-tab active\" data-view=\"original\">\u539f\u56fe<\/button>\n                        <button class=\"view-tab\" data-view=\"edge\">\u8fb9\u7f18<\/button>\n                        <button class=\"view-tab\" data-view=\"gray\">\u7070\u5ea6<\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"canvas-wrapper\" id=\"canvasWrapper\">\n                    <img decoding=\"async\" id=\"displayImage\" src=\"\" alt=\"\">\n                    <canvas id=\"selectionCanvas\"><\/canvas>\n                <\/div>\n\n                <div class=\"button-group\">\n                    <button class=\"btn btn-warning\" id=\"resetSelectionBtn\" disabled>\n                        <svg viewBox=\"0 0 24 24\"><path d=\"M17.65 6.35A7.958 7.958 0 0012 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z\"\/><\/svg>\n                        \u91cd\u7f6e\u9009\u533a\n                    <\/button>\n                    <button class=\"btn btn-primary\" id=\"analyzeBtn\" disabled>\n                        <svg viewBox=\"0 0 24 24\"><path d=\"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z\"\/><\/svg>\n                        \u5f00\u59cb\u5206\u6790\n                    <\/button>\n                    <button class=\"btn btn-secondary\" id=\"resetBtn\" disabled>\n                        <svg viewBox=\"0 0 24 24\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\/><\/svg>\n                        \u91cd\u7f6e\n                    <\/button>\n                <\/div>\n            <\/div>\n\n            <!-- \u9690\u79c1\u63d0\u793a -->\n            <div class=\"privacy-tip\">\n                <svg viewBox=\"0 0 24 24\"><path d=\"M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z\"\/><\/svg>\n                \u6240\u6709\u56fe\u50cf\u5206\u6790\u5747\u5728\u6d4f\u89c8\u5668\u672c\u5730\u5b8c\u6210\uff0c\u4e0d\u4f1a\u4e0a\u4f20\u81f3\u670d\u52a1\u5668\n            <\/div>\n        <\/div>\n\n        <!-- \u53f3\u4fa7\u9762\u677f -->\n        <div class=\"right-panel\">\n            <!-- \u7efc\u5408\u8bc4\u5206 -->\n            <div class=\"dashboard-section\">\n                <div class=\"section-title\">\u7efc\u5408\u8bc4\u5206<\/div>\n                <!-- \u7efc\u5408\u8bc4\u5206\u663e\u793a - \u4f7f\u7528\u8fdb\u5ea6\u6761\u6837\u5f0f -->\n                <div class=\"score-display\">\n                    <div class=\"score-number\" id=\"totalScore\">0<\/div>\n                    <div class=\"score-bar-container\">\n                        <div class=\"score-bar\" id=\"scoreBar\"><\/div>\n                    <\/div>\n                    <div class=\"score-scale\">\n                        <span>0<\/span>\n                        <span>25<\/span>\n                        <span>50<\/span>\n                        <span>75<\/span>\n                        <span>100<\/span>\n                    <\/div>\n                    <div style=\"text-align: center; margin-top: 8px;\">\n                        <span class=\"level-badge\" id=\"scoreLevel\">\u7b49\u5f85\u5206\u6790<\/span>\n                    <\/div>\n                <\/div>\n                \n                <!-- \u8bc4\u5206\u8ba1\u7b97\u8bf4\u660e -->\n                <div class=\"score-explanation\">\n                    <div class=\"score-explanation-toggle\" id=\"scoreToggle\">\n                        <span>\ud83d\udcca \u67e5\u770b\u8bc4\u5206\u8ba1\u7b97\u65b9\u6cd5\u4e0e\u539f\u7406<\/span>\n                        <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M7 10l5 5 5-5z\"\/><\/svg>\n                    <\/div>\n                    <div class=\"score-formula\" id=\"scoreFormula\">\n                        <div style=\"margin-bottom: 10px; font-weight: 600; font-size: 11px;\">\u7efc\u5408\u8bc4\u5206\u8ba1\u7b97\u516c\u5f0f<\/div>\n                        <div style=\"background: var(--bg-primary); padding: 8px; border-radius: 4px; margin-bottom: 10px; font-family: monospace; font-size: 10px;\">\n                            \u8bc4\u5206 = \u8fb9\u7f18\u5bc6\u5ea6x0.25 + (\u9999\u519c\u71b5\u00f78)x100x0.10 + \u7eb9\u7406\u5206\u6570x100x0.25 + \u989c\u8272\u591a\u6837\u6027x100x0.10 + \u5bf9\u6bd4\u5ea6x100x0.15 + (\u65b9\u5dee\u00f76500)x100x0.15\n                        <\/div>\n                        \n                        <div style=\"margin-bottom: 8px; font-weight: 600; font-size: 11px;\">\u5404\u6307\u6807\u6743\u91cd\u8bf4\u660e<\/div>\n                        <div class=\"formula-item\"><span>\u8fb9\u7f18\u5bc6\u5ea6<\/span><span>\u6743\u91cd25%<\/span><\/div>\n                        <div class=\"formula-item\"><span>\u7eb9\u7406\u5206\u6570<\/span><span>\u6743\u91cd25%<\/span><\/div>\n                        <div class=\"formula-item\"><span>\u9999\u519c\u71b5<\/span><span>\u6743\u91cd10%<\/span><\/div>\n                        <div class=\"formula-item\"><span>\u5bf9\u6bd4\u5ea6<\/span><span>\u6743\u91cd15%<\/span><\/div>\n                        <div class=\"formula-item\"><span>\u65b9\u5dee(\u5f52\u4e00\u5316)<\/span><span>\u6743\u91cd15%<\/span><\/div>\n                        <div class=\"formula-item\"><span>\u989c\u8272\u591a\u6837\u6027<\/span><span>\u6743\u91cd10%<\/span><\/div>\n                        \n                        <div style=\"margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color);\">\n                            <div style=\"font-weight: 600; font-size: 11px; margin-bottom: 6px;\">\u5bc6\u5ea6\u7b49\u7ea7\u8bf4\u660e<\/div>\n                            <div style=\"font-size: 10px; line-height: 1.6; color: var(--text-secondary);\">\n                                <div style=\"display: flex; justify-content: space-between; padding: 3px 0; border-bottom: 1px solid var(--border-color);\">\n                                    <span>\u8d85\u9ad8\u5bc6\u5ea6<\/span><span style=\"color: #ef4444;\">75-100\u5206<\/span>\n                                <\/div>\n                                <div style=\"display: flex; justify-content: space-between; padding: 3px 0; border-bottom: 1px solid var(--border-color);\">\n                                    <span>\u9ad8\u5bc6\u5ea6<\/span><span style=\"color: #f59e0b;\">50-75\u5206<\/span>\n                                <\/div>\n                                <div style=\"display: flex; justify-content: space-between; padding: 3px 0; border-bottom: 1px solid var(--border-color);\">\n                                    <span>\u4f4e\u5bc6\u5ea6<\/span><span style=\"color: #10b981;\">25-50\u5206<\/span>\n                                <\/div>\n                                <div style=\"display: flex; justify-content: space-between; padding: 3px 0;\">\n                                    <span>\u8d85\u4f4e\u5bc6\u5ea6<\/span><span style=\"color: #818cf8;\">0-25\u5206<\/span>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                        \n                        <div style=\"margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color);\">\n                            <div style=\"font-weight: 600; font-size: 11px; margin-bottom: 6px;\">\u516c\u5f0f\u7406\u8bba\u6765\u6e90\u4e0e\u4f9d\u636e<\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary);\">\n                                \u672c\u8bc4\u5206\u516c\u5f0f\u7eb3\u5165\u4e866\u4e2a\u6838\u5fc3\u89c6\u89c9\u6307\u6807\uff0c\u5404\u6307\u6807\u6743\u91cd\u57fa\u4e8e\u89c6\u89c9\u611f\u77e5\u7406\u8bba\u548c\u56fe\u50cf\u590d\u6742\u5ea6\u7814\u7a76\u7684\u5206\u914d\u539f\u5219\uff1a\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 6px; padding-left: 8px;\">\n                                <strong>1. \u8fb9\u7f18\u5bc6\u5ea6 (\u6743\u91cd25%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1aMarr-Hildreth\u8fb9\u7f18\u68c0\u6d4b\u7406\u8bba<br>\n                                &#8211; \u6765\u6e90\uff1aMarr, D., &#038; Hildreth, E. (1980). Theory of edge detection. Proceedings of the Royal Society B.<br>\n                                &#8211; \u7406\u8bba\uff1a\u8fb9\u7f18\u662f\u89c6\u89c9\u6ce8\u610f\u529b\u7684\u4e3b\u8981\u6355\u6349\u70b9\uff0c\u53cd\u6620\u56fe\u50cf\u4e2d\u8f6e\u5ed3\u548c\u5f62\u72b6\u8fb9\u754c\u7684\u5bc6\u96c6\u7a0b\u5ea6 (Itti, L., et al., 1998. IEEE Transactions on Pattern Analysis and Machine Intelligence)<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u8fb9\u7f18\u662f\u4eba\u7c7b\u89c6\u89c9\u7cfb\u7edf\u6700\u5148\u611f\u77e5\u7684\u57fa\u672c\u5143\u7d20\uff0c\u5bf9\u4e8e\u5224\u65ad\u753b\u9762\u7e41\u7b80\u7a0b\u5ea6\u5177\u6709\u6700\u9ad8\u6743\u91cd\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 8px; padding-left: 8px;\">\n                                <strong>2. \u7eb9\u7406\u5206\u6570 (\u6743\u91cd25%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1aTamura\u7eb9\u7406\u7279\u5f81<br>\n                                &#8211; \u6765\u6e90\uff1aTamura, H., Mori, S., &#038; Yamawaki, T. (1978). Textural features corresponding to visual perception. IEEE Transactions on Systems, Man, and Cybernetics.<br>\n                                &#8211; \u7406\u8bba\uff1a\u7eb9\u7406\u53cd\u6620\u56fe\u50cf\u5c40\u90e8\u533a\u57df\u7684\u7070\u5ea6\u53d8\u5316\u590d\u6742\u5ea6\uff0c\u662f\u89c6\u89c9\u590d\u6742\u5ea6\u7684\u91cd\u8981\u7ec4\u6210\u90e8\u5206<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u7eb9\u7406\u590d\u6742\u5ea6\u76f4\u63a5\u53cd\u6620\u753b\u9762\u7ec6\u8282\u7684\u4e30\u5bcc\u7a0b\u5ea6\uff0c\u662f\u89c6\u89c9\u7e41\u5bc6\u5ea6\u7684\u91cd\u8981\u6307\u6807\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 8px; padding-left: 8px;\">\n                                <strong>3. \u9999\u519c\u71b5 (\u6743\u91cd10%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1a\u9999\u519c\u4fe1\u606f\u8bba (Shannon Information Theory)<br>\n                                &#8211; \u6765\u6e90\uff1aShannon, C. E. (1948). A Mathematical Theory of Communication. Bell System Technical Journal.<br>\n                                &#8211; \u7406\u8bba\uff1a\u4fe1\u606f\u71b5\u662f\u8861\u91cf\u56fe\u50cf\u4fe1\u606f\u91cf\u7684\u6838\u5fc3\u6307\u6807\uff0c\u71b5\u503c\u8d8a\u9ad8\u8868\u793a\u56fe\u50cf\u4fe1\u606f\u8d8a\u4e30\u5bcc (Gonzalez, R. C. &#038; Woods, R. E., 2018. Digital Image Processing, Pearson)<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u4fe1\u606f\u71b5\u662f\u5168\u5c40\u6027\u6307\u6807\uff0c\u53cd\u6620\u6574\u4f53\u4fe1\u606f\u91cf\uff0c\u4f5c\u4e3a\u8f85\u52a9\u53c2\u8003\u6307\u6807\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 8px; padding-left: 8px;\">\n                                <strong>4. \u5bf9\u6bd4\u5ea6 (\u6743\u91cd15%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1a\u89c6\u89c9\u5bf9\u6bd4\u654f\u611f\u5ea6\u7406\u8bba (Visual Contrast Sensitivity)<br>\n                                &#8211; \u6765\u6e90\uff1aBarten, P. G. J. (1999). Contrast Sensitivity of the Human Eye. SPIE Press.<br>\n                                &#8211; \u7406\u8bba\uff1a\u5bf9\u6bd4\u5ea6\u53cd\u6620\u56fe\u50cf\u660e\u6697\u5dee\u5f02\u7a0b\u5ea6\uff0c\u662f\u89c6\u89c9\u611f\u77e5\u7684\u57fa\u672c\u7ef4\u5ea6\u4e4b\u4e00<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u5bf9\u6bd4\u5ea6\u4e0e\u8fb9\u7f18\u68c0\u6d4b\u5f62\u6210\u4e92\u8865\uff0c\u5171\u540c\u53cd\u6620\u753b\u9762\u7ec6\u8282\u7279\u5f81\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 8px; padding-left: 8px;\">\n                                <strong>5. \u65b9\u5dee\u5f52\u4e00\u5316 (\u6743\u91cd15%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1a\u7edf\u8ba1\u5b66\u4e8c\u9636\u77e9\u5206\u6790<br>\n                                &#8211; \u6765\u6e90\uff1aSonka, M., Hlavac, V., &#038; Boyle, R. (2014). Image Processing, Analysis, and Machine Vision. Cengage Learning.<br>\n                                &#8211; \u7406\u8bba\uff1a\u65b9\u5dee\u53cd\u6620\u56fe\u50cf\u7070\u5ea6\u5206\u5e03\u7684\u79bb\u6563\u7a0b\u5ea6\uff0c\u4e0e\u6574\u4f53\u5bf9\u6bd4\u5ea6\u7279\u5f81\u4e92\u8865<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u65b9\u5dee\u4f5c\u4e3a\u7edf\u8ba1\u6307\u6807\uff0c\u4e0e\u5bf9\u6bd4\u5ea6\u534f\u540c\u53cd\u6620\u753b\u9762\u6574\u4f53\u53d8\u5316\u7a0b\u5ea6\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 8px; padding-left: 8px;\">\n                                <strong>6. \u989c\u8272\u591a\u6837\u6027 (\u6743\u91cd10%)<\/strong><br>\n                                &#8211; \u7406\u8bba\u540d\u79f0\uff1a\u8272\u5f69\u590d\u6742\u5ea6\u7406\u8bba<br>\n                                &#8211; \u6765\u6e90\uff1aOrchard, M. T. &#038; Bouman, C. A. (1991). Color quantization of images. IEEE Transactions on Signal Processing.<br>\n                                &#8211; \u7406\u8bba\uff1a\u8272\u5f69\u4e30\u5bcc\u5ea6\u662f\u5f71\u54cd\u89c6\u89c9\u611f\u77e5\u590d\u6742\u5ea6\u7684\u91cd\u8981\u56e0\u7d20\uff0c\u8272\u5f69\u79cd\u7c7b\u8d8a\u591a\u89c6\u89c9\u4fe1\u606f\u8d8a\u4e30\u5bcc<br>\n                                &#8211; <strong>\u6743\u91cd\u5206\u914d\u7406\u7531\uff1a<\/strong>\u989c\u8272\u4fe1\u606f\u5bf9\u4e8e\u9ed1\u767d\u56fe\u50cf\u5206\u6790\u8d21\u732e\u6709\u9650\uff0c\u4f5c\u4e3a\u8f85\u52a9\u53c2\u8003\u6307\u6807\n                            <\/div>\n                        <\/div>\n                        \n                        <div style=\"margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color);\">\n                            <div style=\"font-weight: 600; font-size: 11px; margin-bottom: 6px; color: var(--accent-yellow);\">\u26a0\ufe0f \u6d45\u8272\u3001\u767d\u8272\u533a\u57df\u6570\u503c\u504f\u9ad8\u8bf4\u660e<\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary);\">\n                                \u6b63\u5e38\u60c5\u51b5\u4e0b\uff0c\u5355\u8272\u533a\u57df\u7684\u8bc4\u5206\u5e94\u4f4e\u4e8e25\uff0c\u4f46\u672a\u7ecf\u8fc7\u9884\u5904\u7406\u7684\u5355\u8272\u80cc\u666f\uff08\u5982\u767d\u8272\u3001\u6d45\u7070\u8272\uff09\u56fe\u50cf\u8bc4\u5206\u53ef\u80fd\u504f\u9ad8\uff0c\u539f\u56e0\u5982\u4e0b\uff1a\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 4px; padding-left: 10px;\">\n                                \u2022 \u6d45\u8272\u80cc\u666f\u4e0e\u5185\u5bb9\u7684\u5bf9\u6bd4\u8fb9\u7f18\u88ab\u8bc6\u522b\u4e3a&#8221;\u4e30\u5bcc\u8fb9\u7f18&#8221;<br>\n                                \u2022 JPEG\u538b\u7f29\u4ea7\u751f\u7684\u566a\u70b9\u4f1a\u589e\u52a0\u8fb9\u7f18\u68c0\u6d4b\u7ed3\u679c<br>\n                                \u2022 \u533a\u57df\u4e2d\u7684\u9634\u5f71\u3001\u53cd\u5149\u3001\u8936\u76b1\u3001\u7070\u5c18\u3001\u7eb9\u7406\u7b49\u7ec6\u5fae\u53d8\u5316\u88ab\u8bef\u5224\u4e3a\u7ec6\u8282\n                            <\/div>\n                            <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary); margin-top: 6px;\">\n                                <strong>\u5efa\u8bae\uff1a<\/strong>\u4f7f\u7528\u9009\u6846\u529f\u80fd\u5206\u6790\u4e3b\u4f53\u533a\u57df\uff0c\u907f\u514d\u6df7\u6742\u7684\u6d45\u8272\u80cc\u666f\u5f71\u54cd\u7ed3\u679c\uff0c\u6216\u5c06\u56fe\u7247\u63d0\u524d\u8fdb\u884c\u9884\u5904\u7406\uff0c\u4f8b\u5982\u8c03\u6574\u753b\u9762\u9608\u503c\u3001\u4e8c\u503c\u5316\u5904\u7406\u7b49\uff0c\u4ee5\u6d88\u9664\u6d45\u8272\u90e8\u5206\u7684\u566a\u58f0\u3002\n                            <\/div>\n                        <\/div>\n                        \n                        <div style=\"margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color);\">\n                            <div style=\"font-weight: 600; font-size: 11px; margin-bottom: 4px;\">\ud83d\udcd0<\/div>\n                            \u8bc4\u5206\u51c6\u786e\u7684\u6761\u4ef6 <div style=\"font-size: 10px; line-height: 1.5; color: var(--text-secondary);\">\n                                \u2022 \u5206\u6790\u533a\u57df\u5e94\u5305\u542b\u8db3\u591f\u591a\u7684\u89c6\u89c9\u5143\u7d20\uff08\u5efa\u8bae\u56fe\u7247\u5927\u4e8e100\u00d7100\u50cf\u7d20\uff09<br>\n                                \u2022 \u4f7f\u7528\u5305\u542b\u5927\u9762\u79ef\u5355\u8272\u533a\u57df\u7684\u56fe\u7247\uff08\u7eaf\u767d\u3001\u7eaf\u9ed1\uff09\u5e94\u786e\u4fdd\u56fe\u7247\u5df2\u7ecf\u8fc7\u9884\u5904\u7406<br>\n                                \u2022 \u63a8\u8350\u5206\u6790\u6574\u5f20\u56fe\u50cf\u6216\u4f7f\u7528\u9009\u6846\u9009\u4e2d\u4e3b\u4f53\u533a\u57df\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- \u96f7\u8fbe\u56fe -->\n            <div class=\"dashboard-section\">\n                <div class=\"section-title\">\u516d\u7ef4\u96f7\u8fbe\u56fe<\/div>\n                <div class=\"radar-container\">\n                    <canvas id=\"radarChart\"><\/canvas>\n                <\/div>\n            <\/div>\n\n            <!-- \u7070\u5ea6\u76f4\u65b9\u56fe -->\n            <div class=\"dashboard-section\">\n                <div class=\"section-title\">\u7070\u5ea6\u76f4\u65b9\u56fe<\/div>\n                <div class=\"histogram-container\">\n                    <canvas id=\"histogramChart\"><\/canvas>\n                <\/div>\n            <\/div>\n\n            <!-- \u6307\u6807\u8be6\u60c5 -->\n            <div class=\"dashboard-section\">\n                <div class=\"section-title\">\u8be6\u7ec6\u6307\u6807<\/div>\n                <div class=\"metrics-grid\">\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u9999\u519c\u71b5 <span class=\"metric-help\" data-tooltip=\"\u4fe1\u606f\u91cf\u6307\u6807\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u56fe\u50cf\u4fe1\u606f\u8d8a\u4e30\u5bcc\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u56fe\u50cf\u8d8a\u5e73\u6ed1\u3002\u53d6\u503c\u8303\u56f4\uff1a0-8\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricEntropy\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u8fb9\u7f18\u5bc6\u5ea6 <span class=\"metric-help\" data-tooltip=\"\u8fb9\u7f18\u50cf\u7d20\u5360\u6bd4\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u8f6e\u5ed3\u8d8a\u591a\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u56fe\u50cf\u8d8a\u5e73\u5766\u3002\u53d6\u503c\u8303\u56f4\uff1a0-100%\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricEdge\">0%<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u65b9\u5dee <span class=\"metric-help\" data-tooltip=\"\u7070\u5ea6\u5206\u5e03\u79bb\u6563\u7a0b\u5ea6\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u660e\u6697\u53d8\u5316\u8d8a\u5267\u70c8\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u753b\u9762\u8d8a\u5e73\u5766\u3002\u53d6\u503c\u8303\u56f4\uff1a0-6500\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricVariance\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u7eb9\u7406\u5206\u6570 <span class=\"metric-help\" data-tooltip=\"\u5c40\u90e8\u65b9\u5dee\u6307\u6807\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u7eb9\u7406\u8d8a\u590d\u6742\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u7eb9\u7406\u8d8a\u5355\u4e00\u3002\u53d6\u503c\u8303\u56f4\uff1a0-1\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricTexture\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u989c\u8272\u79cd\u7c7b <span class=\"metric-help\" data-tooltip=\"\u72ec\u7279\u989c\u8272\u6570\u91cf\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u8272\u5f69\u8d8a\u4e30\u5bcc\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u8272\u5f69\u8d8a\u5355\u8c03\u3002\u53d6\u503c\u8303\u56f4\uff1a0-256\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricColors\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u989c\u8272\u591a\u6837\u6027 <span class=\"metric-help\" data-tooltip=\"\u8272\u5f69\u4e30\u5bcc\u7a0b\u5ea6\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u8272\u5f69\u8d8a\u591a\u6837\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u8272\u5f69\u8d8a\u5355\u8c03\u3002\u53d6\u503c\u8303\u56f4\uff1a0-1\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricDiversity\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u5bf9\u6bd4\u5ea6 <span class=\"metric-help\" data-tooltip=\"\u660e\u6697\u5dee\u5f02\u7a0b\u5ea6\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u660e\u6697\u5bf9\u6bd4\u8d8a\u5f3a\u70c8\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u753b\u9762\u8d8a\u7070\u6697\u3002\u53d6\u503c\u8303\u56f4\uff1a0-1\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricContrast\">0<\/div>\n                    <\/div>\n                    <div class=\"metric-card\">\n                        <div class=\"metric-label\">\u4eae\u5ea6 <span class=\"metric-help\" data-tooltip=\"\u5e73\u5747\u660e\u6697\u7a0b\u5ea6\u3002\u6570\u503c\u8d8a\u5927\u8868\u793a\u753b\u9762\u8d8a\u4eae\uff1b\u6570\u503c\u8d8a\u5c0f\u8868\u793a\u753b\u9762\u8d8a\u6697\u3002\u53d6\u503c\u8303\u56f4\uff1a0-255\">?<\/span><\/div>\n                        <div class=\"metric-value\" id=\"metricBrightness\">0<\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n\n            <!-- \u6570\u636e\u8868\u683c -->\n            <div class=\"table-section\">\n                <div class=\"section-title\">\u5206\u6790\u8bb0\u5f55\u5bf9\u6bd4<\/div>\n                <div class=\"table-scroll\">\n                    <table class=\"data-table\" id=\"dataTable\">\n                        <thead>\n                            <tr>\n                                <th>\u7f29\u7565\u56fe<\/th>\n                                <th>\u56fe\u7247\u540d\u79f0<\/th>\n                                <th>\u8bc4\u5206<\/th>\n                                <th>\u71b5<\/th>\n                                <th>\u8fb9\u7f18<\/th>\n                                <th>\u65b9\u5dee<\/th>\n                            <\/tr>\n                        <\/thead>\n                        <tbody id=\"tableBody\">\n                        <\/tbody>\n                    <\/table>\n                <\/div>\n                <div class=\"empty-tip\" id=\"emptyTip\">\u6682\u65e0\u5206\u6790\u8bb0\u5f55<\/div>\n                \n                <div class=\"export-group\">\n                    <button class=\"btn btn-secondary\" id=\"exportCsvBtn\" disabled>\n                        <svg viewBox=\"0 0 24 24\"><path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"\/><\/svg>\n                        \u5bfc\u51faCSV\n                    <\/button>\n                    <button class=\"btn btn-secondary\" id=\"exportJsonBtn\" disabled>\n                        <svg viewBox=\"0 0 24 24\"><path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"\/><\/svg>\n                        \u5bfc\u51faJSON\n                    <\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n        \/\/ \u5168\u5c40\u53d8\u91cf\n        let currentImageSrc = '';\n        let currentFileName = '';\n        let edgeImageSrc = '';\n        let grayImageSrc = '';\n        let currentMetrics = null;\n        let analysisHistory = [];\n        let charts = {};\n        \n        \/\/ \u9009\u6846\u76f8\u5173\u53d8\u91cf\n        let selectionCanvas, selectionCtx;\n        let isDrawing = false;\n        let startX, startY, endX, endY;\n        let selectionRect = null; \/\/ {x, y, width, height} \u539f\u59cb\u56fe\u50cf\u5750\u6807\n        let imgElement, imgNaturalWidth, imgNaturalHeight;\n        let displayWidth, displayHeight, offsetX, offsetY;\n\n        \/\/ \u521d\u59cb\u5316\n        document.addEventListener('DOMContentLoaded', function() {\n            initCharts();\n            initSelectionCanvas();\n            setupEventListeners();\n        });\n\n        \/\/ \u521d\u59cb\u5316\u9009\u6846\u753b\u5e03\n        function initSelectionCanvas() {\n            selectionCanvas = document.getElementById('selectionCanvas');\n            selectionCtx = selectionCanvas.getContext('2d');\n            imgElement = document.getElementById('displayImage');\n        }\n\n        \/\/ \u66f4\u65b0\u9009\u6846\u753b\u5e03\u5c3a\u5bf8\n        function updateCanvasSize() {\n            const wrapper = document.getElementById('canvasWrapper');\n            const rect = wrapper.getBoundingClientRect();\n            selectionCanvas.width = rect.width;\n            selectionCanvas.height = rect.height;\n            \n            \/\/ \u8ba1\u7b97\u56fe\u7247\u5b9e\u9645\u663e\u793a\u5c3a\u5bf8\u548c\u504f\u79fb\n            const imgRatio = imgNaturalWidth \/ imgNaturalHeight;\n            const wrapperRatio = rect.width \/ rect.height;\n            \n            if (imgRatio > wrapperRatio) {\n                displayWidth = rect.width;\n                displayHeight = rect.width \/ imgRatio;\n            } else {\n                displayHeight = rect.height;\n                displayWidth = rect.height * imgRatio;\n            }\n            \n            offsetX = (rect.width - displayWidth) \/ 2;\n            offsetY = (rect.height - displayHeight) \/ 2;\n        }\n\n        \/\/ \u8bbe\u7f6e\u4e8b\u4ef6\u76d1\u542c\n        function setupEventListeners() {\n            \/\/ \u4e0a\u4f20\n            document.getElementById('uploadZone').addEventListener('click', () => document.getElementById('fileInput').click());\n            document.getElementById('fileInput').addEventListener('change', handleFile);\n            \n            \/\/ \u62d6\u62fd\u4e0a\u4f20\n            const uploadZone = document.getElementById('uploadZone');\n            uploadZone.addEventListener('dragover', (e) => { e.preventDefault(); uploadZone.style.borderColor = '#3b82f6'; });\n            uploadZone.addEventListener('dragleave', () => { uploadZone.style.borderColor = '#475569'; });\n            uploadZone.addEventListener('drop', (e) => {\n                e.preventDefault();\n                uploadZone.style.borderColor = '#475569';\n                if (e.dataTransfer.files[0]) handleFile({ target: { files: e.dataTransfer.files } });\n            });\n\n            \/\/ \u9009\u6846\u7ed8\u5236\n            selectionCanvas.addEventListener('mousedown', startSelection);\n            selectionCanvas.addEventListener('mousemove', updateSelection);\n            selectionCanvas.addEventListener('mouseup', endSelection);\n            selectionCanvas.addEventListener('mouseleave', endSelection);\n\n            \/\/ \u89c6\u56fe\u5207\u6362\n            document.querySelectorAll('.view-tab').forEach(tab => {\n                tab.addEventListener('click', () => switchView(tab.dataset.view));\n            });\n\n            \/\/ \u6309\u94ae\n            document.getElementById('analyzeBtn').addEventListener('click', analyzeImage);\n            document.getElementById('resetBtn').addEventListener('click', resetAll);\n            document.getElementById('resetSelectionBtn').addEventListener('click', resetSelection);\n            document.getElementById('exportCsvBtn').addEventListener('click', exportCSV);\n            document.getElementById('exportJsonBtn').addEventListener('click', exportJSON);\n\n            \/\/ \u8bc4\u5206\u8bf4\u660e toggle\n            document.getElementById('scoreToggle').addEventListener('click', function() {\n                this.classList.toggle('open');\n                document.getElementById('scoreFormula').classList.toggle('show');\n            });\n\n            \/\/ \u7a97\u53e3\u5927\u5c0f\u53d8\u5316\u65f6\u66f4\u65b0\u753b\u5e03\n            window.addEventListener('resize', () => {\n                if (currentImageSrc) {\n                    updateCanvasSize();\n                    redrawSelection();\n                }\n            });\n        }\n\n        \/\/ \u5904\u7406\u6587\u4ef6\n        function handleFile(event) {\n            const file = event.target.files[0];\n            if (!file || !file.type.startsWith('image\/')) {\n                alert('\u8bf7\u4e0a\u4f20\u56fe\u7247\u6587\u4ef6');\n                return;\n            }\n\n            showLoading(true);\n            currentFileName = file.name;\n            \n            \/\/ \u6e05\u9664input\u7684value\uff0c\u5141\u8bb8\u91cd\u590d\u4e0a\u4f20\n            document.getElementById('fileInput').value = '';\n            \n            const reader = new FileReader();\n            reader.onload = function(e) {\n                currentImageSrc = e.target.result;\n                imgElement.src = e.target.result;\n                imgElement.onload = function() {\n                    imgNaturalWidth = imgElement.naturalWidth;\n                    imgNaturalHeight = imgElement.naturalHeight;\n                    \n                    document.getElementById('previewSection').classList.add('active');\n                    updateCanvasSize();\n                    clearSelection();\n                    \n                    showLoading(false);\n                    enableButtons();\n                };\n            };\n            reader.readAsDataURL(file);\n        }\n\n        \/\/ \u5f00\u59cb\u7ed8\u5236\u9009\u6846\n        function startSelection(e) {\n            if (!currentImageSrc) return;\n            isDrawing = true;\n            const rect = selectionCanvas.getBoundingClientRect();\n            startX = e.clientX - rect.left;\n            startY = e.clientY - rect.top;\n        }\n\n        \/\/ \u66f4\u65b0\u9009\u6846\n        function updateSelection(e) {\n            if (!isDrawing) return;\n            \n            const rect = selectionCanvas.getBoundingClientRect();\n            endX = e.clientX - rect.left;\n            endY = e.clientY - rect.top;\n            \n            drawSelection(startX, startY, endX, endY);\n        }\n\n        \/\/ \u7ed3\u675f\u7ed8\u5236\u9009\u6846\n        function endSelection(e) {\n            if (!isDrawing) return;\n            isDrawing = false;\n            \n            \/\/ \u8ba1\u7b97\u9009\u6846\u5728\u539f\u59cb\u56fe\u50cf\u4e0a\u7684\u5750\u6807\n            const selX = Math.min(startX, endX);\n            const selY = Math.min(startY, endY);\n            const selW = Math.abs(endX - startX);\n            const selH = Math.abs(endY - startY);\n            \n            if (selW > 10 && selH > 10) {\n                \/\/ \u8f6c\u6362\u4e3a\u539f\u59cb\u56fe\u50cf\u5750\u6807\n                const scaleX = imgNaturalWidth \/ displayWidth;\n                const scaleY = imgNaturalHeight \/ displayHeight;\n                \n                selectionRect = {\n                    x: Math.round((selX - offsetX) * scaleX),\n                    y: Math.round((selY - offsetY) * scaleY),\n                    width: Math.round(selW * scaleX),\n                    height: Math.round(selH * scaleY)\n                };\n                \n                \/\/ \u786e\u4fdd\u9009\u6846\u5728\u56fe\u50cf\u8303\u56f4\u5185\n                selectionRect.x = Math.max(0, Math.min(selectionRect.x, imgNaturalWidth));\n                selectionRect.y = Math.max(0, Math.min(selectionRect.y, imgNaturalHeight));\n                selectionRect.width = Math.min(selectionRect.width, imgNaturalWidth - selectionRect.x);\n                selectionRect.height = Math.min(selectionRect.height, imgNaturalHeight - selectionRect.y);\n                \n                document.getElementById('resetSelectionBtn').disabled = false;\n            }\n            \n            drawSelection(startX, startY, endX, endY);\n        }\n\n        \/\/ \u7ed8\u5236\u9009\u6846\n        function drawSelection(x1, y1, x2, y2) {\n            const canvas = selectionCanvas;\n            selectionCtx.clearRect(0, 0, canvas.width, canvas.height);\n            \n            const x = Math.min(x1, x2);\n            const y = Math.min(y1, y2);\n            const w = Math.abs(x2 - x1);\n            const h = Math.abs(y2 - y1);\n            \n            if (w > 5 && h > 5) {\n                \/\/ \u7ed8\u5236\u534a\u900f\u660e\u80cc\u666f\n                selectionCtx.fillStyle = 'rgba(239, 68, 68, 0.1)';\n                selectionCtx.fillRect(x, y, w, h);\n                \n                \/\/ \u7ed8\u5236\u8fb9\u6846\n                selectionCtx.strokeStyle = '#ef4444';\n                selectionCtx.lineWidth = 2;\n                selectionCtx.setLineDash([5, 5]);\n                selectionCtx.strokeRect(x, y, w, h);\n                selectionCtx.setLineDash([]);\n                \n                \/\/ \u663e\u793a\u5c3a\u5bf8\u4fe1\u606f\n                if (selectionRect) {\n                    selectionCtx.fillStyle = '#ef4444';\n                    selectionCtx.font = '11px sans-serif';\n                    selectionCtx.fillText(`${selectionRect.width}\u00d7${selectionRect.height}`, x, y - 5);\n                }\n            }\n        }\n\n        \/\/ \u91cd\u7ed8\u9009\u6846\uff08\u7a97\u53e3\u5927\u5c0f\u53d8\u5316\u65f6\uff09\n        function redrawSelection() {\n            if (!selectionRect) {\n                selectionCtx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height);\n                return;\n            }\n            \n            const scaleX = displayWidth \/ imgNaturalWidth;\n            const scaleY = displayHeight \/ imgNaturalHeight;\n            \n            const x = offsetX + selectionRect.x * scaleX;\n            const y = offsetY + selectionRect.y * scaleY;\n            const w = selectionRect.width * scaleX;\n            const h = selectionRect.height * scaleY;\n            \n            drawSelection(x, y, x + w, y + h);\n        }\n\n        \/\/ \u6e05\u9664\u9009\u6846\n        function clearSelection() {\n            selectionRect = null;\n            selectionCtx.clearRect(0, 0, selectionCanvas.width, selectionCanvas.height);\n            document.getElementById('resetSelectionBtn').disabled = true;\n        }\n\n        \/\/ \u91cd\u7f6e\u9009\u533a\n        function resetSelection() {\n            clearSelection();\n        }\n\n        \/\/ \u5207\u6362\u89c6\u56fe\n        function switchView(view) {\n            document.querySelectorAll('.view-tab').forEach(tab => tab.classList.remove('active'));\n            document.querySelector(`[data-view=\"${view}\"]`).classList.add('active');\n            \n            if (view === 'original') {\n                imgElement.src = currentImageSrc;\n            } else if (view === 'edge') {\n                imgElement.src = edgeImageSrc || currentImageSrc;\n            } else if (view === 'gray') {\n                imgElement.src = grayImageSrc || currentImageSrc;\n            }\n        }\n\n        \/\/ \u5206\u6790\u56fe\u50cf\n        function analyzeImage() {\n            showLoading(true);\n            \n            setTimeout(function() {\n                \/\/ \u521b\u5efa\u753b\u5e03\u83b7\u53d6\u5206\u6790\u533a\u57df\n                const canvas = document.createElement('canvas');\n                const ctx = canvas.getContext('2d');\n                \n                let sx = 0, sy = 0, sw = imgNaturalWidth, sh = imgNaturalHeight;\n                \n                \/\/ \u5982\u679c\u6709\u9009\u6846\uff0c\u4f7f\u7528\u9009\u6846\u533a\u57df\n                if (selectionRect) {\n                    sx = selectionRect.x;\n                    sy = selectionRect.y;\n                    sw = selectionRect.width;\n                    sh = selectionRect.height;\n                }\n                \n                canvas.width = sw;\n                canvas.height = sh;\n                ctx.drawImage(imgElement, sx, sy, sw, sh, 0, 0, sw, sh);\n                \n                const imageData = ctx.getImageData(0, 0, sw, sh);\n                \n                \/\/ \u751f\u6210\u89c6\u56fe\u56fe\u50cf\n                generateViewImages(imageData, sw, sh);\n                \n                \/\/ \u8ba1\u7b97\u6307\u6807\n                const metrics = calculateMetrics(imageData, sw, sh);\n                currentMetrics = metrics;\n                \n                \/\/ \u663e\u793a\u7ed3\u679c\n                displayResults(metrics);\n                \n                \/\/ \u751f\u6210\u7f29\u7565\u56fe\uff08\u4f7f\u7528\u5206\u6790\u533a\u57df\uff09\n                const thumbCanvas = document.createElement('canvas');\n                thumbCanvas.width = sw;\n                thumbCanvas.height = sh;\n                thumbCanvas.getContext('2d').drawImage(canvas, 0, 0);\n                const thumbSrc = thumbCanvas.toDataURL();\n                \n                \/\/ \u6dfb\u52a0\u5230\u5386\u53f2\u8bb0\u5f55\n                addToHistory(currentFileName, metrics, thumbSrc);\n                \n                showLoading(false);\n            }, 100);\n        }\n\n        \/\/ \u751f\u6210\u89c6\u56fe\u56fe\u50cf\n        function generateViewImages(imageData, width, height) {\n            const grayData = new Uint8Array(width * height);\n            const edgeData = new Uint8Array(width * height);\n            \n            \/\/ \u7070\u5ea6\u8f6c\u6362\n            for (let i = 0; i < imageData.data.length; i += 4) {\n                const gray = Math.round(0.299 * imageData.data[i] + 0.587 * imageData.data[i + 1] + 0.114 * imageData.data[i + 2]);\n                grayData[i \/ 4] = gray;\n            }\n            \n            \/\/ Sobel\u8fb9\u7f18\u68c0\u6d4b\n            const sobelX = [-1, 0, 1, -2, 0, 2, -1, 0, 1];\n            const sobelY = [-1, -2, -1, 0, 0, 0, 1, 2, 1];\n            \n            for (let y = 1; y < height - 1; y++) {\n                for (let x = 1; x < width - 1; x++) {\n                    let gx = 0, gy = 0;\n                    for (let ky = -1; ky <= 1; ky++) {\n                        for (let kx = -1; kx <= 1; kx++) {\n                            const idx = (y + ky) * width + (x + kx);\n                            const kidx = (ky + 1) * 3 + (kx + 1);\n                            gx += grayData[idx] * sobelX[kidx];\n                            gy += grayData[idx] * sobelY[kidx];\n                        }\n                    }\n                    const mag = Math.sqrt(gx * gx + gy * gy);\n                    edgeData[y * width + x] = mag > 30 ? 255 : 0;\n                }\n            }\n            \n            \/\/ \u751f\u6210\u7070\u5ea6\u56fe\n            const grayCanvas = document.createElement('canvas');\n            grayCanvas.width = width;\n            grayCanvas.height = height;\n            const grayCtx = grayCanvas.getContext('2d');\n            const grayImgData = grayCtx.createImageData(width, height);\n            for (let i = 0; i < grayData.length; i++) {\n                grayImgData.data[i * 4] = grayData[i];\n                grayImgData.data[i * 4 + 1] = grayData[i];\n                grayImgData.data[i * 4 + 2] = grayData[i];\n                grayImgData.data[i * 4 + 3] = 255;\n            }\n            grayCtx.putImageData(grayImgData, 0, 0);\n            grayImageSrc = grayCanvas.toDataURL();\n            \n            \/\/ \u751f\u6210\u8fb9\u7f18\u56fe\n            const edgeCanvas = document.createElement('canvas');\n            edgeCanvas.width = width;\n            edgeCanvas.height = height;\n            const edgeCtx = edgeCanvas.getContext('2d');\n            const edgeImgData = edgeCtx.createImageData(width, height);\n            for (let i = 0; i < edgeData.length; i++) {\n                edgeImgData.data[i * 4] = edgeData[i];\n                edgeImgData.data[i * 4 + 1] = edgeData[i];\n                edgeImgData.data[i * 4 + 2] = edgeData[i];\n                edgeImgData.data[i * 4 + 3] = 255;\n            }\n            edgeCtx.putImageData(edgeImgData, 0, 0);\n            edgeImageSrc = edgeCanvas.toDataURL();\n        }\n\n        \/\/ \u8ba1\u7b97\u6240\u6709\u6307\u6807\n        function calculateMetrics(imageData, width, height) {\n            const data = imageData.data;\n            const grayData = new Uint8Array(width * height);\n            const totalPixels = width * height;\n            \n            \/\/ \u7070\u5ea6\u8f6c\u6362\n            let totalBrightness = 0;\n            for (let i = 0; i < data.length; i += 4) {\n                const gray = Math.round(0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]);\n                grayData[i \/ 4] = gray;\n                totalBrightness += gray;\n            }\n            \n            \/\/ \u4eae\u5ea6\n            const brightness = Math.round(totalBrightness \/ (data.length \/ 4));\n            \n            \/\/ \u9999\u519c\u71b5\n            const histogram = new Array(256).fill(0);\n            for (let i = 0; i < grayData.length; i++) {\n                histogram[grayData[i]]++;\n            }\n            \n            let entropy = 0;\n            for (let i = 0; i < 256; i++) {\n                if (histogram[i] > 0) {\n                    const p = histogram[i] \/ grayData.length;\n                    entropy -= p * Math.log2(p);\n                }\n            }\n            \n            \/\/ \u65b9\u5dee\uff08\u65b0\u589e\u6307\u6807\uff09\n            const mean = grayData.reduce((a, b) => a + b, 0) \/ grayData.length;\n            const variance = grayData.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) \/ grayData.length;\n            const normalizedVariance = Math.min(variance \/ 6500, 1) * 100; \/\/ \u5f52\u4e00\u5316\u52300-100\n            \n            \/\/ \u8fb9\u7f18\u5bc6\u5ea6\n            const sobelX = [-1, 0, 1, -2, 0, 2, -1, 0, 1];\n            const sobelY = [-1, -2, -1, 0, 0, 0, 1, 2, 1];\n            let edgeCount = 0;\n            \n            for (let y = 1; y < height - 1; y++) {\n                for (let x = 1; x < width - 1; x++) {\n                    let gx = 0, gy = 0;\n                    for (let ky = -1; ky <= 1; ky++) {\n                        for (let kx = -1; kx <= 1; kx++) {\n                            const idx = (y + ky) * width + (x + kx);\n                            const kidx = (ky + 1) * 3 + (kx + 1);\n                            gx += grayData[idx] * sobelX[kidx];\n                            gy += grayData[idx] * sobelY[kidx];\n                        }\n                    }\n                    if (Math.sqrt(gx * gx + gy * gy) > 30) edgeCount++;\n                }\n            }\n            const edgeDensity = (edgeCount \/ ((width - 2) * (height - 2))) * 100;\n            \n            \/\/ \u7eb9\u7406\u5206\u6570\uff08\u5c40\u90e8\u65b9\u5dee\uff09\n            let textureScore = 0;\n            const blockSize = 8;\n            for (let by = 0; by < height - blockSize; by += blockSize) {\n                for (let bx = 0; bx < width - blockSize; bx += blockSize) {\n                    let sum = 0, sumSq = 0, count = 0;\n                    for (let y = by; y < by + blockSize; y++) {\n                        for (let x = bx; x < bx + blockSize; x++) {\n                            const val = grayData[y * width + x];\n                            sum += val;\n                            sumSq += val * val;\n                            count++;\n                        }\n                    }\n                    const blockMean = sum \/ count;\n                    const blockVariance = (sumSq \/ count) - (blockMean * blockMean);\n                    textureScore += blockVariance;\n                }\n            }\n            textureScore = Math.min(Math.sqrt(textureScore \/ ((width\/blockSize) * (height\/blockSize))) \/ 50, 1);\n            \n            \/\/ \u989c\u8272\u79cd\u7c7b\u548c\u591a\u6837\u6027\n            const colorSet = new Set();\n            const step = Math.max(1, Math.floor(data.length \/ 4 \/ 5000));\n            for (let i = 0; i < data.length; i += 4 * step) {\n                const key = `${Math.floor(data[i]\/16)},${Math.floor(data[i+1]\/16)},${Math.floor(data[i+2]\/16)}`;\n                colorSet.add(key);\n            }\n            const colorCount = Math.min(colorSet.size * 16, 256);\n            const colorDiversity = Math.min(colorCount \/ 256, 1);\n            \n            \/\/ \u5bf9\u6bd4\u5ea6\uff08\u6807\u51c6\u5dee\uff09\n            const contrast = Math.sqrt(variance) \/ 255;\n            \n            \/\/ \u7efc\u5408\u8bc4\u5206 - \u65b0\u516c\u5f0f\uff1a\u7eb3\u5165\u5168\u90e86\u4e2a\u6838\u5fc3\u6307\u6807\n            \/\/ \u8fb9\u7f18\u5bc6\u5ea625% + \u9999\u519c\u71b515% + \u7eb9\u7406\u5206\u657020% + \u989c\u8272\u591a\u6837\u602710% + \u5bf9\u6bd4\u5ea615% + \u65b9\u5dee\u5f52\u4e00\u531615%\n            const totalScore = Math.round(\n                edgeDensity * 0.25 +\n                (entropy \/ 8 * 100) * 0.10 +\n                textureScore * 100 * 0.25 +\n                colorDiversity * 100 * 0.10 +\n                contrast * 100 * 0.15 +\n                normalizedVariance * 0.15\n            );\n            \n            return {\n                entropy: entropy.toFixed(2),\n                edgeDensity: edgeDensity.toFixed(1),\n                variance: Math.round(variance),\n                normalizedVariance: normalizedVariance.toFixed(1),\n                textureScore: textureScore.toFixed(3),\n                colorCount: colorCount,\n                colorDiversity: colorDiversity.toFixed(3),\n                contrast: contrast.toFixed(3),\n                brightness: brightness,\n                totalScore: Math.min(totalScore, 100),\n                histogram: histogram\n            };\n        }\n\n        \/\/ \u663e\u793a\u7ed3\u679c\n        function displayResults(metrics) {\n            \/\/ \u7efc\u5408\u8bc4\u5206\u5df2\u5728\u4e0a\u65b9\u66f4\u65b0\n            \n            \/\/ \u66f4\u65b0\u7b49\u7ea7 - \u65b0\u5206\u7ea7: 0-25\u8d85\u4f4e\u5bc6\u5ea6, 25-50\u4f4e\u5bc6\u5ea6, 50-75\u9ad8\u5bc6\u5ea6, 75-100\u8d85\u9ad8\u5bc6\u5ea6\n            const levelEl = document.getElementById('scoreLevel');\n            const scoreBar = document.getElementById('scoreBar');\n            const scoreNum = document.getElementById('totalScore');\n            \n            \/\/ \u66f4\u65b0\u7efc\u5408\u8bc4\u5206\u6570\u5b57\n            if (scoreNum) {\n                scoreNum.textContent = metrics.totalScore;\n            }\n            \n            if (metrics.totalScore <= 25) {\n                levelEl.textContent = '\u8d85\u4f4e\u5bc6\u5ea6';\n                levelEl.className = 'level-badge ultra-low';\n                if (scoreBar) scoreBar.className = 'score-bar ultra-low';\n                if (scoreNum) scoreNum.style.color = '#818cf8';\n            } else if (metrics.totalScore <= 50) {\n                levelEl.textContent = '\u4f4e\u5bc6\u5ea6';\n                levelEl.className = 'level-badge low';\n                if (scoreBar) scoreBar.className = 'score-bar low';\n                if (scoreNum) scoreNum.style.color = '#10b981';\n            } else if (metrics.totalScore <= 75) {\n                levelEl.textContent = '\u9ad8\u5bc6\u5ea6';\n                levelEl.className = 'level-badge high';\n                if (scoreBar) scoreBar.className = 'score-bar high';\n                if (scoreNum) scoreNum.style.color = '#f59e0b';\n            } else {\n                levelEl.textContent = '\u8d85\u9ad8\u5bc6\u5ea6';\n                levelEl.className = 'level-badge ultra-high';\n                if (scoreBar) scoreBar.className = 'score-bar ultra-high';\n                if (scoreNum) scoreNum.style.color = '#ef4444';\n            }\n            \n            \/\/ \u66f4\u65b0\u8fdb\u5ea6\u6761\n            if (scoreBar) {\n                scoreBar.style.width = metrics.totalScore + '%';\n            }\n            \n            \/\/ \u66f4\u65b0\u96f7\u8fbe\u56fe\n            charts.radar.data.datasets[0].data = [\n                (metrics.entropy \/ 8) * 100,\n                metrics.edgeDensity,\n                (metrics.variance \/ 6500) * 100,\n                metrics.textureScore * 100,\n                metrics.colorDiversity * 100,\n                metrics.contrast * 100\n            ];\n            charts.radar.update();\n            \n            \/\/ \u66f4\u65b0\u76f4\u65b9\u56fe\n            if (metrics.histogram) {\n                charts.histogram.data.datasets[0].data = metrics.histogram;\n                charts.histogram.update();\n            }\n            \n            \/\/ \u66f4\u65b0\u6307\u6807\n            document.getElementById('metricEntropy').textContent = metrics.entropy;\n            document.getElementById('metricEdge').textContent = metrics.edgeDensity + '%';\n            document.getElementById('metricVariance').textContent = metrics.variance;\n            document.getElementById('metricTexture').textContent = metrics.textureScore;\n            document.getElementById('metricColors').textContent = metrics.colorCount;\n            document.getElementById('metricDiversity').textContent = metrics.colorDiversity;\n            document.getElementById('metricContrast').textContent = metrics.contrast;\n            document.getElementById('metricBrightness').textContent = metrics.brightness;\n        }\n\n        \/\/ \u6dfb\u52a0\u5230\u5386\u53f2\u8bb0\u5f55\n        function addToHistory(fileName, metrics, thumbSrc) {\n            const record = {\n                fileName: fileName,\n                thumbSrc: thumbSrc,\n                metrics: metrics,\n                time: new Date().toLocaleString('zh-CN')\n            };\n            analysisHistory.push(record);\n            updateTable();\n        }\n\n        \/\/ \u66f4\u65b0\u8868\u683c\n        function updateTable() {\n            const tbody = document.getElementById('tableBody');\n            const emptyTip = document.getElementById('emptyTip');\n            \n            if (analysisHistory.length === 0) {\n                emptyTip.style.display = 'block';\n                tbody.innerHTML = '';\n                return;\n            }\n            \n            emptyTip.style.display = 'none';\n            tbody.innerHTML = analysisHistory.map((item, index) => `\n                <tr>\n                    <td><img decoding=\"async\" src=\"${item.thumbSrc}\" class=\"thumb\" alt=\"\" title=\"\u70b9\u51fb\u67e5\u770b\u5927\u56fe\"><\/td>\n                    <td>${item.fileName}<\/td>\n                    <td>${item.metrics.totalScore}<\/td>\n                    <td>${item.metrics.entropy}<\/td>\n                    <td>${item.metrics.edgeDensity}%<\/td>\n                    <td>${item.metrics.variance}<\/td>\n                <\/tr>\n            `).join('');\n        }\n\n        \/\/ \u5bfc\u51faCSV\n        function exportCSV() {\n            if (analysisHistory.length === 0) {\n                alert('\u6682\u65e0\u6570\u636e\u53ef\u5bfc\u51fa');\n                return;\n            }\n            \n            let csv = '\\uFEFF\u56fe\u7247\u540d\u79f0,\u7efc\u5408\u8bc4\u5206,\u9999\u519c\u71b5,\u8fb9\u7f18\u5bc6\u5ea6,\u65b9\u5dee,\u7eb9\u7406\u5206\u6570,\u989c\u8272\u79cd\u7c7b,\u989c\u8272\u591a\u6837\u6027,\u5bf9\u6bd4\u5ea6,\u4eae\u5ea6,\u5206\u6790\u65f6\u95f4\\n';\n            analysisHistory.forEach(item => {\n                csv += `${item.fileName},${item.metrics.totalScore},${item.metrics.entropy},${item.metrics.edgeDensity}%,${item.metrics.variance},${item.metrics.textureScore},${item.metrics.colorCount},${item.metrics.colorDiversity},${item.metrics.contrast},${item.metrics.brightness},${item.time}\\n`;\n            });\n            \n            downloadFile(csv, 'visual_complexity_analysis.csv', 'text\/csv;charset=utf-8;');\n        }\n\n        \/\/ \u5bfc\u51faJSON\n        function exportJSON() {\n            if (analysisHistory.length === 0) {\n                alert('\u6682\u65e0\u6570\u636e\u53ef\u5bfc\u51fa');\n                return;\n            }\n            \n            const jsonData = {\n                exportTime: new Date().toISOString(),\n                totalRecords: analysisHistory.length,\n                records: analysisHistory.map(item => ({\n                    fileName: item.fileName,\n                    thumbnailBase64: item.thumbSrc,\n                    metrics: item.metrics,\n                    timestamp: item.time\n                }))\n            };\n            \n            downloadFile(JSON.stringify(jsonData, null, 2), 'visual_complexity_analysis.json', 'application\/json');\n        }\n\n        \/\/ \u4e0b\u8f7d\u6587\u4ef6\n        function downloadFile(content, filename, mimeType) {\n            const blob = new Blob([content], { type: mimeType });\n            const link = document.createElement('a');\n            link.href = URL.createObjectURL(blob);\n            link.download = filename;\n            link.click();\n            URL.revokeObjectURL(link.href);\n        }\n\n        \/\/ \u91cd\u7f6e\n        function resetAll() {\n            document.getElementById('displayImage').src = '';\n            document.getElementById('previewSection').classList.remove('active');\n            \n            currentFileName = '';\n            currentImageSrc = '';\n            edgeImageSrc = '';\n            grayImageSrc = '';\n            currentMetrics = null;\n            selectionRect = null;\n            \n            disableButtons();\n            \n            \/\/ \u91cd\u7f6e\u8fdb\u5ea6\u6761\n            const scoreBarReset = document.getElementById('scoreBar');\n            if (scoreBarReset) {\n                scoreBarReset.style.width = '0%';\n                scoreBarReset.className = 'score-bar';\n            }\n            charts.radar.data.datasets[0].data = [0, 0, 0, 0, 0, 0];\n            charts.radar.update();\n            charts.histogram.data.datasets[0].data = new Array(256).fill(0);\n            charts.histogram.update();\n            \n            document.getElementById('totalScore').textContent = '0';\n            document.getElementById('scoreLevel').textContent = '\u7b49\u5f85\u5206\u6790';\n            document.getElementById('scoreLevel').className = 'level-badge';\n            \n            ['metricEntropy', 'metricEdge', 'metricVariance', 'metricTexture', 'metricColors', 'metricDiversity', 'metricContrast', 'metricBrightness'].forEach(id => {\n                const el = document.getElementById(id);\n                if (id === 'metricEdge') el.textContent = '0%';\n                else el.textContent = '0';\n            });\n        }\n\n        function enableButtons() {\n            document.getElementById('analyzeBtn').disabled = false;\n            document.getElementById('resetBtn').disabled = false;\n            document.getElementById('exportCsvBtn').disabled = false;\n            document.getElementById('exportJsonBtn').disabled = false;\n        }\n\n        function disableButtons() {\n            document.getElementById('analyzeBtn').disabled = true;\n            document.getElementById('resetBtn').disabled = true;\n            document.getElementById('resetSelectionBtn').disabled = true;\n            document.getElementById('exportCsvBtn').disabled = true;\n            document.getElementById('exportJsonBtn').disabled = true;\n        }\n\n        function showLoading(show) {\n            document.getElementById('loadingOverlay').classList.toggle('active', show);\n        }\n\n        \/\/ \u521d\u59cb\u5316\u56fe\u8868\n        function initCharts() {\n            \/\/ \u8fdb\u5ea6\u6761\u663e\u793a\uff08\u4e0d\u9700\u8981Chart.js\uff09\n\n            \/\/ \u96f7\u8fbe\u56fe\n            const radarCtx = document.getElementById('radarChart').getContext('2d');\n            charts.radar = new Chart(radarCtx, {\n                type: 'radar',\n                data: {\n                    labels: ['\u9999\u519c\u71b5', '\u8fb9\u7f18\u5bc6\u5ea6', '\u65b9\u5dee', '\u7eb9\u7406', '\u989c\u8272\u591a\u6837\u6027', '\u5bf9\u6bd4\u5ea6'],\n                    datasets: [{\n                        data: [0, 0, 0, 0, 0, 0],\n                        backgroundColor: 'rgba(59, 130, 246, 0.2)',\n                        borderColor: '#3b82f6',\n                        borderWidth: 2,\n                        pointBackgroundColor: '#3b82f6'\n                    }]\n                },\n                options: {\n                    scales: {\n                        r: {\n                            beginAtZero: true,\n                            max: 100,\n                            ticks: { display: false },\n                            grid: { color: '#475569' },\n                            angleLines: { color: '#475569' },\n                            pointLabels: { color: '#94a3b8', font: { size: 9 } }\n                        }\n                    },\n                    plugins: { legend: { display: false } }\n                }\n            });\n\n            \/\/ \u7070\u5ea6\u76f4\u65b9\u56fe\n            const histogramCtx = document.getElementById('histogramChart').getContext('2d');\n            charts.histogram = new Chart(histogramCtx, {\n                type: 'bar',\n                data: {\n                    labels: Array.from({length: 256}, (_, i) => i),\n                    datasets: [{\n                        label: '\u7070\u5ea6\u5206\u5e03',\n                        data: new Array(256).fill(0),\n                        backgroundColor: 'rgba(59, 130, 246, 0.6)',\n                        borderColor: '#3b82f6',\n                        borderWidth: 0\n                    }]\n                },\n                options: {\n                    responsive: true,\n                    maintainAspectRatio: false,\n                    plugins: { legend: { display: false } },\n                    scales: {\n                        x: { \n                            display: true,\n                            ticks: { \n                                color: '#94a3b8',\n                                maxTicksLimit: 8,\n                                font: { size: 8 }\n                            },\n                            grid: { display: false }\n                        },\n                        y: { \n                            display: true,\n                            ticks: { \n                                color: '#94a3b8',\n                                maxTicksLimit: 4,\n                                font: { size: 8 }\n                            },\n                            grid: { color: '#334155' }\n                        }\n                    }\n                }\n            });\n        }\n    <\/script>\n<\/body>\n<\/html>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-fe48e5de wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button has-custom-width wp-block-button__width-50 is-style-fill\"><a class=\"wp-block-button__link has-headings-color has-accent-2-background-color has-text-color has-background has-link-color has-normal-font-size has-custom-font-size wp-element-button\" href=\"http:\/\/www.artinfinity.cn\/?p=706\" rel=\"http:\/\/www.artinfinity.cn\/?p=706\">\u91cf\u5316\u5206\u6790\u5de5\u5177\u5f00\u53d1\u8bf4\u660e<\/a><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u753b\u9762\u89c6\u89c9\u7e41\u5bc6\u5ea6\u91cf\u5316\u5206\u6790\u5de5\u5177 V4 \u753b\u9762\u89c6\u89c9\u7e41\u5bc6\u5ea6\u7814 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-651","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/pages\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=651"}],"version-history":[{"count":54,"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/pages\/651\/revisions"}],"predecessor-version":[{"id":749,"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=\/wp\/v2\/pages\/651\/revisions\/749"}],"wp:attachment":[{"href":"http:\/\/www.artinfinity.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}