原型图自动生成json

原型图自动生成json相关

Posted by koryako on October 21, 2021

原型图自动生成json


原型图自动生成json 配置数据

使用百度的EasyDL 自定义模型api和ocr 服务接口实现了UI图自动生成组件信息如下:

1
2
3
4
5
6
7
8
9
   
  [{ label: '付款时间', placehoder: '221-05-22021-05-2', formType: 'input' },
  { label: '类目分组', placehoder: '请选择类目分组', formType: 'select' },
  { label: '站点', placehoder: '请输入站点', formType: 'select' },
  { label: '组长', placehoder: '请选择组长', formType: 'select' },
  { label: '运营专员', placehoder: '请选择运营专员', formType: 'select' },
  { label: '显示已处理', placehoder: '否', formType: 'select' },
  { label: '显示二次销售', placehoder: '否', formType: 'select' },
  { label: '订单状态', placehoder: '全部', formType: 'select' }]

为了更加快速识别,所以前端用了截图功能,需要识别的部分图片上传到服务,然后由百度的两个服务分别识别组件类型和识别文字。然后通过坐标把两个数据拼合下,就得到了以上的数据结构。

截图部分react代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import React from 'react'
import Cropper from 'react-cropper'
import 'cropperjs/dist/cropper.css'
import {Button} from 'antd'

export default class Crop extends React.Component {
    constructor() {
        super();
        this.cropImage = this.cropImage.bind(this);
        this.state={
          src:'',
          file:''
        }
    }

    cropImage() {
        if (this.cropper.getCroppedCanvas() === 'null') {
            return false
        }

        let url = `/homepage_images`
        // 拿到文件名
         let filename = this.state.file.name
        let base64= this.cropper.getCroppedCanvas().toDataURL()
        console.log(base64)
        //message.info("正在上传图片")
        // TODO: 这里可以尝试修改上传图片的尺寸
      /*  this.cropper.getCroppedCanvas().toBlob(async blob => {
          // 创造提交表单数据对象
          const formData = new FormData()
          // 添加要上传的文件
          formData.append('file', blob, filename)
          // 提示开始上传
          this.setState({submitting: true})
          // 上传图片
          const resp = await http.post(url, formData)
          // 拿到服务器返回的数据
          this.props.onUploadedFile(resp.data.data)
          // 提示上传完毕
          this.setState({submitting: false})
          // 关闭弹窗
          this.props.onClose()
        })*/

        
    }

    handleFileChange = (e) => {

      const fileReader = new FileReader()
      const file = e.target.files[0]
     if (file) {
        if (file.size <= 5*1024*1024) {
          this.setState({file: file})
          fileReader.onload = (e) => {
            const dataURL = e.target.result
            this.setState({src: dataURL})
          }
          fileReader.readAsDataURL(file)
        } else {
          message.error("文件过大")
        }
      }
      e.target.value = ''
    }
    
    onCropperInit=cropper => { this.cropper = cropper }
    render() {
        return (
            <div>
                <div style=>
                    <Cropper
                        src={this.state.src}
                        onInitialized={this.onCropperInit.bind(this)}
                        style=
                        
                        guides={false}
                        preview='.cropper-preview'
                    />
                </div>
                <div>
                    <Button type="primary" size="large" onClick={this.cropImage} style=>
                        确认裁剪
                    </Button>
                </div>
                <label className="add-img-btn">
                  <span>添加图片</span>
                   <input
                    type="file"
                    accept="image/jpeg,image/jpg,image/png"
                    className="base-upload-input"
                    onChange={this.handleFileChange}
                   />
                </label>
                <div className="cropper-preview"></div>
            </div>
        );
    }
}

node server demo代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
var AipOcrClient = require("baidu-aip-sdk").ocr;
var request = require('request');


// 设置APPID/AK/SK
var APP_ID = "22361431";
var API_KEY = "A6Ra6d6qIULkpXRCQUe0B7DA";
var SECRET_KEY = "okG1mHYGbQ60ZwpQGofhUzEeURwU5xte";

// 新建一个对象,建议只保存一个对象调用服务接口
var client = new AipOcrClient(APP_ID, API_KEY, SECRET_KEY);

function httprequest(url,data,callback){
  request({
      url: url,
      method: "POST",
      json: true,
      headers: {
          "content-type": "application/json",
      },
      body: data
  }, function(error, response, body) {
      if (!error && response.statusCode == 200) {
        callback(body) // 请求成功的处理逻辑
      }
  });
};


//https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=wwrNWhrGs8zWpMyE5Z4AeQCK&client_secret=dGQGHpApWEeRsyiQGixqbDG2v3VrXy6z&
var fs = require('fs');

var image = fs.readFileSync("0.png").toString("base64");
// 如果有可选参数

var options = {};
options["language_type"] = "CHN_ENG";
options["detect_direction"] = "true";
options["detect_language"] = "true";
options["probability"] = "true";

function rectangleCol(x1,y1,w1,h1,x2,y2,w2,h2){
  var maxX,maxY,minX,minY;
  maxX = x1+w1 >= x2+w2 ? x1+w1 : x2+w2;
  maxY = y1+h1 >= y2+h2 ? y1+h1 : y2+h2;
  minX = x1 <= x2 ? x1 : x2;
  minY = y1 <= y2 ? y1 : y2;
  if(maxX - minX <= w1+w2 && maxY - minY <= h1+h2){
    return true;
  }else{
    return false;
  }
  }


let url='https://aip.baidubce.com/rpc/2.0/ai_custom/v1/detection/componentsdj?access_token=24.edc89ca7db7d4ee6eefa236facdcd220.2592000.1624608499.282335-23388316'
httprequest( url,{"image":image,"threshold":0.4},(data)=>{
 
  var b=data.results
console.log(JSON.stringify(b))

          // 调用通用文字识别, 图片参数为本地图片
client.accurate(image).then(function(result) {
  //var r=JSON.stringify(result)
   var ww=[]
   var r=result.words_result
    r.forEach(element => {
      if (element.location.top>100&&element.location.top<200){
        ww.push(element)
      }
    });
    console.log(JSON.stringify(ww));
    var r=[]
    ww.forEach(function(e){
        var l=e.location
        b.forEach(function(p){
           var c=p.location
          var go=rectangleCol(l.left,l.top,l.width,l.height,c.left,c.top,c.width,c.height)
          if (go){
            r.push({label:e.words.split(":")[0],placehoder:e.words.split(":")[1],formType:p.name})
          }
        })
    })
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});
});

获取token的地址: https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=wwrNWhrGs8zWpMyE5Z4AeQCK&client_secret=dGQGHpApWEeRsyiQGixqbDG2v3VrXy6z&

——————————————————————————————— 2021.10.21 更新 使用第三方api 虽然方便,但是有次数限制。

新的方案是自己搭建ocr 和图片检测服务。

使用tensorflow 给我们的强大功能,python 的格式转为js 格式,然后用纯js 代码加载,推理模型,集成到nodejs服务中。

google colab 还是非常强大的,虽然他现在白嫖有时间限制。

数据集

使用的是阿里前端智能委员会的开源的已经标注的数据集。 使用自己的数据集进行finetune

问题

  1. 阿里的数据集是xml 的,需要把他转成json coco 格式,因为使用的预训练模型是coco 的有点绕大致流程是: xml2json —> json转coco 格式—> 转tfrecord 格式文件—> 使用object detection 进行训练—> 使用自己的数据集进行fewshot训练—>cpkt 格式模型转成 .pb 模型 —> pb模型转成js 格式 —>本地js加载模型并推理—> 嵌入的nodejs 服务中

  2. json 转coco json 代码是搬砖的,有点坑,修改了下

ocr

使用开源的不是很准,暂时还是用百度的

位置聚类与排序

  1. 使用sklearn 聚类函数进行 组件与文字的合并,然后按照位置进行排序

表数据生成文档说明

  1. https://github.com/harvardnlp/boxscore-data 数据集
  2. https://github.com/ratishsp/data2text-entity-py 数据生成文本

代码生成文档说明