如何通过js(javascript)实现图像标注

AI解读 4小时前 硕雀
2 0

一、思路概述

  1. 页面准备:在页面中放置一张图片(<img>)或直接使用 <canvas> 作为绘图层。
  2. 捕获点击坐标:监听鼠标点击事件,利用 event.clientX/Y 与图片/画布的 getBoundingClientRect() 计算出相对于图片左上角的坐标。
  3. 绘制标注:在 Canvas 上绘制形状(圆点、矩形等)并使用 fillText 写入文字,或使用封装好的库(如 Fabric.jsKonva.js)创建可拖拽、可编辑的对象。
  4. 保存数据:把每个标注的坐标、尺寸、文本等信息保存到数组或发送到后端,以便后续查询或持久化。

二、实现方式示例

1️⃣ 纯 Canvas(原生 JS)

<div style="position:relative; display:inline-block;">
    <img id="srcImg" src="your-image.jpg" style="max-width:100%;">
    <canvas id="annoCanvas" style="position:absolute; left:0; top:0;"></canvas>
</div>

<script>
const img   = document.getElementById('srcImg');
const canvas = document.getElementById('annoCanvas');
const ctx   = canvas.getContext('2d');
const marks = [];   // 保存标注信息

// 当图片加载完成后,设置 canvas 大小与图片一致
img.onload = () => {
    canvas.width  = img.width;
    canvas.height = img.height;
};

// 点击获取坐标并弹出输入框填写标注文字
canvas.addEventListener('click', e => {
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;   // 相对图片左上角的 X
    const y = e.clientY - rect.top;    // 相对图片左上角的 Y

    const text = prompt('请输入标注文字:');
    if (!text) return;

    // 绘制圆点
    ctx.beginPath();
    ctx.arc(x, y, 5, 0, Math.PI * 2);
    ctx.fillStyle = 'red';
    ctx.fill();

    // 绘制文字(稍微偏移避免遮挡)
    ctx.font = '14px sans-serif';
    ctx.fillStyle = 'blue';
    ctx.fillText(text, x + 8, y - 8);

    // 保存数据
    marks.push({x, y, text});
});
</script>

关键点

  • getBoundingClientRect() 用于把页面坐标转换为图片内部坐标。
  • canvas 采用绝对定位覆盖在图片上,实现“在图上标注”。

2️⃣ 使用 Fabric.js(更强的交互)

<link  href="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script>

<canvas id="fabricCanvas" width="800" height="600"></canvas>

<script>
const canvas = new fabric.Canvas('fabricCanvas');
const marks = [];

// 加载背景图片
fabric.Image.fromURL('your-image.jpg', img => {
    canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
        scaleX: canvas.width / img.width,
        scaleY: canvas.height / img.height
    });
});

// 点击添加标注
canvas.on('mouse:down', opt => {
    const pointer = canvas.getPointer(opt.e);
    const text = prompt('请输入标注文字:');
    if (!text) return;

    // 圆点
    const circle = new fabric.Circle({
        left: pointer.x,
        top:  pointer.y,
        radius: 5,
        fill: 'red',
        originX: 'center',
        originY: 'center',
        selectable: false
    });

    // 文字
    const txt = new fabric.Text(text, {
        left: pointer.x + 8,
        top:  pointer.y - 8,
        fontSize: 14,
        fill: 'blue',
        selectable: false
    });

    canvas.add(circle, txt);
    canvas.renderAll();

    marks.push({x: pointer.x, y: pointer.y, text});
});
</script>

关键点

  • Fabric.js 把 Canvas 抽象为对象模型,fabric.Circlefabric.Text 可直接创建并添加到画布。
  • canvas.getPointer() 自动把鼠标事件转为画布坐标,省去手动计算。

3️⃣ 数据持久化(示例)

// 将标注信息转成 JSON,发送到后端
function uploadMarks() {
    fetch('/api/saveMarks', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(marks)
    }).then(r => r.json()).then(res => console.log('保存成功', res));
}

只要把 marks 数组(每条记录包含 x、y、text)发送即可,后端可自行存库或写文件。


三、常见需求的扩展

需求 推荐实现方式 关键代码/思路
矩形/多边形标注 Fabric.js 的 fabric.Rectfabric.Polygon new fabric.Rect({ left, top, width, height, stroke:'red', fill:'rgba(0,0,0,0)' })
标注可编辑(拖拽、缩放) 将对象 selectable:true,开启 canvas.selection = true canvas.setActiveObject(obj);
放大/缩小图片 调整 canvas.setZoom(scale) 或修改背景图 scaleX/scaleY canvas.setZoom(1.5);
导出标注结果 canvas.toJSON() 或自行遍历 marks 数组 const json = canvas.toJSON();
移动端触摸支持 Fabric.js 已内置 touch 事件,或在原生 Canvas 中监听 touchstart canvas.addEventListener('touchstart', …)

四、完整示例(可直接拷贝运行)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>JS 图像标注示例</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script>
<style>
  #wrapper{position:relative;display:inline-block;}
  canvas{border:1px solid #ccc;}
</style>
</head>
<body>
<div id="wrapper">
    <canvas id="cvs" width="800" height="600"></canvas>
</div>

<script>
const canvas = new fabric.Canvas('cvs');
const marks = [];

// 背景图
fabric.Image.fromURL('https://picsum.photos/800/600', img=>{
    canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
        scaleX: canvas.width / img.width,
        scaleY: canvas.height / img.height
    });
});

// 添加标注
canvas.on('mouse:down', e=>{
    const p = canvas.getPointer(e.e);
    const txt = prompt('标注文字:');
    if(!txt) return;

    const dot = new fabric.Circle({
        left:p.x, top:p.y, radius:5, fill:'red',
        originX:'center', originY:'center', selectable:false
    });
    const label = new fabric.Text(txt,{
        left:p.x+8, top:p.y-8, fontSize:14,
        fill:'blue', selectable:false
    });
    canvas.add(dot, label);
    marks.push({x:p.x, y:p.y, text:txt});
});

// 保存按钮(可自行添加 UI)
function save(){
    console.log('标注数据', marks);
    // 示例:发送到后端
    // fetch('/save', {method:'POST',body:JSON.stringify(marks)});
}
</script>
</body>
</html>

运行后,点击图片即可弹出输入框,输入文字后会在点击位置出现红点和蓝色文字,所有标注信息保存在 marks 数组中。


五、总结

  • 获取坐标event.clientX/Y + element.getBoundingClientRect()(原生)或 canvas.getPointer()(Fabric.js)。
  • 绘制标注:Canvas APIarcfillText)或库提供的对象(fabric.Circlefabric.Text)。
  • 保存/导出:把坐标 + 文本保存为 JSON,或使用库的 toJSON() 方法。
  • 推荐库:Fabric.js(功能完整、易上手)或 Konva.js(React/Vue 生态友好),均可实现拖拽、缩放、编辑等高级交互。

通过上述步骤,你即可在网页中实现图像标注、实时获取坐标并记录对应的文本信息。祝开发顺利!

来源:www.aiug.cn
声明:文章均为AI生成,请谨慎辨别信息的真伪和可靠性!