将之前标注的目标检测结果导入到label_studio重新标注

新增标签,将之前标注的目标检测结果导入到label_studio重新标注

随着业务扩张,我们的数据标签不断增加。为避免重新标注全部历史数据的繁琐工作,可以将之前已标注的数据转换为模型预测的结果格式,导入 Label Studio 系统。这样,我们只需针对新增的标签进行补充标注,既节省人力,又确保数据完整性。

这里不介绍安装label_studio、启动label_studio。

这篇文章的前提已经安装好了label_studio,并且已经成功启动。

一、创建一个项目

在这里插入图片描述

二、创建从本地路径上传的storage、上传要标注的图片到目录下

在这里插入图片描述
这里的absolute local path就是你这个项目存放的需要标注图片的绝对路径
在这里插入图片描述
这是我的路径下的文件信息,我的路径前面多了/opt/docker/是因为我在容器里做了映射。
在这里插入图片描述
创建好storage之后,将要标注的图片传输到这个目录下,我这里传输了四张图片。

三、数据格式转换
yolo格式的标注数据

我之前在label_studio中标注的数据的格式是yolo的格式
在这里插入图片描述
每一行表示一个标注的结果:

<class_id> <x_center> <y_center>

<class_id>: 类别 ID,从 0 开始(例如,0 表示第一类,1 表示第二类)。

<x_center>: 标注框中心点的 x 坐标,相对于图像宽度的归一化值,范围为 0 到 1。

<y_center>: 标注框中心点的 y 坐标,相对于图像高度的归一化值,范围为 0 到 1。

<width>: 标注框的宽度,相对于图像宽度的归一化值,范围为 0 到 1。

<height>: 标注框的高度,相对于图像高度的归一化值,范围为 0 到 1。

label_studio支持的导入模型预测结果的数据格式
[{'predictions': [{'model_version': 'one',
    'score': 0.5,
    'result': [{'original_width': 238,
      'original_height': 400,
      'image_rotation': 0,
      'value': {'x': 67.87777351604542,
       'y': 91.97786998616884,
       'width': 8.833506458801875,
       'height': 5.809128630705339,
       'rotation': 0,
       'rectanglelabels': ['CE']},
      'id': '1',
      'from_name': 'label',
      'to_name': 'image',
      'type': 'rectanglelabels',
      'origin': 'manual'}]}],
  'data': {'image': 'https://mm.belccol.com/data/local-files/?d=label-studio/data/media/upload/8/0000001.png'}},
 {'predictions': [{'model_version': 'one',
    'score': 0.5,
    'result': [{'original_width': 1500,
      'original_height': 1125,
      'image_rotation': 0,
      'value': {'x': 15.663900414937757,
       'y': 8.99031811894882,
       'width': 15.14522821576763,
       'height': 7.883817427385886,
       'rotation': 0,
       'rectanglelabels': ['French recycling logo']},
      'id': '2',
      'from_name': 'label',
      'to_name': 'image',
      'type': 'rectanglelabels',
      'origin': 'manual'}]}],
  'data': {'image': 'https://mm.belccol.com/data/local-files/?d=label-studio/data/media/upload/8/01b6725a91146d270f0a0e7c6202f7cf.jpg'}},
 ]

是一个列表格式的数据,每个字典元素表示一张图片的预测结果;predictions:预测的结果、data:文件名(我这里是用的url,https://mm.belccol.com/data/local-files/?d=这串是固定的,后面是图片的路径)。

predictions的值又是一个列表,每个元素表示的是每个标签的标注结果:model_version、score、from_name、to_name、type、origin、rotation、image_rotation这些字段都是可以写死不变的。

id需要不同,且是字符串,不然会有问题。

rectanglelabels里的值是标签的名称,original_width、original_height表示图片的宽和高。value字段中的x、y、width、height四个值表示的是:标注框的左上角x坐标、左上角y坐标、宽、高的值,但这个值是一个百分比数值。所以要将yolo的坐标框转换为label_studio的框的数据格式,可以用下面的代码:

x = (x_center - width / 2) * 100
y = (y_center - height / 2) * 100
width = width * 100
height = height * 100

以下是我生成完整的数据格式的代码:

import json
import os
import glob
from PIL import Image


label_dict = {
    "3+": 0,
    "6+": 1,
    "ASTM": 2,
    "ButtonbatterywarningsignsTwo": 3,
    "Buttonbatterywarningsignsone": 4,
    "CE": 5,
    "CPC": 6,
    "DC": 7,
    "Recycling with code": 8,
    "DE WEEE recycling symbol": 9,
    "EC-REP": 10,
    "FCC": 11,
    "French recycling-Daidian": 12,
    "French recycling logo": 13
}

label_reverse = {index: name for name, index in label_dict.items()}

model_version = "one"
root_path = "https://mm.belccol.com/data/local-files/?d=label-studio/data/media/upload/8/"


result_list = []
images_path = r"D:\work\code\ai_my\label_studio_test\images\*"
labels_path = r"D:\work\code\ai_my\label_studio_test\labels"
id = 1
for file in glob.glob(images_path):
    print("file:", file)
    suffix = file.split("\\")[-1].split(".")[0]
    img_path = file.split("\\")[-1]
    image = Image.open(file)
    width, height = image.size
    labels_file = labels_path +  "/" + suffix + ".txt"
    with open(labels_file, "r") as f:
        lines = f.readlines()
    json_result = {"predictions": [{"model_version": "one",
        "score": 0.5, "result": []}], "data": {"image": root_path + img_path}}
    for line in lines:
        label_index, x, y, w, h = map(float, line.strip().split(" "))
        label = label_reverse[int(label_index)]
        x1 = (x - w / 2)*100
        y1 = (y - h / 2)*100
        w1 = w*100
        h1 = h*100
        
        sub_res = {
            "original_width": width,
            "original_height": height,
            "image_rotation": 0,
            "value": {
              "x": x1,
              "y": y1,
              "width": w1,
              "height": h1,
              "rotation": 0,
              "rectanglelabels": [
                label
              ]
            },
            "id": str(id),
            "from_name": "label",
            "to_name": "image",
            "type": "rectanglelabels",
            "origin": "manual"
          }
        json_result["predictions"][0]["result"].append(sub_res)
        id += 1
    result_list.append(json_result)
        


with open('./label_studio_import.json', 'w', encoding='utf-8') as f:
    json.dump(result_list, f, ensure_ascii=False, indent=4)
四、从页面导入json文件

点击页面的import
在这里插入图片描述

点击upload files
在这里插入图片描述

上传第三步生成的json文件,页面就会有数据
在这里插入图片描述

之前标注的结果也显示在页面上了
在这里插入图片描述

备注:

如果遇到问题,可以自己从label_studio页面上上传数据,进行标注;比较从页面上传数据后的数据信息和自己生成的数据信息是否有差距,可以帮助排查问题。

点这里可以查看数据信息
在这里插入图片描述
在这里插入图片描述

文章参考链接:

https://www.bilibili.com/video/BV1BM4y1E7FK/?vd_source=6237c5d136c1b6af9dd1b4068b56f2ce

https://www.breezedeus.com/article/label-studio-20230621

<think>嗯,用户想了解Excel中的VLOOKUP函数的用法和参数含义。首先,我需要回忆一下VLOOKUP的基本结构。VLOOKUP是垂直查找函数,用于在表格的首列查找指定的值,然后返回该行中指定列的数据。它的四个参数分别是查找值、表格范围、列索引号和匹配模式。 接下来,我得确认每个参数的具体作用。第一个参数是lookup_value,也就是用户要查找的值,比如产品ID或者姓名。第二个参数是table_array,即查找的范围,这里要注意的是,查找值必须位于这个范围的第一列,否则函数无法正确工作。第三个参数是col_index_num,也就是用户想要返回的数据在表格范围中的第几列,这个列数是从表格范围的第一列开始算起的,不是整个工作表的列。第四个参数是range_lookup,决定是精确匹配还是近似匹配,通常用FALSE或0来指定精确匹配,避免错误。 然后,用户可能需要一个具体的例子来理解如何使用。比如,假设有一个产品价格表,用户想根据产品ID查找对应的价格。这时候,VLOOKUP就可以在ID列查找,然后返回价格列的数据。同时,要提醒用户注意表格范围最好使用绝对引用,比如$A$2:$C$100,这样在拖动公式时范围不会变化。 可能遇到的问题也需要考虑。比如,如果查找值不在表格的第一列,或者列索引号超过了表格的列数,函数会返回错误。此外,数据格式不一致也可能导致问题,比如查找值是数字,而表格中是文本格式的数字,这时候需要统一格式。还有,当出现#N/A错误时,可能是查找值不存在,或者匹配模式设置不正确,需要检查参数是否正确。 用户可能还会问到如何避免常见的错误,比如部分数据匹配出错的情况。这时候需要检查是否有多余的空格,或者数据格式不一致,或者表格范围没有锁定导致拖动时偏移。此外,XLOOKUP作为VLOOKUP的升级版,可能在某些情况下更方便,比如可以向左查找或者返回多列数据,这也是可以提及的内容。 最后,整理步骤,从基础语法到参数说明,再到具体案例,逐步引导用户理解如何使用VLOOKUP函数。同时,提供常见错误和解决方法,帮助用户在实际应用中避免问题。如果有必要,还可以比较VLOOKUP和其他查找函数的区别,比如HLOOKUP或XLOOKUP,但根据用户的问题,主要集中在VLOOKUP本身即可。</think>### Excel VLOOKUP函数详解 #### 一、基础语法与参数说明 VLOOKUP函数的语法为: $$=VLOOKUP(lookup\_value, table\_array, col\_index\_num, [range\_lookup])$$ 包含4个参数: 1. **lookup_value**(必填):要查找的值(如单元格引用或具体值) 2. **table_array**(必填):包含数据的表格范围(必须包含查找列和返回列) 3. **col_index_num**(必填):返回值所在列的序号(从table_array第一列开始计数) 4. **range_lookup**(可选):匹配类型 - `TRUE`/`1`:近似匹配(默认值,需数据升序排列) - `FALSE`/`0`:精确匹配(常用选项) [^1][^2] #### 二、使用步骤演示(工资表查询案例) 假设需要根据员工编号查询工资: 1. 建立查询单元格(如`B12`) 2. 输入公式: ```excel =VLOOKUP(A12, $A$2:$D$100, 4, 0) ``` - `A12`:待查询的员工编号 - `$A$2:$D$100`:锁定数据区域(绝对引用) - `4`:返回第4列(工资列) - `0`:精确匹配 [^2][^3] #### 三、常见错误与解决方法 | 错误现象 | 原因 | 解决方案 | |---------|------|---------| | #N/A | 查找值不存在 | 检查数据源或改用`IFERROR`容错 | | #REF! | 列序号超出范围 | 确认col_index_num ≤ 表格列数 | | 部分匹配失败 | 数据格式不一致 | 统一数值/文本格式 | | 结果错位 | 表格未锁定 | 使用`$`符号固定区域引用 | [^3][^4] #### 四、进阶技巧 1. **多条件查询**: 使用辅助列合并多个条件字段 ```excel =VLOOKUP(A2&B2, $D$2:$F$100, 3, 0) ``` 2. **通配符匹配**: `"*"`匹配任意字符,`"?"`匹配单个字符 ```excel =VLOOKUP("张*", $A$2:$C$100, 3, 0) ``` 3. **跨表查询**: 引用其他工作表数据 ```excel =VLOOKUP(A2, Sheet2!$A$2:$D$100, 4, 0) ``` [^1][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值