基于华为云自定义模板的图片操作演示(框选、拖拽)

掘金链接
华为云自定义模板识别是服务于AI领域的流程控制系统,我们一起了解下其中一个模块的界面化操作实例。如下图,针对图片的高精度识别,我们需要处理图片的样式以便获得更好的模型训练数据和高精度识别结果。我们针对三个场景来实现图片处理需求:
image.png
在初始化模板的时候,可视化区域内加载图片并呈现出来:

1. 图片的拖拽移动

image.png

  /**
   * 拖拽图片:
   * @param e
   * @returns
   */
  public dragImage(e) {
    e.stopPropagation();     // 阻止事件冒泡
    this.editImgWrapper = this.el.nativeElement.querySelector('#editImgWrapper');// 取图片信息
    let isDraging = false;   // 拖动的标志
    let nodePositon = {      // 当前图片在可视区域内的坐标位置
      left: parseFloat(this.editImgWrapper.style.left.replace('px', '')),
      top: parseFloat(this.editImgWrapper.style.top.replace('px', '')),
    };
    this.deafultPosition = {     // 滑动的时候鼠标在可视窗口的坐标(纯数字)
      left: e.clientX,
      top: e.clientY,
    };
    let movePosition = {
      left: 0,
      top: 0,
    };
    document.onmousedown = e => {
       isDraging = true;
    }
    // move事件
    document.onmousemove = e => {
      if(!isDraging) return;
      e.stopPropagation();
      movePosition.left = e.clientX - this.deafultPosition.left;
      movePosition.top = e.clientY - this.deafultPosition.top;
      this.editImgWrapper.style.left = nodePositon.left + movePosition.left + 'px';
      this.editImgWrapper.style.top = nodePositon.top + movePosition.top + 'px';
    };
    // 鼠标放开
    document.onmouseup = function (event) {
      // 释放事件
      isDraging = false;
      event.stopPropagation();
      document.onmousemove = null;
      document.onmouseup = null;
    };
  }

2. 图片某区域的框选

image.png

  private toDrawImage = e => {
    // 标注框相对图片的位置
    let nodePositon = {
      left: e.pageX - this.editImgWrapper.getBoundingClientRect().left,
      top: e.pageY - this.editImgWrapper.getBoundingClientRect().top,
    };
    // 鼠标按下时的位置
    let mousePosition = {
      left: e.clientX,
      top: e.clientY,
    };
    // 鼠标移动的距离
    let movePosition = {
      left: 0,
      top: 0,
    };
    // 初始化tmp标注框的位置和宽高
    let tmpDivStyles = {
      top: '',
      left: '',
      width: '',
      height: '',
    };
    // 最终生成的标注框宽和高的数值
    let width;
    let height;
    // 文档流添加鼠标 move 事件:
    document.onmousemove = e => {
      e.stopPropagation();
      movePosition.left = (e.clientX - mousePosition.left) / this.editImgWrapper.scaleRatio;
      movePosition.top = (e.clientY - mousePosition.top) / this.editImgWrapper.scaleRatio;
      width = Math.abs(movePosition.left);
      height = Math.abs(movePosition.top);
      if (e.clientY > mousePosition.top) {
        tmpDivStyles.top = nodePositon.top / this.editImgWrapper.scaleRatio + 'px';
      } else {
        tmpDivStyles.top =
          (e.clientY - this.editImgWrapper.getBoundingClientRect().top) / this.editImgWrapper.scaleRatio + 'px';
      }
      if (e.clientX < mousePosition.left) {
        tmpDivStyles.left =
          (e.clientX - this.editImgWrapper.getBoundingClientRect().left) / this.editImgWrapper.scaleRatio + 'px';
      } else {
        tmpDivStyles.left = nodePositon.left / this.editImgWrapper.scaleRatio + 'px';
      }
      tmpDivStyles.width = width + 'px';
      tmpDivStyles.height = height + 'px';
      this.tmpDivStyles = tmpDivStyles;         // 记录框选的样式大小和位置区域
    };

    document.onmouseup = event => {
      // 释放事件
      event.stopPropagation();
      document.onmousemove = null;
      document.onmouseup = null;
      this.addClip();              // 图片绘制
    };
  };
  // 截取框选区域的图片,并调用高精度识别出图片内容,并回显框选区域
  private addClip = () => {
    let tmpStyles = this.tmpDivStyles;
    let position = {
      top: parseFloat(tmpStyles.top.replace('px', '')),
      left: parseFloat(tmpStyles.left.replace('px', '')),
      height: parseFloat(tmpStyles.height.replace('px', '')),
      width: parseFloat(tmpStyles.width.replace('px', '')),
    };
    let list = [];
    //  此处使用生成的64位图片对象
    let image = this.generateImg(position, this.editImgObj, this.editImgCanvas);
    let res: any = await this.service.generalOcr(image, true);   // 调用高精度识别接口
    // 进一步处理回显的框选区域:
    ......
    }
  };
  // 根据坐标和宽高生成图片
  private generateImg(position, imgobj, canvasObj) {
    canvasObj.width = position.width;
    canvasObj.height = position.height;
    let ctx = canvasObj.getContext('2d');
    ctx.drawImage(
      imgobj,
      position.left,
      position.top,
      position.width,
      position.height,
      0,
      0,
      position.width,
      position.height
    );
    let base64Img = canvasObj.toDataURL('image/jpg').split('base64,')[1].toString();
    return base64Img;
  }

3. 移动框选识别区域,改变识别区域内的内容:

  public moveBox(e, item, index) {
    e.stopPropagation();
    // 选取的当前要移动的框选区域:
    let thisBox = this.el.nativeElement.querySelector('.anchor-box-' + index);
    let nodePositon = {
      left: parseFloat(thisBox.style.left.replace('px', '')),
      top: parseFloat(thisBox.style.top.replace('px', '')),
      clientWidth: thisBox.getBoundingClientRect().width,
      clientHeight: thisBox.getBoundingClientRect().height,
    };
    let mousePosition = {
      left: e.clientX,
      top: e.clientY,
    };
    let movePosition = {
      left: 0,
      top: 0,
    };
    let maxPosition = {
      left: this.editImgWrapper.clientWidth - thisBox.clientWidth,
      top: this.editImgWrapper.clientHeight - thisBox.clientHeight
    };
    document.onmousemove = e => {
      e.stopPropagation();
      movePosition.left = (e.clientX - mousePosition.left) / this.editImgWrapper.scaleRatio;
      movePosition.top = (e.clientY - mousePosition.top) / this.editImgWrapper.scaleRatio;
      thisBox.style.left = Math.min(Math.max(0, nodePositon.left + movePosition.left), maxPosition.left) + 'px';
      thisBox.style.top = Math.min(Math.max(0, nodePositon.top + movePosition.top), maxPosition.top) + 'px';
    };
    document.onmouseup = event => {
      event.stopPropagation();
      if (Math.abs(movePosition.left) > 1 || Math.abs(movePosition.top) > 1) {
        this.setClip(item, thisBox);    // 重新绘图并回显
      }
      document.onmousemove = null;
      document.onmouseup = null;
    };
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值