• 半自动标注(使用自己的分割或检测模型推理完得到的矩阵再生成json文件)


    前言
    都知道标注很麻烦、很累,不然先训练一批,然后推理得到它的掩码图,先生成自动标注,再人工手动修改也许会快很多

    半自动标注代码

    这是我自己写的,是labelme的格式,大家想要修改成自己的json格式可以修改json_dict_init与dict_init函数

    默认大家已经得到自己图片经过模型推理之后的掩码图了,掩码图上面生成的像素应该是0,1,2,3. 分别对应自己训练的时候的标签

    import cv2
    import sys
    import base64
    import cv2
    import json
    import time
    import os
    from tqdm import tqdm
    from PIL import Image
    import numpy as np
    
    def dict_init(label_name):
        temp_dict = {
            "label": label_name,
            "line_color": None,
            "fill_color": None,
            "points":[],
            "shape_type": "polygon",
            "flags": {}
        }
    
        return  temp_dict
    
    def json_dict_init(num,height,width,img):
        temp_dict = {
            "version": "3.16.2",
            "flags": {},
            "shapes": [],
            "lineColor": [
                0,
                255,
                0,
                128
            ],
            "fillColor": [
                255,
                0,
                0,
                128
            ],
            "imagePath": "..\\img\\{}.jpg".format(num),
            #原图像数据通过b64编码生成的字符串数据,可以再次解码成图片
            "imageData":img,
            "imageHeight": height,
            "imageWidth": width
        }
    
        return  temp_dict
    
    def image_to_base64(image_path):
        # 读取二进制图片,获得原始字节码
        with open(image_path, 'rb') as jpg_file:
            byte_content = jpg_file.read()
    
        # 把原始字节码编码成base64字节码
        base64_bytes = base64.b64encode(byte_content)
    
        # 把base64字节码解码成utf-8格式的字符串
        base64_string = base64_bytes.decode('utf-8')
    
        return base64_string
    
    # 定义一个函数,用于判断两个点是否相邻
    def is_adjacent(pt1, pt2):
        x1, y1 = pt1
        x2, y2 = pt2
        return abs(x1 - x2) <= 8 and abs(y1 - y2) <= 8
    
    def main():
        img_path = "D:/data_val/new/temp/img"
        label_path = "D:/data_val/new/temp/label"
        json_save_path = 'D:/data_val/new/temp/json'
        os.makedirs(json_save_path,exist_ok=True)
    
        # 放入你的标签名 例如 你的掩码图 像素是1 1对应的就是phone 像素是2 2就是line
        label_name_list = ['phone','line']
    
        img_list = os.listdir(img_path)
        pbar = tqdm(total=len(img_list))
    
        for filename in img_list:
            name = filename.split(".")[0]
            # print("*"*10)
            # print(f'{filename}')
    
            #label图
            label = Image.open(f'{label_path}/{name}.png')
    
            label = np.array(label)
            #输出自己的label有多少种像素
            # unique_values = np.unique(label)
            # print('')
            # print(unique_values)
            # print('')
    
            height  = label.shape[0]
            width   = label.shape[1]
            base64_string = image_to_base64(f'{img_path}/{filename}')
            json_dict = json_dict_init(name,height,width,base64_string)
    
            contours, hierarchy = cv2.findContours(label, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
            background_flag =False
            if (len(contours) == 0):
                print("如果未识别到 则变成背景")
                shapes_dict = dict_init("_background_")
                left_top, left_botton = [10, 10], [10, height - 10]
                right_botton, right_top = [width - 10, height - 10], [width - 10, 10]
                shapes_dict['points'] = [left_top, left_botton, right_botton, right_top]
                json_dict["shapes"].append(shapes_dict)
    
            else:
               for i,clasee_name in enumerate(label_name_list):
                   temp = label.copy()
                   temp[temp!=(i+1)] = 0
                   contours, hierarchy = cv2.findContours(temp, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
                   if (len(contours) == 0):
                       continue
                   else:
                        count = 0
                        for contour in contours:
                            shapes_dict = dict_init(clasee_name)
                            count = count + 1
                            #10 20
                            
                            #语义分割
                            approxCourve = cv2.approxPolyDP(contour, 3, True)
                            for Courve in approxCourve:
                                point = Courve[0]
                                x, y = point
                                x = int(x)
                                y = int(y)
                                temp_list = []
                                temp_list.append(x)
                                temp_list.append(y)
                                shapes_dict["points"].append(temp_list)
                                
                            #目标检测 这里只写到生成检测框的四个点 根据自己需求填进去
                            # rect = cv2.minAreaRect(contour)
                            # box = cv2.boxPoints(rect)
                            # # print(box)
                            # # 轮廓必须是整数, 不能是小数, 所以转化为整数
                            # box = np.round(box).astype('int64')
                            # left_point_x = np.min(box[:, 0])
                            # right_point_x = np.max(box[:, 0])
                            # top_point_y = np.min(box[:, 1])
                            # bottom_point_y = np.max(box[:, 1])
                            
                            
                            json_dict["shapes"].append(shapes_dict)
    
            with open(f'{json_save_path}/{name}.json', "w", encoding='utf-8') as f:
                f.write(json.dumps(json_dict, ensure_ascii=False))
            pbar.update(1)
    
    
    if __name__ == "__main__":
        main()
    

    欢迎大家点赞或收藏哦~
    你们的点赞或收藏可以鼓励作者加快更新哟~

  • 相关阅读:
    SpringBoot统一功能处理
    VC++创建windows服务程序
    springboot 引入 mybatis -plus
    QML与C++通信
    期货开户手续费加一分都是薄利多销
    突破众多技术干货的迷茫
    dedecms织梦复制模型报错系统找不到你所指定的表
    【Java】学习日记 Day22
    【从入门到起飞】JavaSE—IO工具包(Commons-io,Hutool) (2)
    Python 中最常用的4种股票价格移动平均方法(三)
  • 原文地址:https://blog.csdn.net/weixin_44598554/article/details/138909417