1、抠图api,每月有50次免费的额度的抠图api可以调用。
https://www.remove.bg/zh/api#get-started


效果一般。不建议使用。
2,通过canvas识别颜色边缘。

3、使用gimp


好一点
4、使用模型处理。rembg:Python 库,可以通过 WebAssembly 在前端使用,推荐使用,就是有点慢,精细化处理需要时间。

<template>
<div class="container">
<div class="upload-section">
<h2>图片上传与 Canvas 显示</h2>
<input type="file" ref="fileInput" @change="handleFileUpload" accept="image/*" class="file-input" />
<button @click="clearCanvas" class="clear-btn">清除画布</button>
</div>
<div class="canvas-container" v-if="showCanvas">
<div class="canvas-wrapper">
<div class="canvas-item">
<div class="canvas-label">原图</div>
<canvas ref="canvas" class="image-canvas"></canvas>
</div>
<div class="canvas-item" v-if="showResult">
<div class="canvas-label">处理后</div>
<canvas ref="resultCanvas" class="result-canvas"></canvas>
</div>
</div>
<div class="controls" v-if="showCanvas">
<button @click="handleRemoveBackground" class="cutout-btn" :disabled="isProcessing">
{{ isProcessing ? (modelLoading ? '加载模型中...' : '处理中...') : '智能抠图' }}
</button>
<button @click="downloadResult" v-if="showResult" class="download-btn">
下载结果
</button>
<button @click="showResult = false" v-if="showResult" class="hide-result-btn">
隐藏结果
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, nextTick, onMounted } from 'vue'
import { removeBackground } from '@imgly/background-removal'
const fileInput = ref(null)
const canvas = ref(null)
const resultCanvas = ref(null)
const showCanvas = ref(false)
const showResult = ref(false)
const isProcessing = ref(false)
const modelLoading = ref(false)
const handleFileUpload = (event) => {
const file = event.target.files[0]
if (!file) return
// 先显示 canvas 容器
showCanvas.value = true
// 等待 DOM 更新后处理图片
nextTick(() => {
const reader = new FileReader()
reader.onload = (e) => {
const img = new Image()
img.onload = () => {
// 确保 canvas 已经渲染
if (canvas.value) {
drawImageToCanvas(img)
}
}
img.onerror = () => {
console.error('图片加载失败')
showCanvas.value = false
}
img.src = e.target.result
}
reader.onerror = () => {
console.error('文件读取失败')
showCanvas.value = false
}
reader.readAsDataURL(file)
})
}
const drawImageToCanvas = (img) => {
if (!canvas.value) {
console.error('Canvas 元素不存在')
return
}
const ctx = canvas.value.getContext('2d')
// 设置画布尺寸
const maxWidth = 800
const maxHeight = 600
let width = img.width
let height = img.height
// 按比例缩放
if (width > maxWidth || height > maxHeight) {
const ratio = Math.min(maxWidth / width, maxHeight / height)
width = width * ratio
height = height * ratio
}
// 设置 canvas 尺寸
canvas.value.width = width
canvas.value.height = height
console.log('Canvas 尺寸:', width, 'x', height)
console.log('图片尺寸:', img.width, 'x', img.height)
// 绘制图片
ctx.drawImage(img, 0, 0, width, height)
console.log('图片已绘制到 Canvas')
}
const clearCanvas = () => {
if (canvas.value) {
const ctx = canvas.value.getContext('2d')
ctx.clearRect(0, 0, canvas.value.width, canvas.value.height)
showCanvas.value = false
showResult.value = false
if (fileInput.value) {
fileInput.value.value = ''
}
}
}
// 智能抠图功能 - 使用 rembg
const handleRemoveBackground = async () => {
if (!canvas.value) return
isProcessing.value = true
modelLoading.value = true
try {
await nextTick()
// 获取原始 canvas 的图像数据
const imageData = canvas.value.toDataURL('image/png')
// 使用 rembg 进行背景移除
const blob = await removeBackground(imageData)
// 创建结果 canvas
showResult.value = true
await nextTick()
if (resultCanvas.value) {
// 将结果显示在 canvas 上
const url = URL.createObjectURL(blob)
const ctx = resultCanvas.value.getContext('2d')
const img = new Image()
img.onload = () => {
resultCanvas.value.width = img.width
resultCanvas.value.height = img.height
ctx.drawImage(img, 0, 0)
URL.revokeObjectURL(url)
}
img.src = url
}
} catch (error) {
console.error('抠图失败:', error)
alert('抠图失败: ' + error.message)
} finally {
isProcessing.value = false
modelLoading.value = false
}
}
// 下载抠图结果
const downloadResult = () => {
if (resultCanvas.value) {
const link = document.createElement('a')
link.download = 'removed_background.png'
link.href = resultCanvas.value.toDataURL('image/png')
link.click()
}
}
</script>
<style scoped>
.container {
text-align: center;
padding: 30px 20px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.upload-section {
margin-top: 50px;
padding: 30px;
background-color: #f5f5f5;
border-radius: 10px;
}
.upload-section h2 {
color: #35495e;
font-size: 24px;
margin-bottom: 20px;
}
.file-input {
margin-right: 10px;
padding: 8px;
border: 2px solid #42b883;
border-radius: 4px;
background-color: white;
}
button {
padding: 12px 24px;
background-color: #42b883;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #3aa876;
}
.clear-btn {
background-color: #ff6b6b;
margin-left: 10px;
margin-top: 0;
}
.clear-btn:hover {
background-color: #ff5252;
}
.canvas-container {
margin-top: 30px;
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
.canvas-wrapper {
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
width: 100%;
max-width: 1400px;
}
.canvas-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.canvas-label {
font-size: 18px;
font-weight: bold;
color: #35495e;
margin-bottom: 5px;
}
.image-canvas,
.result-canvas {
border: 3px solid #42b883;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
max-width: 600px;
max-height: 500px;
width: auto;
height: auto;
object-fit: contain;
}
.result-canvas {
border-color: #ff6b6b;
background: linear-gradient(45deg, #ccc 25%, transparent 25%),
linear-gradient(-45deg, #ccc 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #ccc 75%),
linear-gradient(-45deg, transparent 75%, #ccc 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
}
.controls {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.cutout-btn {
background-color: #9c27b0;
}
.cutout-btn:hover {
background-color: #7b1fa2;
}
.cutout-btn:disabled {
background-color: #bdbdbd;
cursor: not-allowed;
}
.download-btn {
background-color: #2196f3;
}
.download-btn:hover {
background-color: #1976d2;
}
.hide-result-btn {
background-color: #ff9800;
}
.hide-result-btn:hover {
background-color: #f57c00;
}
</style>