一 、简介
VOC文件目录结构
├── Annotations
├── ImageSets
│ └── Main
├── JPEGImages
- 1、需要在Annotations文件下生成所有图片对用的xml文件
- 2、ImageSets
└── Main 是存放txt文件,2007train.txt 2007test.txt 2007val.txt txt文件里面包含是图片名称(没有后缀):例如 00001 - 3、 JPEGImages存放所有图片
- 如果数据需要自己标注,可以利用labelImg ,详细安装链接可浏览我之前博客:https://blog.csdn.net/jmu201521121021/article/details/79199159
- 下面代码主要功能是我的数据集的label存放在自己txt里面,所以需要转换为xml格式。 由于我的数据坐标是0起始的,所以在 writeXml 函数中 box = labelData[i:i+4]+1操作。
- 我的label txt文件格式: 图片名.png xmin ymin xmax ymax classId xmin ymin xmax ymax classId …
例如: 一行数据:000016_01_01_030.png 272.0707 210.0586 305.85938 232.12881 0 72.85157 178.02774 118.359665 224.31621 0 - 主功能函数 def makeVOC
2、 代码
import cv2
import shutil
import numpy as np
import os
from xml.dom.minidom import Document
# 新建文件夹
def checkWay(way):
if not os.path.exists(way):
os.makedirs(way)
# 获取 txt文件信息
def getRoidbs(filePath)::
inputFp = open(filePath,'r')
datas = inputFp.readlines()
roidbs = []
for roidb in datas:
roidb = roidb.strip('\n')
roidb = roidb.split(' ')
roidbs.append(roidb)
return roidbs
# 生成保存图片的名称txt和复制图片到JPEGImages
def setJpeg(roidb,imageFolder,vocJpegWay, vocImageSetsMainWay,mode):
imageName = roidb[0]
imagePath = imageFolder+imageName
outFile= open(vocImageSetsMainWay+mode+'.txt','a')
outFile.write(imageName.split('.')[0]+'\n') # 写入图片名称
outFile.close()
shutil.copy(imagePath,vocJpegWay+imageName) # 复制图片
def writeXml(roidb, imageFolder,vocXmlWay,vocJpegWay):
imageName = roidb[0]
labelData = np.array(roidb[1:],dtype=float)
bboxes = []
classId = []
imagePath = imageFolder+imageName
img = cv2.imread(imagePath) # 获取图 w h
h = img.shape[0]
w = img.shape[1]
for i in range(0,len(labelData),5) : # 获取 xmin ymin xmax ymax
box = labelData[i:i+4]+1
cls_id = int(labelData[i+4])
for j in range(4):
if box[j] < 1:
box[j] = 1
for j in range(0,4,2):
if box[j] > w:
box[j] = w
for j in range(1,4,2):
if box[j] > h:
box[j] = h
assert box[2]>=box[0], 'box[2]>=box[0]'
assert box[3]>=box[1], 'box[3]>=box[1]'
assert box[0]>=1,'x1<0'
assert box[1]>=1,'y1<0'
assert box[2]>=1,'x2<0'
assert box[3]>=1,'y2<0'
assert box[0]<=w,'x1>w'
assert box[1]<=h,'y1>h'
assert box[2]<=w,'x2>w'
assert box[3]<=h,'y2>h'
assert cls_id == 0 ,'class id erro !=0'
bboxes.append(box)
className = ''
if cls_id == 0:
className = 'lesion'
classId.append(className)
# 制作xml
folder_txt=vocJpegWay.split('/')[-2]
doc=Document()
annotation=doc.createElement('annotation')
doc.appendChild(annotation)
#folder
folder = doc.createElement('folder')
folder_txt = doc.createTextNode(folder_txt)
folder.appendChild(folder_txt)
annotation.appendChild(folder)
#filename
filename = doc.createElement('filename')
filename_txt = doc.createTextNode(imageName.split('.')[0])
filename.appendChild(filename_txt)
annotation.appendChild(filename)
#path
path = doc.createElement('path')
path_txt = doc.createTextNode(vocJpegWay+imageName)
path.appendChild(path_txt)
annotation.appendChild(path)
#size
size = doc.createElement('size')
annotation.appendChild(size)
#width
width = doc.createElement('width')
width_txt = doc.createTextNode(str(w))
width.appendChild(width_txt)
size.appendChild(width)
#height
height = doc.createElement('height')
height_txt = doc.createTextNode(str(h))
height.appendChild(height_txt)
size.appendChild(height)
#depth
depth = doc.createElement('depth')
depth_txt = doc.createTextNode('3')
depth.appendChild(depth_txt)
size.appendChild(depth)
#segmented
segmented = doc.createElement('segmented')
segmented_txt = doc.createTextNode('0')
segmented.appendChild(segmented_txt)
annotation.appendChild(folder)
object1=[]
for i in range(len(bboxes)):
object1.append('name'+str(i))
object1[i]= doc.createElement('object')
annotation.appendChild(object1[i])
#name
name = doc.createElement('name')
name_txt = doc.createTextNode(classId[i])
name.appendChild(name_txt)
object1[i].appendChild(name)
#pose
pose = doc.createElement('pose')
pose_txt = doc.createTextNode('Unspecified')
pose.appendChild(pose_txt)
object1[i].appendChild(pose)
#truncated
truncated = doc.createElement('truncated')
truncated_txt = doc.createTextNode('0')
truncated.appendChild(truncated_txt)
object1[i].appendChild(truncated)
#difficult
difficult = doc.createElement('difficult')
difficult_txt = doc.createTextNode('0')
difficult.appendChild(difficult_txt)
object1[i].appendChild(difficult)
#bndbox
bndbox = doc.createElement('bndbox')
object1[i].appendChild(bndbox)
#xmin
xmin = doc.createElement('xmin')
xmin_txt = doc.createTextNode(str(int(bboxes[i][0])))
xmin.appendChild(xmin_txt)
bndbox.appendChild(xmin)
#ymin
ymin = doc.createElement('ymin')
ymin_txt = doc.createTextNode(str(int(bboxes[i][1])))
ymin.appendChild(ymin_txt)
bndbox.appendChild(ymin)
#xmax
xmax = doc.createElement('xmax')
xmax_txt = doc.createTextNode(str(int(bboxes[i][2])))
xmax.appendChild(xmax_txt)
bndbox.appendChild(xmax)
#ymax
ymax = doc.createElement('ymax')
ymax_txt = doc.createTextNode(str(int(bboxes[i][3])))
ymax.appendChild(ymax_txt)
bndbox.appendChild(ymax)
xmlName=vocXmlWay+imageName.split('.')[0]+'.xml' # 写入xml
f=open(xmlName,'w')
doc.writexml(f,indent = '\t',newl = '\n', addindent = '\t',encoding='utf-8')
f.close()
## vocJpegWay JPEGImages的路径
## vocImageSetsMainWay Main文件路径
## labelTxtPath 输入txt文件路径
## imageFolde 原始图片路径
## mode 训练 测试 验证三种模式
def makeVOC( vocXmlWay,
vocJpegWay,
vocImageSetsMainWay,
labelTxtPath,
imageFolder,
mode
):
roidbs = getRoidbs(labelTxtPath)
cnt = 1
for roidb in roidbs:
print(cnt,':processed--->',roidb[0])
writeXml(roidb, imageFolder,vocXmlWay,vocJpegWay)
setJpeg(roidb,imageFolder,vocJpegWay, vocImageSetsMainWay,mode)
cnt += 1