生活随笔
收集整理的這篇文章主要介紹了
Yolov5 使用精灵标注助手制作数据集
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
精靈標記助手下載:http://www.jinglingbiaozhu.com/
首先點擊菜單文件->新建,然后選擇位置標注,選擇圖片文件夾,點擊創建按鈕,軟件會自動加載文件夾下的圖片(png,jpg,gif)并創建一個項目。
注意:每次標記完一張圖后,要對圖片進行保存,通過快捷鍵 ctrl + s 或者點擊圖片下方的 ?,
當左下角彈出 √保存成功,則證明該張圖片的標記已經保存,如果標記的圖片沒有進行保存,在切換圖片的過程中,前一張的圖片標記框會自動消失,此時需要對圖片重新標記。
快捷鍵
- R:矩形框
- ←:前一張圖片
- →:后一張圖片
- 空格:移動
- 放大縮小圖片:ctrl + 鼠標滾輪
- 保存標記:ctrl + s
所有的數據集標注完成后,將標注的信息導出。
注:選擇導出格式時候必須選擇pascal—voc導出XML直接選擇XML會在后面無法讀取到標注
的信息
導出后,會在目錄中生成一個 outputs 文件夾,導出的文件就是pascal-voc的xml,效果如下:
輸出的標注文件XML保存在Annotations中
數據集標記好后,將原始圖片數據集放到images文件夾中,如圖所示
以下操作是對導出的XML文件和原圖片進行解析。
makeTxt.py
創建 makeTxt.py 文件
makeTxt.py主要是將數據集分類成訓練數據集和測試數據集,默認train,val,test按照8:1:1
的比例進行隨機分類。
import os
import randomtrainval_percent
= 0.9
train_percent
= 0.9
xmlfilepath
= './datasets/Annotations'
txtsavepath
= './datasets/images'
tmage_sets_path
= './datasets/ImageSets'
total_xml
= os
.listdir
(xmlfilepath
)num
= len(total_xml
)
list = range(num
)
tv
= int(num
* trainval_percent
)
tr
= int(tv
* train_percent
)
trainval
= random
.sample
(list, tv
)
train
= random
.sample
(trainval
, tr
)
if not os
.path
.exists
(tmage_sets_path
):os
.makedirs
(tmage_sets_path
)ftrainval
= open('datasets/ImageSets/trainval.txt', 'w')
ftest
= open('datasets/ImageSets/test.txt', 'w')
ftrain
= open('datasets/ImageSets/train.txt', 'w')
fval
= open('datasets/ImageSets/val.txt', 'w')for i
in list:name
= total_xml
[i
][:-4] + '\n'if i
in trainval
:ftrainval
.write
(name
)if i
in train
:ftrain
.write
(name
)else:fval
.write
(name
)else:ftest
.write
(name
)ftrainval
.close
()
ftrain
.close
()
fval
.close
()
ftest
.close
()
voc_label.py
創建 voc_label.py 文件
代碼如下:
classes=[……] 中填入的一定要是自己在數據集中所標注的類別名稱,標記了幾個類別就填寫幾個類別名,填寫錯誤的話會造成讀取不出xml文件里的標注信息。
import xml
.etree
.ElementTree
as ET
import pickle
import os
from os
import listdir
, getcwd
from os
.path
import joinsets
= ['train', 'test', 'val']
classes
= ['杯子', '鍵盤', '鼠標', '手機']
def convert(size
, box
): dw
= 1. / size
[0] dh
= 1. / size
[1] x
= (box
[0] + box
[1]) / 2.0 y
= (box
[2] + box
[3]) / 2.0 w
= box
[1] - box
[0] h
= box
[3] - box
[2] x
= x
* dw w
= w
* dw y
= y
* dh h
= h
* dh
return (x
, y
, w
, h
)
def convert_annotation(image_id
):'''將對應文件名的xml文件轉化為label文件,xml文件包含了對應的bunding框以及圖片長款大小等信息,通過對其解析,然后進行歸一化最終讀到label文件中去,也就是說一張圖片文件對應一個xml文件,然后通過解析和歸一化,能夠將對應的信息保存到唯一一個label文件中去labal文件中的格式:calss x y w h 同時,一張圖片對應的類別有多個,所以對應的bunding的信息也有多個'''in_file
= open('datasets/Annotations/%s.xml' % (image_id
), encoding
='utf-8')out_file
= open('datasets/labels/%s.txt' % (image_id
), 'w', encoding
='utf-8')tree
= ET
.parse
(in_file
)root
= tree
.getroot
()size
= root
.find
('size')if size
!= None:w
= int(size
.find
('width').text
)h
= int(size
.find
('height').text
)for obj
in root
.iter('object'):difficult
= obj
.find
('difficult').textcls
= obj
.find
('name').text
if cls
not in classes
or int(difficult
) == 1:continuecls_id
= classes
.index
(cls
)xmlbox
= obj
.find
('bndbox')b
= (float(xmlbox
.find
('xmin').text
), float(xmlbox
.find
('xmax').text
),float(xmlbox
.find
('ymin').text
), float(xmlbox
.find
('ymax').text
))print(image_id
, cls
, b
)bb
= convert
((w
, h
), b
)out_file
.write
(str(cls_id
) + " " + " ".join
([str(a
) for a
in bb
]) + '\n')
wd
= getcwd
()
print(wd
)for image_set
in sets
:'''對所有的文件數據集進行遍歷做了兩個工作:1.將所有圖片文件都遍歷一遍,并且將其所有的全路徑都寫在對應的txt文件中去,方便定位2.同時對所有的圖片文件進行解析和轉化,將其對應的bundingbox 以及類別的信息全部解析寫到label 文件中去最后再通過直接讀取文件,就能找到對應的label 信息'''if not os
.path
.exists
('datasets/labels/'):os
.makedirs
('datasets/labels/')image_ids
= open('datasets/ImageSets/%s.txt' % (image_set
)).read
().strip
().split
()list_file
= open('datasets/%s.txt' % (image_set
), 'w')for image_id
in image_ids
:list_file
.write
('datasets/images/%s.jpg\n' % (image_id
))convert_annotation
(image_id
)list_file
.close
()
- 分別運行makeTxt.py和voc_label.py。
- makeTxt.py主要是將數據集分類成訓練數據集和測試數據集,默認train,val,test按照8:1:1
的比例進行隨機分類,運行后ImagesSets文件夾中會出現四個文件,主要是生成的訓練數據集和測
試數據集的圖片名稱,同時data目錄下也會出現這四個文件,內容是訓練數據集和測試數據集的圖
片路徑。
labels文件夾下 txt文件的內容如下:
根據數據集會寫一些對圖片文件和txt文件處理的腳本,
例如:以下是在標記數據集的過程中并沒有對一些數據集進行標記然后,將已經標記的數據集進行分開
存放在另一個文件夾中。
import os
, shutil
'''匹配訓練的圖片 和 標記 文件名字是否對應
把對應的名字復制到其它文件中
'''
def mycopyfile(srcfile
, dstfile
): if not os
.path
.isfile
(srcfile
):print("%s not exist!" % (srcfile
))else:fpath
= os
.path
.dirname
(dstfile
) if not os
.path
.exists
(fpath
): os
.makedirs
(fpath
) shutil
.copyfile
(srcfile
, dstfile
) print("copy %s -> %s" % (srcfile
, os
.path
.join
(fpath
, dstfile
)))def operation(images_path
, txt_path
, copy_images_path
, copy_txt_path
):os
.chdir
(images_path
) print("開始復制....")cout
= 0for images_file
in os
.listdir
(images_path
):images_name
= os
.path
.splitext
(images_file
)[0] images_suffix
= os
.path
.splitext
(images_file
)[1] for txt_file
in os
.listdir
(txt_path
):txt_name
= os
.path
.splitext
(txt_file
)[0] txt_suffix
= os
.path
.splitext
(txt_file
)[1] if images_name
== txt_name
:mycopyfile
(images_path
+ images_name
+ images_suffix
, copy_images_path
+ images_name
+ images_suffix
)mycopyfile
(txt_path
+ images_name
+ txt_suffix
, copy_txt_path
+ images_name
+ txt_suffix
)print("images文件復制%s個,txt文件復制%s個,總共復制%s個文件" % (len(os
.listdir
(copy_images_path
)), len(os
.listdir
(copy_txt_path
)), len(os
.listdir
(copy_images_path
)) + len(os
.listdir
(copy_txt_path
))))if __name__
== '__main__':images_path
= 'C:\\Users\\vvcat\\Desktop\\yolov5\\total\\images\\'txt_path
= 'C:\\Users\\vvcat\\Desktop\\yolov5\\total\\labels\\'copy_images_path
= 'C:\\Users\\vvcat\\Desktop\\yolov5\\neaten\\images\\'copy_txt_path
= 'C:\\Users\\vvcat\\Desktop\\yolov5\\neaten\\labels\\'operation
(images_path
, txt_path
, copy_images_path
, copy_txt_path
)
總結
以上是生活随笔為你收集整理的Yolov5 使用精灵标注助手制作数据集的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。