【人工智能笔记】第十节 Tensorflow 2.0 实现指针仪表方向纠正及指针识别(上)

这次目标是实现指针仪表方向纠正及指针识别。这现实情况下,要做指针仪表识别,因为各种拍摄角度、光线与指针值的不同,通常需要标注大量素材,而且这种标注相对复杂。因此为解决该问题,我使用了迁移学习的方法,下面将详细讲解。

将由三部分讲解整个过程:

  1. 搭建Django服务,利用ECharts报表生成虚拟仪表图,作为第一阶段的训练素材。
  2. 编写模型训练与识别代码,并利用虚拟图做预训练,进行方向纠正与指针识别。
  3. 人手标注现实仪表图,并转换成训练素材,进行迁移学习。

一、创建服务

创建Django服务可参考官方文档(中文),快速入门部分,文档链接:https://docs.djangoproject.com/zh-hans/3.0/

# 创建项目
django-admin startproject ai_server

# 进入项目目录
cd ai_server

# 创建应用
python manage.py startapp ai_api

二、生成图表 

创建虚拟仪表图生成页面,通过将生成仪表图提交到服务,由服务保存到本地。

具体参数可查询ECharts官方文档:https://echarts.apache.org/zh/option.html#series-gauge

在ai_api/static/gauge路径下创建generate_image_save.html文件,内容如下:

<!DOCTYPE html>

<head>
  <meta charset="utf-8">
  <title>ECharts</title>
</head>

<body>
  <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
  <div id="main" style="height:400px; width: 400px;"></div>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <!-- ECharts单文件引入 -->
  <script src="http://echarts.baidu.com/build/dist/echarts.js"></script>
  <script type="text/javascript">
    function rgb() {//rgb颜色随机
      var r = Math.floor(Math.random() * 256);
      var g = Math.floor(Math.random() * 256);
      var b = Math.floor(Math.random() * 256);
      var rgb = '(' + r + ',' + g + ',' + b + ')';
      return rgb;
    }
    function color16() {//十六进制颜色随机
      var r = Math.floor(Math.random() * 256);
      var g = Math.floor(Math.random() * 256);
      var b = Math.floor(Math.random() * 256);
      var color = '#' + r.toString(16) + g.toString(16) + b.toString(16);
      return color;
    }
    // 路径配置
    require.config({
      paths: {
        echarts: 'http://echarts.baidu.com/build/dist'
      }
    });

    // 使用
    require(
      [
        'echarts',
        'echarts/chart/gauge' // 按需加载
      ],
      function (ec) {
        // 基于准备好的dom,初始化echarts图表
        let myChart = ec.init(document.getElementById('main'));

        // 为echarts对象加载数据 
        // myChart.setOption(option);
        let updateFun = () => {
          // let startAngle = Math.round(Math.random() * 360)
          // let endAngle = startAngle - Math.round(Math.random() * 300) - 30
          let startAngle = 180 + Math.round(Math.random() * 90) - 45
          let endAngle = 30 + Math.round(Math.random() * 120) - 60
          let option = {
            animation: false,
            // tooltip: {
            //   formatter: "{a} <br/>{b} : {c}%"
            // },
            // toolbox: {
            //   show: true,
            //   feature: {
            //     mark: { show: true },
            //     restore: { show: true },
            //     saveAsImage: { show: true }
            //   }
            // },
            series: [
              {
                name: '业务指标',
                type: 'gauge',
                legendHoverLink: false,
                splitNumber: Math.round(Math.random() * 10),       // 分割段数,默认为5
                startAngle: startAngle,
                endAngle: endAngle,
                axisLine: {            // 坐标轴线
                  lineStyle: {       // 属性lineStyle控制线条样式
                    color: [[0.2, color16()], [0.8, color16()], [1, color16()]],
                    width: Math.round(Math.random() * 10) + 3
                  }
                },
                axisTick: {            // 坐标轴小标记
                  splitNumber: Math.round(Math.random() * 10),   // 每份split细分多少段
                  length: Math.round(Math.random() * 20),        // 属性length控制线长
                  lineStyle: {       // 属性lineStyle控制线条样式
                    color: color16()
                  }
                },
                axisLabel: {           // 坐标轴文本标签,详见axis.axisLabel
                  textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
                    color: color16()
                  }
                },
                splitLine: {           // 分隔线
                  show: true,        // 默认显示,属性show控制显示与否
                  length: Math.round(Math.random() * 20) + 25,         // 属性length控制线长
                  lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式
                    color: color16()
                  }
                },
                pointer: {
                  length: (Math.round(Math.random() * 40) + 60) + '%',
                  width: Math.round(Math.random() * 8) + 1,
                  color: color16()
                },
                title: {
                  show: false,
                  offsetCenter: [0, '-40%'],       // x, y,单位px
                  textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
                    fontWeight: 'bolder'
                  }
                },
                detail: {
                  show: false,
                  formatter: '{value}%',
                  textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE
                    color: color16(),
                    fontWeight: 'bolder'
                  }
                },
                data: [{ value: 50, name: '' }]
              }
            ]
          };
          option.series[0].data[0].value = (Math.random() * 100).toFixed(2) - 0;
          myChart.setOption(option, true);
          let img = myChart.getDataURL();
          // console.log('图片数据:', img);
          axios.post('/ai_api/gauge/gauge_save', {
            img_data: img,
            value: option.series[0].data[0].value
          })
            .then(function (response) {
              console.log(response);
              timeTicket = setTimeout(updateFun, 1);
            })
            .catch(function (error) {
              console.log(error);
            });
        }
        timeTicket = setTimeout(updateFun, 1);
      }
    );
  </script>
</body>

修改ai_server\settings.py文件,在文件最后增加下面代码:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    "ai_api/static",
]

DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800  #默认设置为50M

 创建视图文件,ai_api\views\gauge.py,将图片保存到本地,代码如下:

def gauge_save(request):
    '''保存训练图片'''
    global save_num
    save_num += 0.000001
    request_data = json.loads(request.body)
    # print('request_data:', request_data)
    img_data = request_data['img_data'].split(',')[1]
    img_data = image_helpler.base64ToBytes(img_data)
    img = image_helpler.bytesToOpenCVImage(img_data)
    value = request_data['value']
    img_name = ('%s_%.2f.jpg') % (str(save_num), value)
    path = "./image_data/" + img_name

    image_helpler.openCVImageToFile(path, img)

    jsonObj = {
        "value": value,
    }
    return HttpResponse(json.dumps(jsonObj), content_type="application/json")

增加接口路由,实际路由地址为:/ai_api/gauge/gauge_save

增加路由方法请参考Django文档。

最后用浏览器打开:http://127.0.0.1:8000/static/generate_image_save.html,页面会自动生成图片到文件夹。推荐生成20000以上文件用于作为下一节训练素材。

效果图

下一节,将会讲解如何建立模型,进行方向纠正与指针识别。源码会在第三节发布,敬请关注!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PPHT-H

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值