赞
踩
LabelImg是一个开源的图形图像注释工具,用于创建边界/矩形框(适用于要标注物体的位置和大小)和多边形注释(适用于标注非规则形状的物体)。它是用Python写的,并使用Qt作为其图形界面。LabelImg能够在Windows、Linux和macOS等多个平台上运行,同时支持各种类型的图像文件格式,如JPG、PNG和BMP等(注:图片格式不是这几种的,可以使用格式工厂转一下即可)。
在LabelImg中,可以选择PASCAL VOC、YOLO和CreateML三种格式进行类别标注,生成的文件类型分别为:
PASCAL VOC——xx.XML文件(常用)
YOLO——xx.txt文件(常用)
CreateML——xx.json文件
CreateML是Apple提供的一种机器学习工具箱,用于构建和训练各种机器学习模型,包括图像分类、目标检测等任务。
Labelimg安装十分方便,不需要去git或者github上下载什么开源代码,使用pip就能直接安装。
建议在conda中创建一个独立的环境来安装图片标注工具(不会使用conda可以看【基础01】 Anaconda+Pycharm让Python开发直接起飞 ),避免忘记安装在哪个环境中,或者与其他环境混淆。
conda create -n labelimg python=3.8
输入y,继续安装
出现以上信息,即创建完成
conda activate labelimg
左边出现你的环境名,即切换成功
pip install labelimg
这里选择默认版本(最新版)安装,你也可以指定labelimg的版本号进行安装
在末尾出现successfully就表示安装成功啦~
若没有安装conda,使用python原生IDLE开发的,可以直接打开cmd命令符窗口
输入pip install labelimg 安装成功后即可
在刚刚创建的环境中直接输入 labelimg
在Labelimg中比较常用的快捷键如下:
快捷键 | 含义 |
w | 绘制矩形框 |
d | 下一张图片 |
a | 上一张图片 |
Del | 删除标注框 |
Ctrl+鼠标滚轮 | 放大/缩小图片 |
Ctrl + + | 放大图片 |
Ctrl + - | 缩小图片 |
Ctrl + s | 保存 |
若打完标签未保存,切换图片时,会出现保存提醒
保存成功后,会在你选择保存标签的文件夹中默认生成两个txt文件:
1.存放标签信息的文件(XXX.txt);
2.存放标签类别的文件(classes.txt)
存放标签信息的文件的文件名为与图片名相同,内容由N行5列数据组成。
每一行代表标注的一个目标,通常包括五个数据,从左到右依次为:类别id、x_center、y_center、width、height。
其中:
类别id代表标注目标的类别;
x_center和y_center代表标注框的相对中心坐标;
width和height代表标注框的相对宽和高。
请注意,这里的中心点坐标、宽和高都是相对数据!!!
存放标签类别的文件的文件名为classes.txt (固定不变),用于存放创建的标签类别。
同样会生成两个文件:
1.存放标签信息的文件(XXX.json);
2.存放标签类别的文件(classes.txt)(若之前存在,则不会再生成)
在生成JSON文件中,每个目标都表示为一个对象,其中包含以下属性:
image:图像文件的名称。
annotation:一个包含所有目标的数组,每个目标都表示为一个对象。包括:
label:目标的类别名称,例如"汽车"、"人"、"自行车"等。
x和y:目标的左上角坐标,表示其在图像中的位置。
width和height:目标的宽度和高度,表示其在图像中的大小。
同样会生成两个文件:
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)物体等。这些信息用于辅助标注和评估目标检测任务的性能。
- 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>')
- 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))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。