YOLOv5 training cannot find labels, No labels found in /path/train.cache problem solution (available for personal testing)
❤️ Most of the solutions described in tutorials on the Internet are unreliable, and there is no analysis of the cause of the problem. This article completely solves the problem of No labels found in /path/train.cache when YOLOv5 training cannot be found! I hope that through this article, you can solve some unnecessary troubles during the process of configuring the environment. ——©️ Sylvan Ding
Version | system |
---|---|
YOLOv5 v6.1 | Linux |
There No labels found
are two main reasons for this. On the one hand, the data set downloaded from the Internet only provides its own label format and needs to be converted into YOLOv5 format labels; on the other hand, it is because of the organization of the project directory. This article focuses on the latter, that is, the problem of not being able to find tags caused by the organization of the project directory . There are few answers to this type of problem online.
Label format is wrong
Most of the data sets downloaded from the Internet only provide labeled files VOC
in format .xml
, stored in annotations
folders, or labeled files in other formats. At this time, you should first write a program to convert the tags into the format required by YOLOv5.
YOLOv5 tag format description
After using a tool like Roboflow Annotate to label your images, export your labels to YOLO format, with one
*.txt
file per image (if no objects in image, no*.txt
file is required). The*.txt
file specifications are:
- One row per object
- Each row is
class x_center y_center width height
format.- Box coordinates must be in normalized xywh format (from 0 - 1). If your boxes are in pixels, divide
x_center
andwidth
by image width, andy_center
andheight
by image height.- Class numbers are zero-indexed (start from 0).
convert VOC to YOLOv5
For VOC to YOLOv5 format conversion, please refer yolov5/data/VOC.yaml
to line 36 convert_label()
, which convert_box()
provides the coordinate conversion function.
def convert_label(path, lb_path, year, image_id):
def convert_box(size, box):
dw, dh = 1. / size[0], 1. / size[1]
x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2]
return x * dw, y * dh, w * dw, h * dh
in_file = open(path / f'VOC{
year}/Annotations/{
image_id}.xml')
out_file = open(lb_path, 'w')
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
cls = obj.find('name').text
if cls in yaml['names'] and not int(obj.find('difficult').text) == 1:
xmlbox = obj.find('bndbox')
bb = convert_box((w, h), [float(xmlbox.find(x).text) for x in ('xmin', 'xmax', 'ymin', 'ymax')])
cls_id = yaml['names'].index(cls) # class id
out_file.write(" ".join([str(a) for a in (cls_id, *bb)]) + '\n')
Note:
convert_box(size, box)
,bb = convert_box((w, h), [float(xmlbox.find(x).text) for x in ('xmin', 'xmax', 'ymin', 'ymax')])
❤️ For specific implementation details, you can refer to other bloggers’ articles. There are many such articles.
Convert other formats to YOLOv5
For other mark files in different formats, you need to manually write a program to convert them into YOLOv5 format marks.
yolov5/utils/general.py
Some functions in it may give you some inspiration, such as xyxy2xywh()
... xywh2xyxy()
They are responsible for the conversion of coordinate formats.
The structure of the project directory is incorrect
After getting the correct label format, No labels found
errors still occur. At this time, consider that there is an error in the project directory organizational structure.
Correct directory structure
coco
⭐️ Let’s put the conclusion first. Taking COCO as an example, the correct directory structure should be:
# path example
../datasets/coco128/images/im0.jpg # image
../datasets/coco128/labels/im0.txt # label
# yolov5/data/coco.yaml
path: ../datasets/coco # dataset root dir
train: train2017.txt # train images (relative to 'path')
val: val2017.txt # val images
test: test-dev2017.txt
-
datasets
Foldersyolov5
are at the same level as folders, anddatasets
each data set file is created under them. Forcoco
example,images
the folder directly stores all image data , andlabels
the folder directly stores the mark files corresponding to the images*.txt
.. ├── images │ ├── 20151127_114556.jpg │ ├── 20151127_114946.jpg │ └── 20151127_115133.jpg ├── labels │ ├── 20151127_114556.txt │ ├── 20151127_114946.txt │ └── 20151127_115133.txt
-
Note that neither the name
images
norlabels
the name of the folder can be changed to anything else ! The reason will be discussed later. -
train2017.txt
The image file paths of the training set, verification set, and test set are stored in , , and their contents are asval2017.txt
follows :test-dev2017.txt
./images/20151127_114556.jpg ./images/20151127_114946.jpg ./images/20151127_115133.jpg
coco128
If you want to use coco128’s file organization format:
# yolov5/data/coco128.yaml
path: ../datasets/coco128 # dataset root dir
train: images/train2017 # train images (relative to 'path') 128 images
val: images/train2017 # val images (relative to 'path') 128 images
test: # test images (optional)
Then datasets
the directory structure should be:
coco128
├── images
│ ├── test
│ │ └── 20151127_115133.jpg
│ └── train2017
│ └── 20151127_114556.jpg
└── labels
├── test
│ └── 20151127_115133.txt
└── train2017
└── 20151127_114556.txt
- Note that neither the name
images
norlabels
the name of the folder can be changed to anything else ! images
andlabels
folders, create corresponding folders to store the training set, validation set, and test set. The folder names must be consistent. There is no requirement, but they need to be set incoco128.yaml
.
Error cause investigation
yolov5/utils/datasets.py
Line 391 img2label_paths(img_paths)
defines the mapping of image paths to label paths, and self.label_files = img2label_paths(self.im_files) # labels
line 447 calls img2label_paths()
to generate label_files
.
def img2label_paths(img_paths):
# Define label paths as a function of image paths
sa, sb = os.sep + 'images' + os.sep, os.sep + 'labels' + os.sep # /images/, /labels/ substrings
return [sb.join(x.rsplit(sa, 1)).rsplit('.', 1)[0] + '.txt' for x in img_paths]
YOLOv5 locates labels automatically for each image by replacing the last instance of
/images/
in each image path with/labels/
.
That is, YOLOv5 will automatically ../datasets/coco128/images/*.jpg
change the image path ../datasets/coco128/labels/*.txt
to find the labels path!
How to solve the problem?
After the above label_files
assignment and printing label_files
, we can get the marked path, and then modify the file path of our project based on the printed path to solve all problems!