【数据准备001】标注工具Labelimg安装与使用(附txt与xml文件相互转化代码)

本文介绍了开源图形图像注释工具LabelImg,支持多种格式的标注,包括PASCALVOC、YOLO和CreateML。详细讲解了安装步骤、LabelImg的使用方法,以及不同格式文件之间的转换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

        LabelImg是一个开源的图形图像注释工具,用于创建边界/矩形框(适用于要标注物体的位置和大小)和多边形注释(适用于标注非规则形状的物体)。它是用Python写的,并使用Qt作为其图形界面。LabelImg能够在Windows、Linux和macOS等多个平台上运行,同时支持各种类型的图像文件格式,如JPGPNGBMP等(注:图片格式不是这几种的,可以使用格式工厂转一下即可)。

        在LabelImg中,可以选择PASCAL VOCYOLOCreateML三种格式进行类别标注,生成的文件类型分别为:

        PASCAL VOC——xx.XML文件(常用)

        YOLO——xx.txt文件(常用)

        CreateML——xx.json文件

        CreateML是Apple提供的一种机器学习工具箱,用于构建和训练各种机器学习模型,包括图像分类、目标检测等任务。


二、Labelimg工具的安装

        Labelimg安装十分方便,不需要去git或者github上下载什么开源代码,使用pip就能直接安装

1. conda 安装

        建议在conda中创建一个独立的环境来安装图片标注工具(不会使用conda可以看​【Python基础000】Anaconda+Pycharm让Python开发直接起飞​ ),避免忘记安装在哪个环境中,或者与其他环境混淆。

        (1)创建环境

conda create -n labelimg python=3.8

        输入y,继续安装

        出现以上信息,即创建完成

        (2)激活环境,安装工具

        a. 激活环境
 conda activate labelimg

        左边出现你的环境名,即切换成功

        b. 安装工具
pip install labelimg

        这里选择默认版本(最新版)安装,你也可以指定labelimg的版本号进行安装

        在末尾出现successfully就表示安装成功啦~

2. Pip安装

        若没有安装conda,使用python原生IDLE开发的,可以直接打开cmd命令符窗口

        输入pip install labelimg 安装成功后即可


三、Labelimg工具的使用

1. 打开工具

        (1)打开工具

        在刚刚创建的环境中直接输入 labelimg

        (2)基本功能介绍

        (3)快捷键

        在Labelimg中比较常用的快捷键如下:

快捷键

含义

w

绘制矩形框

d

下一张图片

a

上一张图片

Del

删除标注框

Ctrl+鼠标滚轮

放大/缩小图片

Ctrl + +

放大图片

Ctrl + -

缩小图片

Ctrl + s

保存

2. 使用工具

        (1)选择YOLO模式创建标签

        若打完标签未保存,切换图片时,会出现保存提醒

        保存成功后,会在你选择保存标签的文件夹中默认生成两个txt文件

                1.存放标签信息的文件(XXX.txt);

                2.存放标签类别的文件(classes.txt)

        存放标签信息的文件的文件名为与图片名相同,内容由N行5列数据组成。

        每一行代表标注的一个目标,通常包括五个数据,从左到右依次为:类别idx_centery_centerwidthheight

        其中:

                类别id代表标注目标的类别

                x_center和y_center代表标注框的相对中心坐标

                width和height代表标注框的相对宽和高

        请注意,这里的中心点坐标、宽和高都是相对数据!!!

        存放标签类别的文件的文件名为classes.txt (固定不变),用于存放创建的标签类别。

        (2)选择create ML模式创建标签

        同样会生成两个文件:

                1.存放标签信息的文件(XXX.json);

                2.存放标签类别的文件(classes.txt)(若之前存在,则不会再生成)

        在生成JSON文件中,每个目标都表示为一个对象,其中包含以下属性

                image:图像文件的名称。

                annotation:一个包含所有目标的数组,每个目标都表示为一个对象。包括:

                label:目标的类别名称,例如"汽车"、"人"、"自行车"等。

                x和y:目标的左上角坐标,表示其在图像中的位置。

                width和height:目标的宽度和高度,表示其在图像中的大小。

        (3)选择PascalVOC模式创建标签

        同样会生成两个文件:

                1.存放标签信息的文件(XXX.xml);

                2.存放标签类别的文件(classes.txt)(若之前存在,则不会再生成)

        每个XML文件对应一个图像文件,文件中包含了对图像的解释。具体来说,XML文件里标记了物体框的坐标和类别等信息。对于用户自定义数据,可根据实际情况对这些字段进行标注。

        在XML文件中,关键信息包括:

                folder:图像所在文件夹名

                filename:图像文件的名称

                path:图像所在路径

                size:图像的尺寸,包括宽度、高度和通道数

                object:标注框的信息,包括:

                        name:物体框对应的类别名称

                        bndbox:物体框的信息,包括左上角和右下角的坐标

                                xmin:图像左上角x坐标

                                ymin:图像左上角y坐标

                                xmax:图像右下角x坐标

                                ymax:图像右下角y坐标

        此外,XML文件中还可能包含其他相关信息,例如物体框的遮挡情况(pose)、是否被截断(truncated)、是否是难检测(difficult)物体等。这些信息用于辅助标注和评估目标检测任务的性能。

四、YOLO格式文件与VOC格式文件相互转换

        1. txt2xml

def Txt2XML(input_txt_dir, output_xml_dir, image_dir, class_txt):
    # 获取txt文件的目录列表
    txt_files = os.listdir(input_txt_dir)
    # 获取图像的目录列表
    image_files = os.listdir(image_dir)
    image_infos = []
    for txt_file in txt_files:
        file_name, file_ext = os.path.splitext(txt_file)
        for image_file in image_files:
            images = []
            image_name, image_ext = os.path.splitext(image_file)
            if image_ext == '.jpg':
                # 判断图像名是否与txt文件名相同
                if image_name == file_name:
                    images.append(image_file)
                    # 读取txt文件中的标注信息
                    with open(os.path.join(input_txt_dir, txt_file), 'r') as f:
                        bboxes = []
                        for line in f.readlines():
                            bbox_id, x_center, y_center, width, height = line.strip().split()
                            x_center = float(x_center)    # 相对坐标
                            y_center = float(y_center)    # 相对坐标
                            width = float(width)          # 相对坐标
                            height = float(height)        # 相对坐标

                            bbox = (bbox_id, x_center, y_center, width, height)
                            bboxes.append(bbox)
                        images.append(bboxes)
                    image_infos.append(images)
    # 获取标注框的类别列表
    class_names = []
    with open(class_txt, 'r') as classes:
        for class_name in classes.readlines():
            class_names.append(class_name.strip())

    # 遍历每个图像文件,获取图像的高度和宽度,并将标注信息写入XML文件
    for image_info in image_infos:
        image_file = image_info[0]
        image_name, image_ext = os.path.splitext(image_file)
        image_path = os.path.join(image_dir, image_file)
        img = cv2.imread(image_path)
        image_height, image_width, num_channels = img.shape[:3]   # 获取图片的高度、宽度和通道数

        # 创建XML文件并写入标注信息
        with open(os.path.join(output_xml_dir, image_name+'.xml'), 'a') as f:
            f.write('<annotation>\n')
            # 图像位置信息
            f.write('\t<filename>{}</filename>\n'.format(image_file))
            f.write('\t<path>{}</path>\n'.format(image_path))
            # 图像尺寸信息
            f.write('\t<size>\n')
            f.write('\t\t<width>{}</width>\n\t\t<height>{}</height>\n\t\t<depth>{}</depth>\n'.format(image_width, image_height, num_channels))
            f.write('\t</size>\n')
            # 图像类别、坐标信息
            bboxes = image_info[1]
            for bbox in bboxes:
                bbox_id, x_center, y_center, width, height = bbox
                xmin = (x_center * image_width) - (width * image_width)/2      # 计算标注框左上角x坐标值
                ymin = (y_center * image_height) - (height * image_height)/2   # 计算标注框左上角y坐标值
                xmax = (x_center * image_width) + (width * image_width)/2      # 计算标注框右下角x坐标值
                ymax = (y_center * image_height) + (height * image_height)/2   # 计算标注框右下角y坐标值

                f.write('\t<object>\n')
                f.write('\t\t<name>{}</name>\n'.format(class_names[int(bbox_id)].strip()))
                f.write('\t\t<pose>Unspecified</pose>\n')
                f.write('\t\t<truncated>0</truncated>\n')
                f.write('\t\t<difficult>0</difficult>\n')
                f.write('\t\t<bndbox>\n')
                f.write('\t\t\t<xmin>{}</xmin>\n\t\t\t<ymin>{}</ymin>\n\t\t\t<xmax>{}</xmax>\n\t\t\t<ymax>{}</ymax>\n'.format(int(xmin), int(ymin), int(xmax), int(ymax)))
                f.write('\t\t</bndbox>\n')

                f.write('\t</object>\n')
            f.write('</annotation>')

        2. xml2txt

def XML2txt(input_dir, output_dir, class_txt):
    # 获取所有XML文件列表
    xml_files = os.listdir(input_dir)
    # 获取标注框的类别列表
    class_names = []
    with open(class_txt, 'r') as classes:
        for class_name in classes.readlines():
            class_names.append(class_name.split())

    # 遍历每个XML文件
    for xml_file in xml_files:
        # 获取文件名和扩展名
        file_name, file_ext = os.path.splitext(xml_file)
        # 确保是XML文件
        if file_ext == '.xml':
            # 解析XML文件并获取标注信息
            tree = ET.parse(os.path.join(input_dir, xml_file))
            root = tree.getroot()

            # 获取图像的最大宽度和高度
            max_width = float(root.find('size').find('width').text)
            max_height = float(root.find('size').find('height').text)

            # 获取标注框的坐标信息
            bndbox_coords = []
            for obj in root.findall('object'):
                bbox_type = obj.find('name').text
                type_id = class_name.index(bbox_type)
                bndbox = obj.find('bndbox')
                xmin = float(bndbox.find('xmin').text)
                ymin = float(bndbox.find('ymin').text)
                xmax = float(bndbox.find('xmax').text)
                ymax = float(bndbox.find('ymax').text)
                bndbox_coords.append((type_id, xmin, ymin, xmax, ymax))

            # 计算YOLO所需的格式并写入输出文件
            with open(os.path.join(output_dir, file_name + '.txt'), 'w') as f:
                for coords in bndbox_coords:
                    type_id, xmin, ymin, xmax, ymax = coords
                    x_center = (xmin + xmax) / 2 / max_width    # x_center字段计算,相对坐标
                    y_center = (ymin + ymax) / 2 / max_height   # y_center字段计算,相对坐标
                    width = (xmax - xmin) / max_width           # width字段(相对宽)计算
                    height = (ymax - ymin) / max_height         # height字段(相对高)计算
                    f.write('{} {:.6f} {:.6f} {:.6f} {:.6f}\n'.format(type_id, x_center, y_center, width, height))

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值