vue-picture-bd-marker 简单的数据标注

Vue2 专栏收录该内容
20 篇文章 0 订阅

参考文档:https://github.com/sunshengfei/ui-picture-bd-marker
https://vmarker.sagocloud.com/quick_start/#a-qs-vue
https://www.jianshu.com/p/4dc54799c0e3
在这里插入图片描述

代码:

<template>
  <div>
    <el-form :model="formInline">
      <el-form-item label="数据集:">
        <el-select v-model="formInline.region" placeholder="选择数据集">
          <el-option
            :label="item.name"
            :value="item.code"
            v-for="item in dataList"
          ></el-option>
        </el-select>
        <el-button type="primary" style="margin-left: 20px">选择</el-button>
      </el-form-item>

      <el-form-item label="图片筛选:">
        <el-radio-group v-model="formInline.radio" @change="handleChange">
          <el-radio-button label="全部"></el-radio-button>
          <el-radio-button label="未标注"></el-radio-button>
          <el-radio-button label="已标注"></el-radio-button>
        </el-radio-group>
      </el-form-item>
      <!-- <el-form-item>
        <el-button type="primary">选择</el-button>
      </el-form-item> -->
    </el-form>

    <!-- 图片导航 -->
    <div class="pics">
      <div class="arrow arrow-left" @click="showMore('down')"></div>
      <div class="pic-container">
        <div class="pic-box" ref="picContainer">
          <div class="pic" v-for="(v, i) in pics" :key="i">
            <div
              class="info"
              :style="{ 'background-image': 'url(' + v.cropImage + ')' }"
              @click="activePic(v.cropImage)"
            ></div>
          </div>
        </div>
      </div>
      <div class="arrow arrow-right" @click="showMore('up')"></div>
    </div>

    <el-row :gutter="10" class="tagList">
      <el-col :span="18">
        <ui-marker
          ref="aiPanel-editor"
          class="ai-observer"
          :uniqueKey="uuid"
          :ratio="16 / 9"
          :imgUrl="currentInfo.currentBaseImage"
          @vmarker:onImageLoad="onImageLoad"
        ></ui-marker>
      </el-col>
      <el-col :span="6">
        <div class="title">标签</div>
        <div class="tags" v-for="(v, i) in tags" :key="i">
          <el-tag size="small" @click="setTag(v)">
            {{ v.tagName }}
          </el-tag>
          <i class="el-icon-delete" @click="delTag(i)"></i>
        </div>
        <el-row>
          <el-button type="success" class="handleButton" @click="addTag">
            添加标签
          </el-button>
        </el-row>
        <el-button type="primary" class="handleButton" @click="submitForm">
          提交标注
        </el-button>
      </el-col>
    </el-row>

    <!-- 添加标签 dialog -->
    <el-dialog
      width="30%"
      title="添加标签"
      :visible.sync="innerVisible"
      :before-close="beforeClose"
    >
      <el-form ref="innerForm" :model="innerForm" :rules="tep_rules">
        <el-form-item label="标签名称:" prop="tagName">
          <el-input v-model="innerForm.tagName" />
        </el-form-item>
        <el-form-item label="标签编码:" prop="tag">
          <el-input v-model="innerForm.tag" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="close">取 消</el-button>
        <el-button type="primary" @click="createForm('innerForm')">
          确 定
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
// import { AIMarker } from 'Vue-Picture-BD-Marker'
import { AIMarker } from 'vue-picture-bd-marker'
export default {
  name: 'stagePicPage',
  components: { 'ui-marker': AIMarker },
  data() {
    return {
      formInline: {
        region: '',
        radio: '全部'
      },
      dataList: [
        { name: '安全帽', code: 1 },
        { name: '火焰', code: 2 }
      ],

      uuid: '0da9130',
      // 当前图片的信息,包含图片原本的高矮胖瘦尺寸
      currentInfo: {
        currentBaseImage:
          'https://seopic.699pic.com/photo/50041/3365.jpg_wh1200.jpg',
        rawW: 0,
        rawH: 0,
        currentW: 0,
        currentH: 0,
        checked: false, // false表示当前图片还没有标记过
        data: [] // 表示图片矩形标记信息
      },

      // *****************************
      pics: [
        {
          cropImage: 'https://seopic.699pic.com/photo/50041/3365.jpg_wh1200.jpg'
        },
        {
          cropImage: 'https://seopic.699pic.com/photo/50041/3365.jpg_wh1200.jpg'
        },
        {
          cropImage: 'https://seopic.699pic.com/photo/50098/1015.jpg_wh1200.jpg'
        },
        {
          cropImage: 'https://seopic.699pic.com/photo/50098/1015.jpg_wh1200.jpg'
        },
        {
          cropImage: 'https://seopic.699pic.com/photo/50050/5027.jpg_wh1200.jpg'
        },
        {
          cropImage: 'https://seopic.699pic.com/photo/50140/6207.jpg_wh1200.jpg'
        }
      ],
      active: 0, // 当前图片序号
      picTotal: 10, // 照片总数

      // *********************************************
      tags: [
        {
          tagName: '小蜜蜂',
          tag: '0x0001'
        },
        {
          tagName: '汽车',
          tag: '0x0002'
        }
      ],
      allInfo: [], // 图片的矩形标记信息集合
      imageInfo: [], // 存储图片原始信息

      innerVisible: false,
      innerForm: {
        tagName: '',
        tag: ''
      },

      tep_rules: {
        tagName: [{ required: true, message: '请输入', trigger: 'blur' }],
        tag: [{ required: true, message: '请输入', trigger: 'blur' }]
      }
    }
  },
  mounted() {
    // this.onImageLoad()
  },
  methods: {
    /**记录图片当前的大小和原始大小 data={rawW,rawH,currentW,currentH} */
    onImageLoad(data) {
      console.log(data)
      this.imageInfo = data
    },

    setTag(v) {
      this.$refs['aiPanel-editor'].getMarker().setTag(v)
    },
    addTag() {
      this.innerVisible = true
      this.innerForm.tagName = ''
      this.innerForm.tag = ''
    },
    delTag(index) {
      this.tags.splice(index, 1)
    },
    close() {
      this.innerVisible = false
      this.$refs['innerForm'].resetFields()
    },
    beforeClose(done) {
      this.$refs['innerForm'].resetFields()
      done()
    },
    createForm(formName) {
      this.$refs[formName].validate(valid => {
        if (valid) {
          for (let index in this.tags) {
            let item = this.tags[index]
            if (
              item.tagName === this.innerForm.tagName ||
              item.tag === this.innerForm.tag
            ) {
              this.$message.warning('标签名或标签值已存在,请重新输入')
              return
            }
          }
          this.tags.push({
            tagName: this.innerForm.tagName,
            tag: this.innerForm.tag
          })
          this.innerVisible = false
        }
      })
    },
    /**
     * 完成标记,提交标记集合
     */
    submitForm() {
      let data = this.$refs['aiPanel-editor'].getMarker().getData()

      this.allInfo = data
      console.log(this.allInfo)

      let size = {
        width: this.imageInfo.rawW,
        height: this.imageInfo.rawH
      }
      let xmin =
        (parseInt(
          this.allInfo[0].position.x.substring(
            0,
            this.allInfo[0].position.x.length - 1
          )
        ) *
          size.width) /
        100
      console.log(xmin, '左上')
      let ymin =
        (parseInt(
          this.allInfo[0].position.y.substring(
            0,
            this.allInfo[0].position.y.length - 1
          )
        ) *
          size.height) /
        100
      console.log(ymin, '右手上')
      let xmax =
        (parseInt(
          this.allInfo[0].position.x1.substring(
            0,
            this.allInfo[0].position.x1.length - 1
          )
        ) *
          size.width) /
        100
      console.log(xmax, '右上')
      let ymax =
        (parseInt(
          this.allInfo[0].position.y1.substring(
            0,
            this.allInfo[0].position.y1.length - 1
          )
        ) *
          size.height) /
        100
      console.log(ymax, '左上')

      console.log(
        (xmax - xmin).toFixed(2),
        (ymax - ymin).toFixed(2),
        '计算矩形宽高'
      )
    },

    // 点击左右按钮显示更多
    showMore(v) {
      let el = this.$refs.picContainer
      let percent = (this.active / this.pics.length) * 100
      if (v == 'up') {
        this.active++
        if (this.active >= this.picTotal - 3) {
          // 最后4张图
          this.active = this.pics.length - 3
          return
        }
        if (
          this.pics.length - 3 == this.active &&
          this.pics.length < this.picTotal
        ) {
          this.photoPageIndex++
          this.getPhotos()
          return
        }
      } else {
        this.active--
        if (this.active < 0) this.active = 0
      }
      el.style.transform =
        'translateX(-' + (this.active / this.pics.length) * 100 + '%)'
    },

    getPhotos() {
      return this.$nextTick(() => {
        let el = this.$refs.picContainer
        if (el) {
          el.style.width = el.scrollWidth + 'px'

          el.style.transform =
            'translateX(-' + (this.active / this.pics.length) * 100 + '%)'
        }
      })
    },
    /**得到当前点击图片*/
    activePic(v) {
      this.currentInfo.currentBaseImage = v
    },

    handleChange(label) {
      console.log(label)
    }
  }
}
</script>

<style lang="scss" scoped>
.pics {
  width: 100%;
  overflow: hidden;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  .arrow {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-image: url('~@/assets/images/common/left.png');
    background-repeat: no-repeat;
    background-size: contain;
    &.arrow-right {
      transform: rotate(180deg);
    }
  }
  .pic-container {
    // width: 1180px;
    width: calc(100% - 30px);
    height: 114px;
    margin: 0 auto;
    overflow: hidden;
    .pic-box {
      height: 100%;
      // min-width: 1180px;
      min-width: calc(100% - 30px);
      transition: all 0.5s linear;
      display: flex;
      flex-wrap: nowrap;
    }
    .pic {
      float: left;
      border: 1px solid #ccc;
      box-sizing: border-box;
      margin-right: 10px;
      width: 185px;
      height: 114px;
      .info {
        width: 183px;
        height: 100%;
        background-size: 100%;
        background-repeat: no-repeat;
        background-position: center;
        position: relative;
        &:hover {
          border: 1px solid skyblue;
        }
      }
    }
  }
}
.tagList {
  .title {
    text-align: center;
    font-weight: bold;
  }
  .handleButton {
    width: 100%;
    margin-bottom: 10px;
  }
  .tags {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    .el-icon-delete {
      cursor: pointer;
    }
  }
}
</style>

  • 0
    点赞
  • 3
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值