G2 动态更新某个文本的方法

11 篇文章 0 订阅

蚂蚁金服的 G2 这个库有提供写入文本的功能. 可惜没提供比较好的 示例.想动态更新文本还是要研究一番的. 我就研究了一上午. 终于研究通了, 把重点说一下.
如果要想在界面上做到下面的这种效果.
在这里插入图片描述

需要在代码中新建一个View专门渲染文本 , 到时候更新的时候专门更新某个View. 这样可以保证其他的数据不会被更新掉. 并且content 要写成函数的形式. 代码如下.

<script lang="ts">
import Vue from 'vue';
import { Chart } from '@antv/g2';

export default Vue.extend({
  data() {
    return {
      current_epoch: 100,
      epochsbili: 0.5, // 进度比例 50%
      visiblCreatNewTrainTaskModal: false,
      DataSets: [], // 数据集
      LossArray: [], // 损失函数指标数据.
      ImageFileCount: 0, //  需要训练的样本图片个数
      TaskState: '已停止',
      currentEpochLossData: {}, // 当前的损失函数指标数据
      epoch: 0,
      epochs: 0,
      // 训练参数
      trainParam: {
        weights: './yolov5/weights/yolov5s.pt', // default='./runs/exp11/weights/best.pt', help='initial weights path')
        cfg: './yolov5/models/yolov5m.yaml', // help='model.yaml path')
        data: './yolov5/data/mydataset.yaml', // help='data.yaml path')#
        hyp: './yolov5/data/hyp.scratch.yaml', // help='hyperparameters path')
        epochs: 300,
        AutoSaveEpochs: 1, // 模型保存间隔 自动保存轮数
        batch_size: 10, // help='total batch size for all GPUs')#
        img_size: [640, 640], // help='[train, test] image sizes')
        rect: '', // help='rectangular training')
        resume: false, // help='resume most recent training') resume 应该是恢复训练,加上的话是用最近一次的权重开始训练
        nosave: true, // help='only save final checkpoint')
        notest: true, // help='only test final epoch')
        noautoanchor: true, // help='disable autoanchor check')
        evolve: true, // help='evolve hyperparameters') 进化超参数(hyp),可以试试
        bucket: '', // help='gsutil bucket')
        cache_images: true, // help='cache images for faster training')
        image_weights: true, // help='use weighted image selection for training')
        name: '', // help='renames results.txt to results_name.txt if supplied')
        device: 'cpu', // help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
        multi_scale: true, // help='vary img_size +/- 50%%')
        single_cls: true, // help='train as single_class dataset')
        adam: true, // help='use torch.optim.Adam() optimizer')
        sync_bn: true, // help='use SyncBatchNorm, only available in DDP mode')
        local_rank: -1, // help='DDP parameter, do not modify')
        logdir: 'runs/', // help='logging directory')
        workers: 8 // help='maximum number of dataloader workers')
      },
      hyp: {
        lr0: 0.01, // initial learning rate (SGD=1E-2, Adam=1E-3)    ######lr0:0.01#初始学习率(SGD=1E-2,Adam=1E-3)
        lrf: 0.2, // final OneCycleLR learning rate (lr0 * lrf)      ######lrf:0.2#最终一个周期ELR学习率(lr0*lrf)
        momentum: 0.937, // SGD momentum/Adam beta1                  ######动量:0.937新加坡元/亚当贝塔1
        weight_decay: 0.0005, // optimizer weight decay 5e-4         ######重量衰减:0.0005优化器重量衰减5e-4
        warmup_epochs: 3.0, // warmup epochs (fractions ok)
        warmup_momentum: 0.8, // warmup initial momentum
        warmup_bias_lr: 0.1, // warmup initial bias lr
        giou: 0.05, // box loss gain                                 ######giou:0.05#盒损增益
        cls: 0.5, // cls loss gain                                   ######cls:0.5#cls损益
        cls_pw: 1.0, // cls BCELoss positive_weight                  ######cls_pw:1.0#cls B无正重量
        obj: 1.0, // obj loss gain (scale with pixels)               ######obj:1.0#obj损失增益(按像素缩放)
        obj_pw: 1.0, // obj BCELoss positive_weight                  ######目标重量:1.0
        iou_t: 0.20, // IoU training threshold                       ######iou t:0.20#iou培训阈值
        anchor_t: 4.0, // anchor-multiple threshold                  ######锚定值:4.0#锚定多重阈值
        anchors: 0, // anchors per output grid (0 to ignore)         #######定位点:每个输出网格0个定位点(0忽略)
        fl_gamma: 0.0, // focal loss gamma (efficientDet default gamma=1.5)    ######flťgamma:0.0#焦点损失gamma(efficientDet default gamma=1.5)
        hsv_h: 0.015, // image HSV-Hue augmentation (fraction)       ######hsv_h:0.015#图像hsv色彩空间 色调H增强(分数)
        hsv_s: 0.7, // image HSV-Saturation augmentation (fraction)  ######hsv s:0.7#图像hsv色彩空间 饱和S增强(分数)
        hsv_v: 0.4, // image HSV-Value augmentation (fraction)       ######hsv#v:0.4#图像hsv色彩空间 亮度V增大(分数)
        degrees: 0.0, // image rotation (+/- deg)                    ######度数:0.0#图像旋转(+/-度)
        translate: 0.1, // image translation (+/- fraction)          ######翻译:0.1#图像翻译(+/-分数)
        scale: 0.5, // image scale (+/- gain)                        ######比例:0.5#图像比例(+/-增益)
        shear: 0.0, // image shear (+/- deg)                         ######剪切:0.0#图像剪切(+/-度)
        perspective: 0.0, // image perspective (+/- fraction), range 0-0.001   ######透视:0.0#图像透视(+/-分数),范围0-0.001
        flipud: 0.0, // image flip up-down (probability)             ######flipud:0.0#图像上下翻转(概率)
        fliplr: 0.5, // image flip left-right (probability)          ######fliplr:0.5#图像左右翻转(概率)
        mosaic: 1.0, // image mosaic (probability)
        mixup: 0.0 // image mixup (probability)			                 ######混音:0.0#图像混音(概率)
      },
      result: {
        GIoU: 0, // GIoU:推测为GIoU损失函数均值,越小方框越准;
        Objectness: 0, // Objectness:推测为目标检测loss均值,越小目标检测越准;
        Classification: 0, // Classification:推测为分类loss均值,越小分类越准;
        Precision: 0, // Precision:准确率(找对的/找到的);
        Recall: 0, // Recall:召回率(找对的/该找对的);
        mAP: 0, // mAP@0.5 & mAP@0.5:0.95:这里说的挺好,总之就是AP是用Precision和Recall作为两轴作图后围成的面积,m表示平均,@后面的数表示判定iou为正负样本的阈值,@0.5:0.95表示阈值取0.5:0.05:0.95后取均值。

      }
    };
  },
  mounted() {
    // console.log(45252);
    // 数量÷总数×100= 百分比
    this.epochsbili = 0; // Math.round(this.current_epoch / this.trainParam.epochs * 100);
    this.JinDuViewChart = this.JinDuView();
    this.LossViewChart = this.LossView();
    this.LoadDatasets();

    setInterval(this.GetLossArray.bind(this), 5000);
  },
  methods: {
    LoadDatasets() {
      this.$post({
        url: '/DatasetManage/LoadDatasets',
        method: 'post',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8'
        }
      })
        .then((res: any) => {
          if (res.success) {
            this.DataSets = res.data;
          } else {
            this.$message.info(res.message);
          }
        });
    },

    GetLossArray() {
      console.log('正在加载训练指标数据..');
      this.$post({
        url: '/Train/GetLossArray',
        method: 'post',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8'
        }
      })
        .then((res: any) => {
          if (res.success) {
            this.ImageFileCount = res.data.ImageFileCount;
            this.LossArray = res.data.LossLogArray;
            this.TaskState = res.data.TaskState;
            this.RefreshLossView();
          } else {
            this.$message.info(res.message);
          }
        });
    },
    // 刷新界面
    RefreshLossView() {
      console.log('正在刷新训练指标数据..');

      if (this.LossArray.length === 0) {
        return;
      }
      const lastindex = this.LossArray.length - 1;
      const lastloss = this.LossArray[lastindex] as any; 
      
      this.epoch = lastloss.epoch;
      this.epochs = lastloss.epochs;
      this.currentEpochLossData = lastloss;

      this.epochsbili = Math.round(this.epoch / this.epochs * 100);
      const data2 = [];
      for (let i = 0; i < 100; i++) {
        const item: any = {};
        item.type = i + '';
        item.value = 4;
        if (i === this.epochsbili) {
          item.value = 8;
        }
        if (i > this.epochsbili) {
          item.value = 0;
        }
        data2.push(item);
      }  
      // this.JinDuViewChart.views[2] 就是view3 单独更新数据,就可以刷新
      this.JinDuViewChart.views[2].changeData(data2);
      // this.JinDuViewChart.paint(true);
      this.LossViewChart.changeData(this.LossArray);
    },
    CreatNewTrainTask() {

      const par = {
        option: JSON.stringify(this.trainParam),
        hyp: JSON.stringify(this.hyp),
      };

      this.$post.post('/Train/CreatNewTrainTask', this.ToFormData(par))
        .then((res: any) => {
          if (res.success) {
            this.$message.info(res.message);
            // this.GetLabels();
          } else {
            this.$message.info(res.message);
          }
        });
    },
    LossView() {
      const data = [
        { year: '1991', value: 3 },
        { year: '1992', value: 4 },
        { year: '1993', value: 3.5 },
        { year: '1994', value: 5 },
        { year: '1995', value: 4.9 },
        { year: '1996', value: 6 },
        { year: '1997', value: 7 },
        { year: '1998', value: 9 },
        { year: '1999', value: 13 },
      ];
      const chart = new Chart({
        container: 'LossViewEL',
        autoFit: true,
        height: 400,
      });

      chart.data(data);
      chart.scale({
        year: {
          range: [0, 1],
        },
        value: {
          min: 0,
          nice: true,
        },
      });

      chart.tooltip({
        showCrosshairs: true, // 展示 Tooltip 辅助线
        shared: true,
      });

      chart.line().position('year*value').label('value');
      chart.point().position('year*value');


      const titleView3 = chart.createView();
      titleView3.annotation().text({
        position: ['50%', '5%'],
        content: '误差(loss)',
        style: {
          fill: '#CBCBCB',
          fontSize: 25,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });

      chart.render();
      return chart;
    },
    JinDuView() {
      // 极坐标下的柱状图
      // 构造数据
      // 灰色线, 总进度


      // 蓝色线线, 进度线
      const data2 = [];
      for (let i = 0; i < 100; i++) {
        const item: any = {};
        item.type = i + '';
        item.value = 4;
        if (i === this.epochsbili) {
          item.value = 8;
        }
        if (i > this.epochsbili) {
          item.value = 0;
        }
        data2.push(item);
      }

      const chart = new Chart({
        container: 'jindu',
        autoFit: true,
        height: 400,
        padding: 0,
      });
      chart.scale({
        type: {
          range: [0, 1],
        },
        value: {
          sync: true,
        },
      });
      chart.legend(false);
      chart.tooltip(false);

      const view1 = chart.createView();
      const data1 = [];
      for (let i = 0; i < 100; i++) {
        data1.push({
          type: i + '',
          value: 4, // 线的长短
        });
      }
      view1.data(data1);
      view1.axis(false);
      view1.coordinate('polar', {
        startAngle: (-9 / 8) * Math.PI,
        endAngle: (1 / 8) * Math.PI,
        innerRadius: 0.75,
        radius: 0.8,
      });
      view1
        .interval()
        .position('type*value')
        .color('#CBCBCB')
        .size(6);

      const view2 = chart.createView();
      view2.data(data1);
      view2.axis('value', false);
      view2.axis('type', {
        grid: null,
        line: null,
        tickLine: null,
        label: {
          offset: -25,
          style: {
            textAlign: 'center',
            fill: '#CBCBCB',
            fontSize: 18,
          },
          formatter: (val) => {
            if (+val % 7 !== 0) {
              return '';
            }

            return val;
          },
        },
      });
      // 内圈小虚线
      view2.coordinate('polar', {
        startAngle: (-9 / 8) * Math.PI,
        endAngle: (1 / 8) * Math.PI,
        innerRadius: 0.95,
        radius: 0.55,
      });
      view2
        .interval()
        .position('type*value')
        .color('#A987FB')
        .size(2);

      // chart.point()
      //   .position('x*y')
      //   .label('value', (xValue) => {
      //     return {
      //       content: xValue + '%',
      //     };
      //   });
      const view3 = chart.createView();

      view3.data(data2);
      view3.axis(false);
      view3.coordinate('polar', {
        startAngle: (-9 / 8) * Math.PI,
        endAngle: (1 / 8) * Math.PI,
        innerRadius: 0.75,
        radius: 0.8,
      });
      view3
        .interval()
        .position('type*value')
        .color('value', '#3023AE-#188cfa')
        .size(6);

      view3.annotation().text({
        position: ['50%', '60%'],
        content: '轮次',
        style: {
          fill: '#CBCBCB',
          fontSize: 12,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });



      view3.annotation().text({
        position: ['50%', '75%'],
        content: '样本数',
        style: {
          fill: '#CBCBCB',
          fontSize: 12,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });


      view3.annotation().text({
        position: ['50%', '95%'],
        content: () => {
          return this.TaskState;
        },
        style: {
          fill: '#1f65a4',
          fontSize: 20,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });

      view3.annotation().text({
        position: ['50%', '5%'],
        content: '进度(progress)%',
        style: {
          fill: '#CBCBCB',
          fontSize: 25,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });

      view3.annotation().text({
        position: ['50%', '55%'],
        content: () => {  // 注意这里是函数的形式
          return this.epoch + '/' + this.epochs;
        },
        top: true,
        style: {
          fill: '#CBCBCB',
          fontSize: 24,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });

      view3.annotation().text({
        position: ['50%', '70%'],
        content: () => { // 注意这里是函数的形式
          return this.ImageFileCount;
        },
        style: {
          fill: '#CBCBCB',
          fontSize: 24,
          textAlign: 'center',
          textBaseline: 'middle',
        },
      });
      chart.render();
      return chart;
    }
  }
});

</script>

this.JinDuViewChart.views[2].changeData(data2);

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值