网站搜索

javascript - 在图像上显示和选择边界框


给定边界框的坐标和一张图像,我希望在 Angular 网络应用程序中在图像上显示可点击的边界框。

目标是用户应该选择一个或多个绘制在图像上的边界框以进行标注。

到目前为止,我只在 HTML Canvas 上见过可绘制的边界框。然而,在我的情况下,多个边界框已经存在。我该如何处理这个任务?

编辑:我尝试过将两个画布元素叠加在一起,但我甚至无法显示图像,更不用说让矩形出现了。

https://stackblitz.com/edit/angular-bvnjc3

component.html:

<div style="position: relative;">
 <canvas #layer1 id="layer1" width={{imgWidth}} height={{imgHeight}} 
   style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
 <canvas #layer2 id="layer2" width={{imgWidth}} height={{imgHeight}}
   style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>

component.ts:

export class AppComponent {

  public imgWidth: number;
  public imgHeight: number;
  public url: string;
  public image;

  @ViewChild("layer1", { static: false }) layer1Canvas: ElementRef;
  private context: CanvasRenderingContext2D;
  private layer1CanvasElement: any;

  onSelectFile(event) {
    if (event.target.files && event.target.files[0]) {
      var reader = new FileReader();

      reader.readAsDataURL(event.target.files[0]);

      reader.onload = event => {
        this.image = new Image();
        this.image.src = reader.result;
        this.image.onload = () => {
          this.imgWidth = this.image.width;
          this.imgHeight = this.image.height;
          this.showImage();
        };
      };
    }
  }

  showImage() {
    this.layer1CanvasElement = this.layer1Canvas.nativeElement;
    this.context = this.layer1CanvasElement.getContext("2d");
    this.context.drawImage(this.image, this.imgWidth, this.imgHeight);
    this.drawRect();
  }

  drawRect() {
    this.context.beginPath();
    this.context.rect(200, 300, 400, 500);
    this.context.lineWidth = 10;
    this.context.strokeStyle = "black";
    this.context.stroke();
  }
}

答案#1

Stackblitz 链接

https://stackblitz.com/edit/angular-lg4lmy

预览

步骤01

  • 移除

    width={{imgWidth}} height={{imgHeight}}
    

步骤 02

  • 添加

    this.layer1CanvasElement.width = this.imgWidth;
    this.layer1CanvasElement.height = this.imgHeight;
    

步骤03

  • 改变来自

    this.context.drawImage(this.image,this.imgWidth, this.imgHeight);
    
  • 到

    this.context.drawImage(this.image, 0, 0, this.imgWidth, this.imgHeight);
    

步骤 04

  • 添加 mousemove 事件监听器

    this.layer1CanvasElement.addEventListener("mousemove", function(e) {})
    

步骤05

  • 确定 点 是否

      (PointX,PointY) 
    
  • 属于 矩形

      (RectangleX,RectangleY,RectangleWidth,RectangleHeight)
    
  • 通过使用

      (RectangleX <=       PointX       <= RectangleX + RectangleWidth)
      (RectangleY <=       PointY       <= RectangleY + RectangleHeight)
    
  • 代码

      let x = 200;
      let y = 300;
      let w = 400;
      let h = 500;
    
      if ( 
           x <= e.clientX && e.clientX <= x + w 
                            &&
           y <= e.clientY && e.clientY <= y + h  
         )
         drawRect("red");
         else 
         drawRect("black");
    });
    

为什么是步骤01和02

  • 不确定,但我认为它喜欢 Angular 的变更检测

为什么是步骤03

  • 基于 CanvasRenderingContext2D.drawImage() - Web APIs | MDN,你误用了重载

    void ctx.drawImage(image, dx, dy);

    void ctx.drawImage(image, dx, dy, dWidth, dHeight);

    void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

为什么是步骤04和05

  • 据我理解,你需要实现这个功能

    我想显示可点击的边界框

参考。重要

HTMLCanvasElement.getContext() - Web API | MDN

CanvasRenderingContext2D.drawImage() - Web API | MDN

可点击画布圆

HTML5 Canvas 的命中区域检测以及如何监听画布形状的点击事件

MouseEvent.clientX - Web APIs | MDN

参考。不重要

getContext("2d");+ - 谷歌搜索

my_canvas.getContext("2d"); 是什么以及它如何工作? | Codecademy

从控制台访问 Angular 应用 - Google 搜索

在浏览器控制台调试 Angular - 由 Munsters 制作 - Medium

js 从 FileReader 获取图像尺寸 - 谷歌搜索

javascript - 使用 filereader 获取图片的宽度和高度 - Stack Overflow

jquery - 使用 JavaScript 获取图像的真实宽度和高度?(在 Safari/Chrome 中)- Stack Overflow

onload 图像角度器 - Google 搜索

image.onload - 过时内容档案 | MDN

angular - 在 img 标签中检测图像何时加载 - Stack Overflow

angluer this.context.drawImage - 谷歌搜索

typescript - Angular 5 使用 Canvas drawImage 不显示 - Stack Overflow

javascript - CanvasContext2D drawImage() 问题 [onload 和 CORS] - Stack Overflow

addeventlistener 定义文件 typescript - 谷歌搜索

javascript - 将 window.event 处理程序添加到 typescript - Stack Overflow

clientX - 谷歌搜索

is poin 属于 sqrae - 谷歌搜索

解析几何 - 如何检查一个点是否在矩形内? - 数学 Stack Exchange

平面(几何)- 维基百科

angular - 运算符 '>' 不能应用于类型 'boolean' 和 'number'? - Stack Overflow

stroke() - 谷歌搜索

HTML canvas 的 stroke() 方法

画布在悬停时更改路径颜色 - 谷歌搜索

javascript - 当鼠标悬停时更改画布中的颜色线条 - Stack Overflow

答案#2

你可以使用一个名为 Annotorious 的工具。我曾在 Angular 8 中使用它来标注图像。该工具采用 BSD 许可证授权。使用起来相当简单。如果你愿意,你可以下载源代码并编辑小部件。完全是一个很棒的工具。Annotorious 工具