标签搜索

抠图功能

wehg489
2025-06-23 / 0 评论 / 3 阅读 / 正在检测是否收录...
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能抠图工具 - 一键去除背景</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            min-height: 100vh;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            color: white;
        }
        
        .container {
            width: 100%;
            max-width: 1200px;
            padding: 20px;
        }
        
        header {
            text-align: center;
            margin-bottom: 30px;
            padding: 20px;
            animation: fadeIn 1s ease;
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.2);
        }
        
        .subtitle {
            font-size: 1.2rem;
            opacity: 0.9;
            max-width: 600px;
            margin: 0 auto;
        }
        
        .app-container {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
        }
        
        .upload-section {
            flex: 1;
            min-width: 300px;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        .preview-section {
            flex: 1;
            min-width: 300px;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        .section-title {
            font-size: 1.3rem;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .section-title i {
            font-size: 1.5rem;
        }
        
        .drop-area {
            border: 3px dashed rgba(255, 255, 255, 0.5);
            border-radius: 15px;
            padding: 40px 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            background: rgba(255, 255, 255, 0.05);
        }
        
        .drop-area:hover, .drop-area.active {
            border-color: #fff;
            background: rgba(255, 255, 255, 0.1);
        }
        
        .drop-area i {
            font-size: 3rem;
            margin-bottom: 15px;
            color: rgba(255, 255, 255, 0.7);
        }
        
        .drop-area p {
            margin: 10px 0;
        }
        
        .file-input {
            display: none;
        }
        
        .btn {
            background: linear-gradient(45deg, #ff8a00, #ff2070);
            color: white;
            border: none;
            padding: 12px 25px;
            font-size: 1rem;
            border-radius: 50px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: 600;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            box-shadow: 0 4px 15px rgba(255, 138, 0, 0.3);
        }
        
        .btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 7px 20px rgba(255, 138, 0, 0.4);
        }
        
        .btn:active {
            transform: translateY(0);
        }
        
        .btn-outline {
            background: transparent;
            border: 2px solid rgba(255, 255, 255, 0.5);
            box-shadow: none;
        }
        
        .btn-outline:hover {
            background: rgba(255, 255, 255, 0.1);
        }
        
        .preview-container {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        .preview-box {
            position: relative;
            width: 100%;
            height: 250px;
            border-radius: 15px;
            overflow: hidden;
            background: rgba(0, 0, 0, 0.2);
            display: flex;
            align-items: center;
            justify-content: center;
            border: 2px solid rgba(255, 255, 255, 0.1);
        }
        
        .preview-box img, .preview-box canvas {
            max-width: 100%;
            max-height: 100%;
            display: none;
        }
        
        .preview-placeholder {
            text-align: center;
            color: rgba(255, 255, 255, 0.5);
        }
        
        .controls {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
        }
        
        .tolerance-control {
            flex: 1;
            min-width: 200px;
        }
        
        .tolerance-label {
            display: flex;
            justify-content: space-between;
            margin-bottom: 8px;
        }
        
        .slider {
            width: 100%;
            height: 10px;
            -webkit-appearance: none;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 5px;
            outline: none;
        }
        
        .slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #ff8a00;
            cursor: pointer;
        }
        
        .tolerance-value {
            background: rgba(255, 255, 255, 0.1);
            padding: 2px 10px;
            border-radius: 10px;
            min-width: 40px;
            text-align: center;
        }
        
        .result-actions {
            display: flex;
            gap: 15px;
            margin-top: 10px;
        }
        
        .info-box {
            background: rgba(0, 0, 0, 0.2);
            border-radius: 15px;
            padding: 20px;
            margin-top: 30px;
            font-size: 0.9rem;
        }
        
        .info-box h3 {
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .info-content {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
        }
        
        .info-item {
            flex: 1;
            min-width: 250px;
        }
        
        .info-item ul {
            padding-left: 20px;
            margin-top: 10px;
        }
        
        .info-item li {
            margin-bottom: 8px;
        }
        
        footer {
            text-align: center;
            margin-top: 40px;
            padding: 20px;
            color: rgba(255, 255, 255, 0.7);
            font-size: 0.9rem;
        }
        
        .loading {
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 10;
            border-radius: 15px;
        }
        
        .spinner {
            width: 50px;
            height: 50px;
            border: 5px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top: 5px solid #ff8a00;
            animation: spin 1s linear infinite;
            margin-bottom: 15px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(-20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        .featured-examples {
            display: flex;
            gap: 20px;
            margin-top: 15px;
            justify-content: center;
            flex-wrap: wrap;
        }
        
        .example-item {
            width: 80px;
            height: 80px;
            border-radius: 10px;
            overflow: hidden;
            cursor: pointer;
            border: 2px solid rgba(255, 255, 255, 0.3);
            transition: all 0.3s ease;
        }
        
        .example-item:hover {
            transform: scale(1.05);
            border-color: white;
        }
        
        .example-item img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        @media (max-width: 768px) {
            .app-container {
                flex-direction: column;
            }
            
            .controls {
                flex-direction: column;
            }
            
            h1 {
                font-size: 2rem;
            }
        }
    </style>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
</head>
<body>
    <div class="container">
        <header>
            <h1><i class="fas fa-magic"></i> 智能抠图工具</h1>
            <p class="subtitle">上传图片,一键自动去除背景 - 无需复杂操作,快速获得透明背景PNG图片</p>
        </header>
        
        <div class="app-container">
            <div class="upload-section">
                <h2 class="section-title"><i class="fas fa-upload"></i> 上传图片</h2>
                <div class="drop-area" id="dropArea">
                    <i class="fas fa-cloud-upload-alt"></i>
                    <p>拖放图片到此处或</p>
                    <button class="btn" id="browseBtn"><i class="fas fa-folder-open"></i> 选择图片</button>
                    <p class="small">支持 JPG, PNG 格式,最大 5MB</p>
                </div>
                <input type="file" id="fileInput" class="file-input" accept="image/*">
                
                <div class="featured-examples">
                    <div class="example-item" data-example="1">
                        <img src="https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="示例1">
                    </div>
                    <div class="example-item" data-example="2">
                        <img src="https://images.unsplash.com/photo-1543852786-1cf6624b9987?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="示例2">
                    </div>
                    <div class="example-item" data-example="3">
                        <img src="https://images.unsplash.com/photo-1533738363-b7f9aef128ce?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="示例3">
                    </div>
                    <div class="example-item" data-example="4">
                        <img src="https://images.unsplash.com/photo-1526336024174-e58f5cdd8e13?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80" alt="示例4">
                    </div>
                </div>
            </div>
            
            <div class="preview-section">
                <h2 class="section-title"><i class="fas fa-image"></i> 预览结果</h2>
                <div class="preview-container">
                    <div class="preview-box">
                        <div class="preview-placeholder">
                            <i class="fas fa-image" style="font-size: 3rem; margin-bottom: 15px;"></i>
                            <p>处理后的图像将显示在这里</p>
                        </div>
                        <canvas id="originalCanvas"></canvas>
                        <canvas id="resultCanvas"></canvas>
                        <div class="loading" id="loading">
                            <div class="spinner"></div>
                            <p>正在处理图像...</p>
                        </div>
                    </div>
                    
                    <div class="controls">
                        <div class="tolerance-control">
                            <div class="tolerance-label">
                                <span>抠图精度调节:</span>
                                <span class="tolerance-value" id="toleranceValue">30</span>
                            </div>
                            <input type="range" min="1" max="100" value="30" class="slider" id="toleranceSlider">
                            <p style="font-size: 0.8rem; margin-top: 5px; opacity: 0.7;">值越小,抠图越精细(处理时间越长)</p>
                        </div>
                        <button class="btn" id="processBtn"><i class="fas fa-cogs"></i> 开始抠图</button>
                    </div>
                    
                    <div class="result-actions">
                        <button class="btn" id="downloadBtn" disabled><i class="fas fa-download"></i> 下载结果</button>
                        <button class="btn btn-outline" id="resetBtn"><i class="fas fa-redo"></i> 重置</button>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="info-box">
            <h3><i class="fas fa-info-circle"></i> 使用说明</h3>
            <div class="info-content">
                <div class="info-item">
                    <h4>如何获得最佳效果:</h4>
                    <ul>
                        <li>选择主体与背景对比度高的图片</li>
                        <li>避免复杂背景或毛发等细节丰富的图像</li>
                        <li>如果效果不理想,尝试调整抠图精度</li>
                        <li>对于人像照片效果最佳</li>
                    </ul>
                </div>
                <div class="info-item">
                    <h4>技术说明:</h4>
                    <ul>
                        <li>使用HTML5 Canvas实现纯前端处理</li>
                        <li>基于智能颜色识别算法</li>
                        <li>处理时间取决于图像大小和复杂度</li>
                        <li>完全在浏览器中运行 - 不上传服务器</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    
    <footer>
        <p>© 2023 智能抠图工具 | 纯前端实现 | 无需上传服务器 | 保护您的隐私</p>
    </footer>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 获取DOM元素
            const dropArea = document.getElementById('dropArea');
            const fileInput = document.getElementById('fileInput');
            const browseBtn = document.getElementById('browseBtn');
            const processBtn = document.getElementById('processBtn');
            const downloadBtn = document.getElementById('downloadBtn');
            const resetBtn = document.getElementById('resetBtn');
            const toleranceSlider = document.getElementById('toleranceSlider');
            const toleranceValue = document.getElementById('toleranceValue');
            const originalCanvas = document.getElementById('originalCanvas');
            const resultCanvas = document.getElementById('resultCanvas');
            const loading = document.getElementById('loading');
            const previewPlaceholder = document.querySelector('.preview-placeholder');
            
            let originalImage = null;
            let processedImage = null;
            
            // 设置事件监听器
            browseBtn.addEventListener('click', () => fileInput.click());
            fileInput.addEventListener('change', handleFileSelect);
            dropArea.addEventListener('dragover', handleDragOver);
            dropArea.addEventListener('dragleave', handleDragLeave);
            dropArea.addEventListener('drop', handleDrop);
            processBtn.addEventListener('click', processImage);
            downloadBtn.addEventListener('click', downloadResult);
            resetBtn.addEventListener('click', resetApp);
            toleranceSlider.addEventListener('input', updateTolerance);
            
            // 示例图片点击事件
            document.querySelectorAll('.example-item').forEach(item => {
                item.addEventListener('click', function() {
                    const exampleNum = this.getAttribute('data-example');
                    loadExample(exampleNum);
                });
            });
            
            // 更新容差值显示
            function updateTolerance() {
                toleranceValue.textContent = toleranceSlider.value;
            }
            
            // 处理文件选择
            function handleFileSelect(e) {
                const file = e.target.files[0];
                if (file && file.type.match('image.*')) {
                    loadImage(file);
                }
            }
            
            // 处理拖放
            function handleDragOver(e) {
                e.preventDefault();
                e.stopPropagation();
                dropArea.classList.add('active');
            }
            
            function handleDragLeave(e) {
                e.preventDefault();
                e.stopPropagation();
                dropArea.classList.remove('active');
            }
            
            function handleDrop(e) {
                e.preventDefault();
                e.stopPropagation();
                dropArea.classList.remove('active');
                
                const file = e.dataTransfer.files[0];
                if (file && file.type.match('image.*')) {
                    loadImage(file);
                }
            }
            
            // 加载图片
            function loadImage(file) {
                const reader = new FileReader();
                
                reader.onload = function(e) {
                    originalImage = new Image();
                    originalImage.onload = function() {
                        // 显示原始图片
                        displayOriginalImage();
                        processBtn.disabled = false;
                    };
                    originalImage.src = e.target.result;
                };
                
                reader.readAsDataURL(file);
            }
            
            // 加载示例图片
            function loadExample(num) {
                const examples = {
                    '1': 'https://images.unsplash.com/photo-1518791841217-8f162f1e1131?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80',
                    '2': 'https://images.unsplash.com/photo-1543852786-1cf6624b9987?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80',
                    '3': 'https://images.unsplash.com/photo-1533738363-b7f9aef128ce?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80',
                    '4': 'https://images.unsplash.com/photo-1526336024174-e58f5cdd8e13?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80'
                };
                
                originalImage = new Image();
                originalImage.crossOrigin = "Anonymous";
                originalImage.onload = function() {
                    displayOriginalImage();
                    processBtn.disabled = false;
                };
                originalImage.src = examples[num];
            }
            
            // 显示原始图片
            function displayOriginalImage() {
                const previewBox = document.querySelector('.preview-box');
                previewPlaceholder.style.display = 'none';
                
                // 设置canvas尺寸
                const maxWidth = previewBox.clientWidth - 20;
                const maxHeight = previewBox.clientHeight - 20;
                
                let width = originalImage.width;
                let height = originalImage.height;
                
                if (width > maxWidth) {
                    height = (maxWidth / width) * height;
                    width = maxWidth;
                }
                
                if (height > maxHeight) {
                    width = (maxHeight / height) * width;
                    height = maxHeight;
                }
                
                originalCanvas.width = width;
                originalCanvas.height = height;
                resultCanvas.width = width;
                resultCanvas.height = height;
                
                const ctx = originalCanvas.getContext('2d');
                ctx.clearRect(0, 0, width, height);
                ctx.drawImage(originalImage, 0, 0, width, height);
                
                originalCanvas.style.display = 'block';
            }
            
            // 处理图像(抠图)
            function processImage() {
                if (!originalImage) return;
                
                // 显示加载状态
                loading.style.display = 'flex';
                downloadBtn.disabled = true;
                
                // 使用setTimeout让UI有机会更新
                setTimeout(() => {
                    try {
                        const tolerance = parseInt(toleranceSlider.value);
                        removeBackground(tolerance);
                        
                        // 显示结果
                        originalCanvas.style.display = 'none';
                        resultCanvas.style.display = 'block';
                        downloadBtn.disabled = false;
                    } catch (error) {
                        console.error('Error processing image:', error);
                        alert('处理图像时出错: ' + error.message);
                    } finally {
                        loading.style.display = 'none';
                    }
                }, 100);
            }
            
            // 移除背景的核心算法
            function removeBackground(tolerance) {
                const ctx = originalCanvas.getContext('2d');
                const resultCtx = resultCanvas.getContext('2d');
                
                // 获取图像数据
                const imageData = ctx.getImageData(0, 0, originalCanvas.width, originalCanvas.height);
                const data = imageData.data;
                
                // 创建新图像数据(带透明通道)
                const newData = new ImageData(originalCanvas.width, originalCanvas.height);
                const newPixels = newData.data;
                
                // 假设图片中心点属于前景
                const centerX = Math.floor(originalCanvas.width / 2);
                const centerY = Math.floor(originalCanvas.height / 2);
                const centerIndex = (centerY * originalCanvas.width + centerX) * 4;
                
                // 获取中心点颜色作为前景参考
                const centerR = data[centerIndex];
                const centerG = data[centerIndex + 1];
                const centerB = data[centerIndex + 2];
                
                // 处理每个像素
                for (let i = 0; i < data.length; i += 4) {
                    const r = data[i];
                    const g = data[i + 1];
                    const b = data[i + 2];
                    
                    // 计算与中心点的颜色差异
                    const diff = Math.sqrt(
                        Math.pow(r - centerR, 2) +
                        Math.pow(g - centerG, 2) +
                        Math.pow(b - centerB, 2)
                    );
                    
                    // 如果颜色差异在容差范围内,保留像素,否则设为透明
                    if (diff < tolerance) {
                        newPixels[i] = r;
                        newPixels[i + 1] = g;
                        newPixels[i + 2] = b;
                        newPixels[i + 3] = 255; // 不透明
                    } else {
                        newPixels[i] = 0;
                        newPixels[i + 1] = 0;
                        newPixels[i + 2] = 0;
                        newPixels[i + 3] = 0; // 完全透明
                    }
                }
                
                // 将新图像数据绘制到结果canvas
                resultCtx.putImageData(newData, 0, 0);
            }
            
            // 下载结果
            function downloadResult() {
                if (!resultCanvas) return;
                
                const link = document.createElement('a');
                link.download = '抠图结果.png';
                link.href = resultCanvas.toDataURL('image/png');
                link.click();
            }
            
            // 重置应用
            function resetApp() {
                // 重置所有状态
                originalImage = null;
                processedImage = null;
                
                // 隐藏canvas
                originalCanvas.style.display = 'none';
                resultCanvas.style.display = 'none';
                
                // 显示占位符
                previewPlaceholder.style.display = 'flex';
                
                // 重置按钮状态
                processBtn.disabled = true;
                downloadBtn.disabled = true;
                
                // 重置文件输入
                fileInput.value = '';
            }
            
            // 初始化
            updateTolerance();
        });
    </script>
</body>
</html>
0

评论

博主关闭了当前页面的评论
歌曲封面
0:00