核心思想
- 需要将图片传至后端,后端返回需要标注的物品的坐标及识别到的名称,此篇坐标为左上角和右下角;
- 使用canvas的绘图功能。在现实的图片上绘制矩形,并调整样式。
实现效果如图:

初始化canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
显示图片
- drawImage接受五个参数:图片、x坐标、y坐标、宽度、高度;
- 图片、x、y为必须参数;
ctx.drawImage(img, 0,0,width,height)
绘制矩形
- strokeStyle :描边矩形颜色;
- rect(x,y,width,height):描边矩形,参数为x坐标、y坐标、宽、高;
- fillStyle:填充颜色;
- fillRect(x,y,width,height):填充矩形,参数为x坐标、y坐标、宽、高。
ctx.strokeStyle = 'red';
ctx.rect(x,y,wid,hei);
ctx.fillStyle = 'red';
ctx.fillRect(x,y-20,ctx.measureText(value.cont).width+20,20);
绘制文字
- font :文字颜色及字体;
- fillText(文字内容,x,y):填充的文字,参数为文字内容、x坐标、y坐标。
ctx.fillStyle = '#fff';
ctx.font = "16px Arial";
ctx.fillText(文字内容,x,y);
后台数据
const resData = {"data":{"success":"1","cont":[{"pos":[220,71,449,682],"cont":"元气森林"},{"pos":[437,72,660,719],"cont":"元气森林"},{"pos":[794,104,979,653],"cont":"元气森林"}]}}
标注框宽高
- 后台返回的坐标数据是根据图片原始大小进行抓取,但是页面显示的图片会进行尺寸缩小,所以要计算标注框在页面上显示的大小。
- img.naturalWidth、img.naturalHeight:图片原始尺寸;
- img.width、img.height:图片显示尺寸;
- 宽缩小比例 = (img.naturalWidth - img.width)/img.width;
- 长缩小比例 = (img.naturalHeight - img.height)/img.height;
- 实际计算标注框的尺寸 = 实际尺寸 * 缩小比例;
标注框部分完整代码
const img = document.getElementById('img');
const canvas = document.getElementById('canvas');
// 调整画布大小
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
// 根据数据循环生成标注框
if(resData.data.cont.length > 0){
ctx.strokeStyle = 'red';
// 画布上显示图片
ctx.drawImage(img, 0,0,img.width,img.height);
// 计算缩小比率
const widthrat = (img.naturalWidth - img.width)/img.width;
const heightrat = (img.naturalHeight - img.height)/img.height;
resData.data.cont.forEach(value => {
// 获取标注框的x、y坐标
const x = value.pos[0]*widthrat;
const y = value.pos[1]*heightrat;
// 获取标注框的宽、高
const wid = (value.pos[2]-value.pos[0])*widthrat;
const hei = (value.pos[3]-value.pos[1])*heightrat;
// 根据获取的数据绘制描边矩形
ctx.rect(x,y,wid,hei);
// 绘制描边矩形上的红色填充矩形,并稍微调整样式
ctx.fillStyle = 'red';
ctx.fillRect(x,y-20,ctx.measureText(value.cont).width+20,20);
// 绘制填充矩形上的白色文字,并调整坐标
ctx.fillStyle = '#fff';
ctx.font = "16px Arial";
ctx.fillText(value.cont,x+10,y-4);
})
ctx.stroke()
}else{
ctx.fillStyle = '#000';
ctx.fillText('图片中无饮料。',10,10);
}
<img id='img' src={flieData}></img>
<canvas id='canvas' ></canvas>