【cv视觉】标注工具的使用和数据集的创建
目录
目标
环境准备
1.环境要求
2.目标要求
标注软件
1.labelimg标注软件的安装
2. labelimg使用说明
3. 标签文件解释
4.数据集的划分
LabelImg 是数据标注领域常用的开源工具,主要用于计算机视觉任务中对图像进行矩形框目标检测标注。它能让标注人员通过鼠标拖拽的方式在图像上快速绘制边界框,为每个框指定对应的目标类别,并将标注结果保存为 PASCAL VOC 格式的 XML 文件(包含目标坐标、类别等信息),这些标注数据可直接用于训练 YOLO、Faster R-CNN 等目标检测模型,是深度学习数据预处理阶段实现图像目标定位与分类标注的高效工具。
目标
labelimg标注软件的安装和使用;
掌握数据集和测试集的创建和划分
环境准备
1.环境要求
(1) PC机
(2) matplotlib>=3.2.2
(3) numpy>=1.18.5,<1.24.0
(4) opencv-python>=4.1.1
(5) Pillow>=7.1.2
(6) PyYAML>=5.3.1
(7) requests>=2.23.0
(8) scipy>=1.4.1
(9) torch>=1.7.0,!=1.12.0
(10) torchvision>=0.8.1,!=0.13.0
(11) tqdm>=4.41.0
(12) protobuf<4.21.3
2.目标要求
(1) 掌握labelimg标注软件的安装和使用;
(2) 掌握数据集和测试集的创建和划分。
标注软件
使用labelimg标注软件对图片进行yolo标签格式标注,划分训练,验证,测试集。
(1) 划分图片和标签文件夹
(2) 使用labelimg进行标注保存标注的标签文件
(3) 使用代码进行图片和标签的数据集和测试集的创建和划分
1.labelimg标注软件的安装
图片标注主要是为了建立自己的数据集,便于进行更深度的学习训练。
labelimg 是一个可视化的图像标定工具。它是用Python编写的,并将Qt用于其图形界面。批注以PASCAL VOC格式(ImageNet使用的格式)另存为XML文件。此外,它还支持YOLO格式。Faster R-CNN,YOLO,SSD等目标检测网络所需要的数据集,均需要借此工具标定图像中的目标。
在安装labelimg之前,我们需要先进行一个环境搭建,搭建环境之后再进行labelimg的安装和使用。
labelimg的安装和使用
安装labelimg
打开我们第一节创建的虚拟环境
在命令行窗口中依次输入下列代码,安装labelimg依赖的第三方库。
代码1 安装labelimg
pip install PyQt5 pip install pyqt5-tools pip install lxml pip install labelimg |
安装labelimg,安装成功截图如下
至此,环境配置步骤已经全部完成。在第三方库安装完成后,在命令行中输入labelimg指令以启动labelimg(注:环境配置完成后再次启动只需要打开anaconda prompt命令行并输入labelimg即可启动,无需再次安装第三方库)。
进入labelimg标注工具的初始化界面如下图所示。
2. labelimg使用说明
使用labelimg进行数据集标注
labelimg的标注模式分为VOC和YOLO两种,两种模式下生成的标注文件分别为.xml文件和.txt文件,因此在进行标注前需要优先选择好标注的模式。
labelimg左侧菜单栏中按钮功能说明如下。
在labelimg中,标注的快捷键为w,标注后用鼠标拖动锚框进行框选,框选完毕后会弹出类别选择框,如果是当前已有类则直接选择即可,若需要新加类别则在输入框中输入类别标签并确定。
图6
(YOLO标注模式下)标注完成后数据集整体结构如下图所示。
图7
3. 标签文件解释
使用labelimg标注产生的结果如下。
用labelimg以YOLO模式进行标注产生的标注文件如下,classes.txt文件中存放的是类别标签,标签文件中以类别+锚框的位置坐标信息进行保存,文件中有几行则说明对应的标注图像中有几个锚框。
图8
使用labelimg以YOLO模式进行标注产生的标注文件如下,classes.txt文件中存放的是类别标签,标签文件中以类别+锚框的位置坐标信息进行保存,文件中有几行则说明对应的标注图像中有几个锚框。
图9
labelimg操作快捷键汇总
标注常用快捷键如下所示。
(1) Ctrl + s 保存当前改动(注:切换图片时若未保存则会进行询问)
(2) Ctrl + d 复制当前标签和矩形框
(3) space 将当前图像标记为已验证
(4) w 创建一个矩形框
(5) d 下一张图片
(6) Del 删除选定的矩形框
(7) Ctrl + +/Ctrl + 滚轮向前 放大
(8) Ctrl + -/Ctrl + 滚轮向后 缩小
(9) ↑→↓← 键盘箭头移动选定的矩形框
在labelimg的view菜单栏中可进行选项设置来进一步提高标注效率,如下图所示
图10
在上图中可以勾选“Auto Save mode”来使程序自动保存标注结果,而无需再框选目标后点击“Save”按钮手动保存。
4.数据集的划分
创建一个工程 建立两个文件夹,一个文件夹存放标记的TXT文件,一个存放图像文件的文件。
图11
代码1存储文件路径和切分比例
import shutil
import random
import os
#原始路径
image_original_path = "imge"
label_original_path = "Annotations"
cur_path = os.getcwd()
#训练集路径
train_image_path = os.path.join(cur_path, "images/train/")
train_label_path = os.path.join(cur_path, "labels/train/")
#验证集路径
val_image_path = os.path.join(cur_path, "images/val/")
val_label_path = os.path.join(cur_path, "labels/val/")
#测试集路径
test_image_path = os.path.join(cur_path, "images/test/")
test_label_path = os.path.join(cur_path, "labels/test/")
#训练集目录
list_train = os.path.join(cur_path, "train.txt")
list_val = os.path.join(cur_path, "val.txt")
list_test = os.path.join(cur_path, "test.txt")
train_percent = 0.8
val_percent = 0.1
test_percent = 0.1
代码2删除文件和创建目录以及清除文件的函数
def del_file(path):for i in os.listdir(path):file_data = os.path.join(path, i)os.remove(file_data)
def mkdir():if not os.path.exists(train_image_path):os.makedirs(train_image_path)else:del_file(train_image_path)if not os.path.exists(train_label_path):os.makedirs(train_label_path)else:del_file(train_label_path)if not os.path.exists(val_image_path):os.makedirs(val_image_path)else:del_file(val_image_path)if not os.path.exists(val_label_path):os.makedirs(val_label_path)else:del_file(val_label_path)if not os.path.exists(test_image_path):os.makedirs(test_image_path)else:del_file(test_image_path)if not os.path.exists(test_label_path):os.makedirs(test_label_path)else:del_file(test_label_path)
def clearfile():if os.path.exists(list_train):os.remove(list_train)if os.path.exists(list_val):os.remove(list_val)if os.path.exists(list_test):os.remove(list_test)
代码3主函数 main()
def main():mkdir()clearfile()file_train = open(list_train, 'w')file_val = open(list_val, 'w')file_test = open(list_test, 'w')total_txt = os.listdir(label_original_path)num_txt = len(total_txt)list_all_txt = range(num_txt)num_train = int(num_txt * train_percent)num_val = int(num_txt * val_percent)num_test = num_txt - num_train - num_valtrain = random.sample(list_all_txt, num_train)# train从list_all_txt取出num_train个元素# 所以list_all_txt列表只剩下了这些元素val_test = [i for i in list_all_txt if not i in train]# 再从val_test取出num_val个元素,val_test剩下的元素就是testval = random.sample(val_test, num_val)print("训练集数目:{}, 验证集数目:{}, 测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))for i in list_all_txt:name = total_txt[i] # 注意这里直接使用 total_txt[i] 作为文件名srcImage = os.path.join(image_original_path, name[:-4] + '.jpg')srcLabel = os.path.join(label_original_path, name)# 注意这里不需要再加.txtif i in train:name_without_extension = name[:-4] # 去掉文件名的后缀dst_train_Image = os.path.join(train_image_path, name_without_extension + '.jpg')dst_train_Label = os.path.join(train_label_path, name_without_extension + '.txt')shutil.copy(srcImage, dst_train_Image)shutil.copy(srcLabel, dst_train_Label)
file_train.write(dst_train_Image + '\n')elif i in val:name_without_extension = name[:-4] # 去掉文件名的后缀dst_val_Image = os.path.join(val_image_path, name_without_extension + '.jpg')dst_val_Label = os.path.join(val_label_path, name_without_extension + '.txt')shutil.copy(srcImage, dst_val_Image)shutil.copy(srcLabel, dst_val_Label)file_val.write(dst_val_Image + '\n')else:name_without_extension = name[:-4] # 去掉文件名的后缀dst_test_Image = os.path.join(test_image_path, name_without_extension + '.jpg')dst_test_Label = os.path.join(test_label_path, name_without_extension + '.txt')shutil.copy(srcImage, dst_test_Image)shutil.copy(srcLabel, dst_test_Label)file_test.write(dst_test_Image + '\n')file_train.close()file_val.close()file_test.close()if __name__ == "__main__":main()