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