yolov8 与 label studio实现半自动化标注

准备工作

  • label studio前端服务
  • 下载lable studio ml backend 代码
  • yolov8训练好的模型

安装label studio前端

实现自己的label studio ml backend

  • 下载code, Github地址: https://github.com/HumanSignal/label-studio-ml-backend

  • 根据README中的说明创建自己的ml后端, 如图:
    在这里插入图片描述

  • 我创建时用的命令:

    #用清华的源会快一点
    pip install -e . -i https://pypi.tuna.tsinghua.edu.cn/simple
    #创建自己的后端服务
    label-studio-ml create my_ml_backend
    

    在这里插入图片描述

  • 在model.py中重写predict() 函数, 里面会有返回值的json样例, 具体重写方法可以参考官方地址: label-studio-yolov8-backend 中的model_det.py, 这个地方要注意的是获取到xyxy后需要转换为lable studio对应的坐标值, 我根据官方文档修改后的代码会贴在文章最后。

  • 重写完成后的本地启动命令:

    label-studio-ml start my_ml_backend -p 9091
    

前端配置及效果展示

  • 新建项目以及使用可以看up主视频: label-studio 环境搭建
  • model配置:
    1. Settings中选中Model, 点击Connect Model
      在这里插入图片描述
    2. 启动好你的ml后端后, 做如下配置:
      Name: 自己定义(ML)
      Backend URL: 后端服务地址, 我本地启动的,所以是127.0.0.1, 端口号就是启动命令(label-studio-ml start my_ml_backend -p 9091)中设置 -p, 点击 Validate and Save, 成功后如下图
      在这里插入图片描述
      在这里插入图片描述
  • 导入图片后,选中你要自动标注的图片, 按下图点击 Retrieve Predictions
    在这里插入图片描述
    在这里插入图片描述
  • 效果如下图: 预标注这一列会由0 变为 1,检查是否需要手动修改
    在这里插入图片描述
    在这里插入图片描述

yolov8安装及模型训练

label studio ml backend 重写 predict()思路

  • 最终的目的:我们只需要根据例子, 封装好对应结构的数据返回即可, 关键就是拿到示例中对应的结果参数
  • from_name, type, to_name这些值都是label studio的参数, 可以从传入参数tasks中获取
  • original_width, original_height是原图片的大小, 可以通过image.size获取
  • 重点是 rectanglelabels, xyxy的值需要从模型解析的结果中获取,
    我们可以写个yolov8的测试函数, 看看 results = self.model.predict(image,conf=0.5) 中results的返回结果包含什么,
    xyxy的值就包含在results的boxes属性里面,
  • rectanglelabels 就是标注所属的类型, 比如Hero,Monster, boxes中有个cls的属性, 包含的就是 self.model.names中对应的编号key值, 可以根据 cls 和 names将 编号 转换为 具体的类型名字
  • xyxy的值需要转换成label studio对应的值

我自己修改后的label studio ml backend代码

from typing import List, Dict, Optional
from label_studio_ml.model import LabelStudioMLBase
from label_studio_ml.response import ModelResponse
from label_studio_ml.utils import get_single_tag_keys, get_local_path

from ultralytics import YOLO
from PIL import Image


class NewModel(LabelStudioMLBase):
    """Custom ML Backend model
    """

    def setup(self):
        self.set("model_version", "0.0.1")
        # Initialize self variables
        self.from_name, self.to_name, self.value, self.classes = get_single_tag_keys(
            self.parsed_label_config, 'RectangleLabels', 'Image')
	
        # 加载自己的yolov8模型
        self.model = YOLO('my_ml_backend/model/best.pt')
        # 改动的地方, 这里要获取自己模型中的类型
        self.labels = self.model.names


    def predict(self, tasks: List[Dict], context: Optional[Dict] = None, **kwargs) -> ModelResponse:
        print(f'''\
        Run prediction on {tasks}
        Received context: {context}
        Project ID: {self.project_id}
        Label config: {self.label_config}
        Parsed JSON Label config: {self.parsed_label_config}
        Extra params: {self.extra_params}''')

		# 改动的地方: 也可以按原方法获取图片路径, ls_host就是你本机的ip地址
        image_path = self.get_local_path(url=tasks[0]['data'][self.value],ls_host="http://192.168.131.220", task_id=tasks[0]['id'])
        print(f'image_path: {image_path}')

        # Getting URL and loading image
        image = Image.open(image_path)
        # Height and width of image
        original_width, original_height = image.size

        # Creating list for predictions and variable for scores
        predictions = []
        score = 0
        i = 0

		# 改动的地方, 增加了conf配置, 只有conf>=0.5的才会被标记出来 
		# 默认conf是0.25, 不改的话被标注的地方肯能会很多, 根据自己的实际情况配置
        # Getting prediction using model
        results = self.model.predict(image,conf=0.5)

        # Getting mask segments, boxes from model prediction
        for result in results:
            for i, prediction in enumerate(result.boxes):
                xyxy = prediction.xyxy[0].tolist()
                predictions.append({
                    "id": str(i),
                    "from_name": self.from_name,
                    "to_name": self.to_name,
                    "type": "rectanglelabels",
                    "score": prediction.conf.item(),
                    "original_width": original_width,
                    "original_height": original_height,
                    "image_rotation": 0,
                    "value": {
                        "rotation": 0,
                        # 坐标转换, 只有转换后才能标注在正确的位置
                        "x": xyxy[0] / original_width * 100,
                        "y": xyxy[1] / original_height * 100,
                        "width": (xyxy[2] - xyxy[0]) / original_width * 100,
                        "height": (xyxy[3] - xyxy[1]) / original_height * 100,
                        "rectanglelabels": [self.labels[int(prediction.cls.item())]]
                    }})
                score += prediction.conf.item()

        print(f"Prediction Score is {score:.3f}.")

        # Dict with final dicts with predictions
        final_prediction = [{
            "result": predictions,
            "score": score / (i + 1),
            "model_version": "v8n"
        }]

        return ModelResponse(predictions=final_prediction)

    def fit(self, event, data, **kwargs):
        """
        This method is called each time an annotation is created or updated
        You can run your logic here to update the model and persist it to the cache
        It is not recommended to perform long-running operations here, as it will block the main thread
        Instead, consider running a separate process or a thread (like RQ worker) to perform the training
        :param event: event type can be ('ANNOTATION_CREATED', 'ANNOTATION_UPDATED', 'START_TRAINING')
        :param data: the payload received from the event (check [Webhook event reference](https://labelstud.io/guide/webhook_reference.html))
        """

        # use cache to retrieve the data from the previous fit() runs
        old_data = self.get('my_data')
        old_model_version = self.get('model_version')
        print(f'Old data: {old_data}')
        print(f'Old model version: {old_model_version}')

        # store new data to the cache
        self.set('my_data', 'my_new_data_value')
        self.set('model_version', 'my_new_model_version')
        print(f'New data: {self.get("my_data")}')
        print(f'New model version: {self.get("model_version")}')

        print('fit() completed successfully.')

注意事项

  • label studio导入图片一次性导入太多会卡死, 我这边一次最多导入40张
  • 自动标注时,选中的task太多会执行很慢, 可能会出问题, 我这边一次Retrieve Predictions 20个task

相关链接

结语

  • 本来是想用yolov5 和 label studio实现自动化标注的, 但是没研究出来, 主要卡在模型解析这一步, 我将pt转为onnx之后解析, 返回的结果没有yolov8 返回的结果结构清晰, 导致不知到怎么从结果中获取想要的信息, 如果有网友有现成的示例的, 希望能提供个链接看看代码。

  • 我在xyxy坐标转换这一步卡了很久, 网上也没有搜到有用的信息,最后无意中搜到 label-studio-yolov8-ml-backend才解决。

  • 因为一开始就研究的 label-studio-ml-backend的代码, 所以在后端启动方面都是用的 这部分代码, 只是在 predict()重写方面,将label-studio-yolov8-backend 的代码移植了过来

  • 如果有yolov和 label studio的依赖问题, 可以尝试命令:

    # label studio sdk
    pip install --upgrade label-studio-sdk -i https://pypi.tuna.tsinghua.edu.cn/simple
    # yolov8 加载模型需要使用的包
    pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
    
### Label StudioYOLO在数据标注和目标检测中的角色 #### 数据标注工具:Label Studio Label Studio是一个灵活的数据标注平台,支持多种类型的任务,包括图像分类、对象框标注、多边形分割等。该工具允许用户通过图形界面轻松创建高质量的训练集。对于计算机视觉项目而言,Label Studio提供了直观的方式来进行像素级精确的对象标记[^2]。 ```python from label_studio_sdk import Client ls = Client(url='http://localhost:8080', api_key='your_api_key') project = ls.start_project(title="Object Detection Project", description="A project to detect objects using bounding boxes.") ``` #### 对象检测框架:YOLO 相比之下,YOLO (You Only Look Once) 是一种先进的实时物体识别算法,在单次推理过程中完成边界框预测和类别概率估计。YOLO模型因其速度优势而闻名,并且已被广泛应用于自动驾驶汽车、安防监控等领域。然而,YOLO本身并不具备内置的数据标注功能;它依赖于预先准备好的带标签数据集来训练其网络权重[^1]。 ```bash # 下载预训练YOLOv3模型并测试图片 wget https://pjreddie.com/media/files/yolov3.weights ./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/dog.jpg ``` #### 关系对比 两者之间存在互补关系而非竞争对立: - **用途不同**:Label Studio主要用于构建自定义数据集的过程当中,即生成用于机器学习模型训练所需的输入文件;而YOLO则是利用这些经过精心策划后的资料去实现高效能的目标侦测服务。 - **工作流程衔接紧密**:通常情况下,开发者会先使用像Label Studio这样的专用软件包对原始素材实施细致入微的手动或半自动化的打标作业,之后再将得到的结果导入至诸如YOLO之类的深度神经网络架构之中开展进一步的学习活动。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值