labelme\labelimg标注数据可视化

已标注数据的可视化有两种方式:

1.将图片和标注文件(json\xml)放在同一文件夹中,然后用labelme\labelimg打开此文件夹即可查看;

2.解析标注文件,用opencv进行可视化。

显然,本文要讲的是第二种!!!

一、labelimg标注的xml文件可视化

# 单张图片可视化
import cv2
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET

# 载入图像
img_path = '3.jpg'
img_bgr = cv2.imread(img_path)

# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()

# 载入labelimg格式的xml标注文件
xml_path = '3.xml'

xml_inf = open(xml_path)
tree = ET.parse(xml_inf)
# print(tree)
root = tree.getroot()
# print(root)

# 框可视化配置
bbox_color = (255, 129, 0)           # 框的颜色
bbox_thickness = 2                   # 框的线宽

# 框类别文字
bbox_labelstr = {
    'font_size':1,         # 字体大小
    'font_thickness':2,   # 字体粗细
    'offset_x':0,          # X 方向,文字偏移距离,向右为正
    'offset_y':-10,       # Y 方向,文字偏移距离,向下为正
}
# 画框
for obj in root.iter('object'): # 一个object代表一个标注物体

    # 框的类别
    bbox_label = obj.find('name').text

    # 框的两点坐标
    # 左上角坐标
    bbox_top_left_x = int(obj.find('bndbox').find('xmin').text)
    bbox_top_left_y = int(obj.find('bndbox').find('ymin').text)
    # 右下角坐标
    bbox_bottom_right_x = int(obj.find('bndbox').find('xmax').text)
    bbox_bottom_right_y = int(obj.find('bndbox').find('ymax').text)

    # 画矩形:画框
    img_bgr = cv2.rectangle(img_bgr, (bbox_top_left_x, bbox_top_left_y), (bbox_bottom_right_x, bbox_bottom_right_y),
                            bbox_color, bbox_thickness)

    # 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
    img_bgr = cv2.putText(img_bgr, bbox_label, (
                            bbox_top_left_x + bbox_labelstr['offset_x'],
                            bbox_top_left_y + bbox_labelstr['offset_y']),
                            cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color,
                            bbox_labelstr['font_thickness'])

# 可视化
plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
plt.show()
# 当前目录下保存可视化结果
cv2.imwrite('visualize3.jpg', img_bgr)
# 数据集可视化
import cv2
import os
import matplotlib.pyplot as plt
import xml.etree.ElementTree as ET

data_path = os.path.join("VOCdevkit", "VOC2007")
imgs_path = os.path.join(data_path, 'JPEGImages')
anns_path = os.path.join(data_path, 'Annotations')

# img_names = set([i for i in os.listdir(imgs_path)])
# ann_names = set([i for i in os.listdir(anns_path)])
img_names = set([os.path.splitext(i)[0] for i in os.listdir(imgs_path)])
ann_names = set([os.path.splitext(i)[0] for i in os.listdir(anns_path)])
img_names = list(img_names)
ann_names = list(ann_names)
# print(img_names)
# print(ann_names)

# print(img_names[0])
# print(ann_names[0])
# print(len(img_names))
# print(len(ann_names))

for i in range(len(img_names)):
    img_path = os.path.join(imgs_path, img_names[i]+".jpg")
    img_bgr = cv2.imread(img_path)

    xml_path = os.path.join(anns_path, ann_names[i] + ".xml")

    xml_inf = open(xml_path)
    tree = ET.parse(xml_inf)
    root = tree.getroot()

# 框可视化配置
    bbox_color = (255, 129, 0)  # 框的颜色
    bbox_thickness = 2  # 框的线宽

# 框类别文字
    bbox_labelstr = {
        'font_size': 1,  # 字体大小
        'font_thickness': 2,  # 字体粗细
        'offset_x': 0,  # X 方向,文字偏移距离,向右为正
        'offset_y': -10,  # Y 方向,文字偏移距离,向下为正
    }
# 画框
    for obj in root.iter('object'):  # 一个object代表一个标注物体

        # 框的类别
        bbox_label = obj.find('name').text

        # 框的两点坐标
        # 左上角坐标
        bbox_top_left_x = int(obj.find('bndbox').find('xmin').text)
        bbox_top_left_y = int(obj.find('bndbox').find('ymin').text)
        # 右下角坐标
        bbox_bottom_right_x = int(obj.find('bndbox').find('xmax').text)
        bbox_bottom_right_y = int(obj.find('bndbox').find('ymax').text)

        # 画矩形:画框
        img_bgr = cv2.rectangle(img_bgr, (bbox_top_left_x, bbox_top_left_y), (bbox_bottom_right_x, bbox_bottom_right_y),
                            bbox_color, bbox_thickness)

        # 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        img_bgr = cv2.putText(img_bgr, bbox_label, (
            bbox_top_left_x + bbox_labelstr['offset_x'],
            bbox_top_left_y + bbox_labelstr['offset_y']),
                          cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color,
                          bbox_labelstr['font_thickness'])

    cv2.imwrite("D:\cnn\Segmentation\CCBANet-main\VOCdevkit\VOC2007/result//{}.jpg".format(img_names[i]), img_bgr)
# 提取包含某些特定类别的图片和xml文件
import os
import shutil
import xml.etree.ElementTree as ET

data_path = os.path.join("D:\cnn\Segmentation\CCBANet-main\VOCdevkit", "VOC2007")
imgs_path = os.path.join(data_path, 'JPEGImages')
anns_path = os.path.join(data_path, 'Annotations')

img_names = set([os.path.splitext(i)[0] for i in os.listdir(imgs_path)])
ann_names = set([os.path.splitext(i)[0] for i in os.listdir(anns_path)])
img_names = list(img_names)
print(len(img_names))
ann_names = list(ann_names)

for i in range(len(img_names)):
    img_path = os.path.join(imgs_path, img_names[i]+".png")
    xml_path = os.path.join(anns_path, ann_names[i] + ".xml")

    xml_inf = open(xml_path)
    tree = ET.parse(xml_inf)
    root = tree.getroot()

    result_path = os.path.join(data_path, 'SD')

# 分别单独运行每一个类别
    for obj in root.iter('object'):  # 一个object代表一个标注物体
        # 框的类别
        bbox_label = obj.find('name').text
        # if bbox_label == "GL":
        #     shutil.copy(img_path, result_path)
        #     shutil.copy(xml_path, result_path)

        # if bbox_label == "PG":
        #     shutil.copy(img_path, result_path)
        #     shutil.copy(xml_path, result_path)

        if bbox_label == "SD":
            shutil.move(img_path, result_path)
            shutil.copy(xml_path, result_path)

 

二、labelme标注的json文件可视化

# 导入工具包
import cv2
import numpy as np
import json

import matplotlib.pyplot as plt
# matplotlib inline

# 载入图像
img_path = '1.jpg'
img_bgr = cv2.imread(img_path)

# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()

# 载入labelme格式的json标注文件
labelme_path = '1_labelme.json'

with open(labelme_path, 'r', encoding='utf-8') as f:
    labelme = json.load(f)

# 查看标注信息  rectangle:矩形  point:点  polygon:多边形
# print(labelme.keys())
# dict_keys(['version', 'flags', 'shapes', 'imagePath', 'imageData', 'imageHeight', 'imageWidth'])
# print(labelme['shapes'])

# <<<<<<<<<<<<<<<<<<可视化框(rectangle)标注>>>>>>>>>>>>>>>>>>>>>
# 框可视化配置
bbox_color = (255, 129, 0)           # 框的颜色
bbox_thickness = 5                   # 框的线宽

# 框类别文字
bbox_labelstr = {
    'font_size':6,         # 字体大小
    'font_thickness':14,   # 字体粗细
    'offset_x':0,          # X 方向,文字偏移距离,向右为正
    'offset_y':-80,       # Y 方向,文字偏移距离,向下为正
}
# 画框
for each_ann in labelme['shapes']:  # 遍历每一个标注

    if each_ann['shape_type'] == 'rectangle':  # 筛选出框标注

        # 框的类别
        bbox_label = each_ann['label']
        # 框的两点坐标
        bbox_keypoints = each_ann['points']
        bbox_keypoint_A_xy = bbox_keypoints[0]
        bbox_keypoint_B_xy = bbox_keypoints[1]
        # 左上角坐标
        bbox_top_left_x = int(min(bbox_keypoint_A_xy[0], bbox_keypoint_B_xy[0]))
        bbox_top_left_y = int(min(bbox_keypoint_A_xy[1], bbox_keypoint_B_xy[1]))
        # 右下角坐标
        bbox_bottom_right_x = int(max(bbox_keypoint_A_xy[0], bbox_keypoint_B_xy[0]))
        bbox_bottom_right_y = int(max(bbox_keypoint_A_xy[1], bbox_keypoint_B_xy[1]))

        # 画矩形:画框
        img_bgr = cv2.rectangle(img_bgr, (bbox_top_left_x, bbox_top_left_y), (bbox_bottom_right_x, bbox_bottom_right_y),
                                bbox_color, bbox_thickness)

        # 写框类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        img_bgr = cv2.putText(img_bgr, bbox_label, (
                              bbox_top_left_x + bbox_labelstr['offset_x'],
                              bbox_top_left_y + bbox_labelstr['offset_y']),
                              cv2.FONT_HERSHEY_SIMPLEX, bbox_labelstr['font_size'], bbox_color,
                              bbox_labelstr['font_thickness'])

# # 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()

# <<<<<<<<<<<<<<<<<<可视化关键点(keypoint)标注>>>>>>>>>>>>>>>>>>>>>
# 关键点的可视化配置
# 关键点配色
kpt_color_map = {
    'angle_30':{'id':0, 'color':[255,0,0], 'radius':30, 'thickness':-1},
    'angle_60':{'id':1, 'color':[0,255,0], 'radius':30, 'thickness':-1},
    'angle_90':{'id':2, 'color':[0,0,255], 'radius':30, 'thickness':-1}
}

# 点类别文字
kpt_labelstr = {
    'font_size':4,             # 字体大小
    'font_thickness':12,       # 字体粗细
    'offset_x':30,             # X 方向,文字偏移距离,向右为正
    'offset_y':100,            # Y 方向,文字偏移距离,向下为正
}

# 画点
for each_ann in labelme['shapes']:  # 遍历每一个标注

    if each_ann['shape_type'] == 'point':  # 筛选出关键点标注

        kpt_label = each_ann['label']  # 该点的类别

        # 该点的 XY 坐标
        kpt_xy = each_ann['points'][0]
        kpt_x, kpt_y = int(kpt_xy[0]), int(kpt_xy[1])

        # 该点的可视化配置
        kpt_color = kpt_color_map[kpt_label]['color']  # 颜色
        kpt_radius = kpt_color_map[kpt_label]['radius']  # 半径
        kpt_thickness = kpt_color_map[kpt_label]['thickness']  # 线宽(-1代表填充)

        # 画圆:画该关键点
        img_bgr = cv2.circle(img_bgr, (kpt_x, kpt_y), kpt_radius, kpt_color, kpt_thickness)

        # 写该点类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        img_bgr = cv2.putText(img_bgr, kpt_label, (kpt_x + kpt_labelstr['offset_x'], kpt_y + kpt_labelstr['offset_y']),
                              cv2.FONT_HERSHEY_SIMPLEX, kpt_labelstr['font_size'], kpt_color,
                              kpt_labelstr['font_thickness'])

# 可视化
# plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
# plt.show()

# <<<<<<<<<<<<<<<<<<可视化多段线(polygon)标注>>>>>>>>>>>>>>>>>>>>>
# 多段线的可视化配置
poly_color = (151, 57, 224)
poly_thickness = 3

poly_labelstr = {
    'font_size':4,          # 字体大小
    'font_thickness':12,    # 字体粗细
    'offset_x':-200,        # X 方向,文字偏移距离,向右为正
    'offset_y':0,           # Y 方向,文字偏移距离,向下为正
}

# 画多段线
img_mask = np.ones(img_bgr.shape, np.uint8) #创建一个和img_bgr一样大小的黑色mask

for each_ann in labelme['shapes']:  # 遍历每一个标注

    if each_ann['shape_type'] == 'polygon':  # 筛选出多段线(polygon)标注

        poly_label = each_ann['label']  # 该多段线的类别

        poly_points = [np.array(each_ann['points'], np.int32).reshape((-1, 1, 2))]  #reshape后增加一个维度

        # 该多段线平均 XY 坐标,用于放置多段线类别文字
        x_mean = int(np.mean(poly_points[0][:, 0, :][:, 0])) #取出所有点的x坐标并求平均值
        y_mean = int(np.mean(poly_points[0][:, 0, :][:, 1])) #取出所有点的y坐标并求平均值

        # 画该多段线轮廓
        img_bgr = cv2.polylines(img_bgr, poly_points, isClosed=True, color=poly_color, thickness=poly_thickness)

        # 画该多段线内部填充
        img_mask = cv2.fillPoly(img_mask, poly_points, color=poly_color) #填充的颜色为color=poly_color

        # 写该多段线类别文字:图片,文字字符串,文字左上角坐标,字体,字体大小,颜色,字体粗细
        img_bgr = cv2.putText(img_bgr, poly_label,
                              (x_mean + poly_labelstr['offset_x'], y_mean + poly_labelstr['offset_y']),
                              cv2.FONT_HERSHEY_SIMPLEX, poly_labelstr['font_size'], poly_color,
                              poly_labelstr['font_thickness'])

opacity = 0.8 # 透明度,越大越接近原图
img_bgr = cv2.addWeighted(img_bgr, opacity, img_mask, 1-opacity, 0)

# 可视化
plt.imshow(img_bgr[:,:,::-1]) # 将bgr通道转换成rgb通道
plt.show()

# 可视化多段线填充效果
# plt.imshow(img_mask[:, :, ::-1])  # 将bgr通道转换成rgb通道
# plt.show()

# 当前目录下保存可视化结果
cv2.imwrite('visualize1.jpg', img_bgr)

 

# 可视化json标注文件,并将其转化为mask掩码图像
import base64
import json
import os
import os.path as osp

from labelme.logger import logger
from labelme import utils


def main():
    logger.warning(
        "This script is aimed to demonstrate how to convert the "
        "JSON file to a single image dataset."
    )
    logger.warning(
        "It won't handle multiple JSON files to generate a "
        "real-use dataset."
    )

    # json_file是标注完之后生成的json文件的目录。out_dir是输出目录,即数据处理完之后文件保存的路径
    json_file = r"D:\cnn\deeplabv3-plus-pytorch-main_YUANBAN\datasets\before"
    out_dir = r"D:\cnn\deeplabv3-plus-pytorch-main_YUANBAN\datasets\SegmentationClass345-onlySB"

    # 如果输出的路径不存在,则自动创建这个路径
    if not osp.exists(out_dir):
        os.mkdir(out_dir)
    # 将类别名称转换成数值,以便于计算,此处先定义好每个(部分)类别对应的像素值
    label_name_to_value = {"_background_": 0, "SB": 1}
    for file_name in os.listdir(json_file):
        # 遍历json_file里面所有的文件,并判断这个文件是不是以.json结尾
        if file_name.endswith(".json"):
            path = os.path.join(json_file, file_name)
            if os.path.isfile(path):
                data = json.load(open(path))

                # 获取json里面的图片数据,也就是二进制数据
                imageData = data.get("imageData")
                # 如果通过data.get获取到的数据为空,就重新读取图片数据
                if not imageData:
                    imagePath = os.path.join(json_file, data["imagePath"])
                    with open(imagePath, "rb") as f:
                        imageData = f.read()
                        imageData = base64.b64encode(imageData).decode("utf-8")
                #  将二进制数据转变成numpy格式的数据
                img = utils.img_b64_to_arr(imageData)

                for shape in sorted(data["shapes"], key=lambda x: x["label"]):
                    label_name = shape["label"]
                    # print(label_name)
                    if label_name in label_name_to_value:
                        label_value = label_name_to_value[label_name]
                    else: #如果想排除某个类别,就把该类别的label_value置为0
                        # label_value = len(label_name_to_value)
                        label_value = 0
                        label_name_to_value[label_name] = label_value
                lbl, _ = utils.shapes_to_label(img.shape, data["shapes"], label_name_to_value)
                # print(label_name_to_value) #{'_background_': 0, 'SB': 1, 'PI': 0}

                label_names = [None] * (max(label_name_to_value.values()) + 1)
                for name, value in label_name_to_value.items():
                    label_names[value] = name

                # 将输出结果保存
                utils.lblsave(osp.join(out_dir, "%s.png" % file_name.split(".")[0]), lbl)
                logger.info("Saved to: {}".format(out_dir))
    print("label:", label_name_to_value)


if __name__ == "__main__":
    main()
import base64
import json
import os
import os.path as osp
import numpy as np

from labelme.logger import logger
from labelme import utils


def main():
    logger.warning(
        "This script is aimed to demonstrate how to convert the "
        "JSON file to a single image dataset."
    )
    logger.warning(
        "It won't handle multiple JSON files to generate a "
        "real-use dataset."
    )

    # json_file是标注完之后生成的json文件的目录。out_dir是输出目录,即数据处理完之后文件保存的路径
    json_file = r"D:\cnn\deeplabv3-plus-pytorch-main_YUANBAN\datasets\before"
    out_dir = r"D:\cnn\deeplabv3-plus-pytorch-main_YUANBAN\datasets\SegmentationClass-onlyPI"

    # 如果输出的路径不存在,则自动创建这个路径
    if not osp.exists(out_dir):
        os.mkdir(out_dir)
    # 将类别名称转换成数值,以便于计算,此处先定义好每个(部分)类别对应的像素值
    label_name_to_value = {"_background_": 0, "PI": 1}
    for file_name in os.listdir(json_file):
        # 遍历json_file里面所有的文件,并判断这个文件是不是以.json结尾
        if file_name.endswith(".json"):
            path = os.path.join(json_file, file_name)
            if os.path.isfile(path):
                data = json.load(open(path))

                # 获取json里面的图片数据,也就是二进制数据
                imageData = data.get("imageData")
                # 如果通过data.get获取到的数据为空,就重新读取图片数据
                if not imageData:
                    imagePath = os.path.join(json_file, data["imagePath"])
                    with open(imagePath, "rb") as f:
                        imageData = f.read()
                        imageData = base64.b64encode(imageData).decode("utf-8")
                #  将二进制数据转变成numpy格式的数据
                img = utils.img_b64_to_arr(imageData)

                for shape in sorted(data["shapes"], key=lambda x: x["label"]):
                    label_name = shape["label"]
                    # print(label_name)
                    if label_name in label_name_to_value:
                        label_value = label_name_to_value[label_name]
                    else: #如果想排除某个类别,就把该类别的label_value置为0
                        # label_value = len(label_name_to_value)
                        label_value = 0
                        label_name_to_value[label_name] = label_value
                lbl, _ = utils.shapes_to_label(img.shape, data["shapes"], label_name_to_value) #lbl即为对应的mask掩码图
                # print(label_name_to_value) #{'_background_': 0, 'SB': 1, 'PI': 0}
                # print(lbl)

                label_names = [None] * (max(label_name_to_value.values()) + 1)
                for name, value in label_name_to_value.items():
                    label_names[value] = name

                mask_array = np.array(lbl)
                # print(np.unique(mask_array))
                print(np.max(mask_array))
                if np.max(mask_array) == 1: #判断lbl中的像素最大值是否为1,否则为无标注图
                    # 将输出结果保存
                    utils.lblsave(osp.join(out_dir, "%s.png" % file_name.split(".")[0]), lbl)
                    logger.info("Saved to: {}".format(out_dir))
        print("label:", label_name_to_value)


if __name__ == "__main__":
    main()

reference

【标注关键点检测数据集】 https://www.bilibili.com/video/BV19g4y1777q/?share_source=copy_web&vd_source=95705b32f23f70b32dfa1721628d5874

  • 3
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值