數據轉化為VOC格式:
一、我們先看 VOC格式的數據是什么???
Annotations:存放xml 包括 文件夾信息 圖片名稱、 圖片尺寸信息、 圖片中object的信息。
JPEGImages: 存放圖片
二、分析Wider FACE數據集:
數據集中的txt中信息為:
第一行: 圖片路徑
第二行:多少個人臉
第三行:bbox信息 存儲的左上角 坐標 和 高度寬度
三、代碼轉換:
1 import os,cv2,sys,shutil 2 3 from xml.dom.minidom import Document 4 5 def writexml(filename,saveimg,bboxes,xmlpath,typename): 6 #xml打包的函數,我們不需要知道內部做了什么。 7 #我們只需要將圖片名稱 圖片信息 bbox信息 最終存儲信息 作為參數 就可以了 8 #不需要做修改 9 10 doc = Document() #定義文件對象 11 annotation = doc.createElement('annotation') #創建根節點 12 doc.appendChild(annotation) #存放在doc中 13 # 定義annotation 的子節點 14 folder = doc.createElement('folder') 15 16 folder_name = doc.createTextNode('widerface') 17 folder.appendChild(folder_name) 18 annotation.appendChild(folder) 19 filenamenode = doc.createElement('filename') 20 filename_name = doc.createTextNode(filename) 21 filenamenode.appendChild(filename_name) 22 annotation.appendChild(filenamenode) 23 source = doc.createElement('source') 24 annotation.appendChild(source) 25 database = doc.createElement('database') 26 database.appendChild(doc.createTextNode('wider face Database')) 27 source.appendChild(database) 28 annotation_s = doc.createElement('annotation') 29 annotation_s.appendChild(doc.createTextNode('PASCAL VOC2007')) 30 source.appendChild(annotation_s) 31 image = doc.createElement('image') 32 image.appendChild(doc.createTextNode('flickr')) 33 source.appendChild(image) 34 flickrid = doc.createElement('flickrid') 35 flickrid.appendChild(doc.createTextNode('-1')) 36 source.appendChild(flickrid) 37 owner = doc.createElement('owner') 38 annotation.appendChild(owner) 39 flickrid_o = doc.createElement('flickrid') 40 flickrid_o.appendChild(doc.createTextNode('yanyu')) 41 owner.appendChild(flickrid_o) 42 name_o = doc.createElement('name') 43 name_o.appendChild(doc.createTextNode('yanyu')) 44 owner.appendChild(name_o) 45 46 size = doc.createElement('size') 47 annotation.appendChild(size) 48 49 width = doc.createElement('width') 50 width.appendChild(doc.createTextNode(str(saveimg.shape[1]))) 51 height = doc.createElement('height') 52 height.appendChild(doc.createTextNode(str(saveimg.shape[0]))) 53 depth = doc.createElement('depth') 54 depth.appendChild(doc.createTextNode(str(saveimg.shape[2]))) 55 56 size.appendChild(width) 57 58 size.appendChild(height) 59 size.appendChild(depth) 60 segmented = doc.createElement('segmented') 61 segmented.appendChild(doc.createTextNode('0')) 62 annotation.appendChild(segmented) 63 for i in range(len(bboxes)): 64 bbox = bboxes[i] 65 objects = doc.createElement('object') 66 annotation.appendChild(objects) 67 object_name = doc.createElement('name') 68 object_name.appendChild(doc.createTextNode(typename[i])) #人臉數據的話 直接為 “face” 69 objects.appendChild(object_name) 70 pose = doc.createElement('pose') 71 pose.appendChild(doc.createTextNode('Unspecified')) 72 objects.appendChild(pose) 73 truncated = doc.createElement('truncated') 74 truncated.appendChild(doc.createTextNode('1')) 75 objects.appendChild(truncated) 76 difficult = doc.createElement('difficult') 77 difficult.appendChild(doc.createTextNode('0')) 78 objects.appendChild(difficult) 79 bndbox = doc.createElement('bndbox') 80 objects.appendChild(bndbox) 81 xmin = doc.createElement('xmin') 82 xmin.appendChild(doc.createTextNode(str(bbox[0]))) 83 bndbox.appendChild(xmin) 84 ymin = doc.createElement('ymin') 85 ymin.appendChild(doc.createTextNode(str(bbox[1]))) 86 bndbox.appendChild(ymin) 87 xmax = doc.createElement('xmax') 88 xmax.appendChild(doc.createTextNode(str(bbox[2])))# bbox[0] + 89 bndbox.appendChild(xmax) 90 ymax = doc.createElement('ymax') 91 ymax.appendChild(doc.createTextNode(str(bbox[3])))# bbox[1] + 92 bndbox.appendChild(ymax) 93 f = open(xmlpath, "w") 94 f.write(doc.toprettyxml(indent='')) 95 f.close() 96 97 98 rootdir = "/media/kuan/新加卷/wider_face" #定義數據集的根目錄wider_face 下載好的 99 100 101 def convertimgset(img_set): #解析函數 img_set 作為解析的路徑 img_sets = ["train","val"] 102 imgdir = rootdir + "/WIDER_" + img_set + "/images" #圖片文件的路徑 103 gtfilepath = rootdir + "/wider_face_split/wider_face_" + img_set + "_bbx_gt.txt" #標注信息 104 fwrite = open(rootdir + "/ImageSets/Main/" + img_set + ".txt", 'w') #寫入txt中 main 底下的文件夾 對應140行 105 index = 0 #表示解析到第幾張圖 106 with open(gtfilepath, 'r') as gtfiles: #打開真值文件,獲取bbox 107 while(True): #true index< 1000 #前1000個樣本 108 filename = gtfiles.readline()[:-1] #讀取一行數據, 為圖像路徑 109 if filename == None or filename == "": 110 break 111 imgpath = imgdir + "/" + filename #圖片的絕對路徑 112 img = cv2.imread(imgpath) #拿到讀取圖片 可以獲取到shape信息 113 if not img.data: 114 break; 115 numbbox = int(gtfiles.readline()) #讀取到了第二行 人臉個數 116 bboxes = [] 117 print(numbbox) 118 for i in range(numbbox): #讀取bbox信息 numbbox 行 119 line = gtfiles.readline() 120 lines = line.split(" ") 121 lines = lines[0:4] 122 123 bbox = (int(lines[0]), int(lines[1]), int(lines[2]), int(lines[3])) #存儲的左上角 坐標 和 高度寬度 124 125 if int(lines[2]) < 40 or int(lines[3]) < 40: 126 continue 127 128 bboxes.append(bbox) #存放到bbox中 numbbox個人臉信息 129 130 #cv2.rectangle(img, (bbox[0],bbox[1]),(bbox[0]+bbox[2],bbox[1]+bbox[3]),color=(255,255,0),thickness=1) 131 132 filename = filename.replace("/", "_") #圖片的名稱存儲 133 134 if len(bboxes) == 0: 135 print("no face") 136 continue 137 #cv2.imshow("img", img) 138 #cv2.waitKey(0) 139 cv2.imwrite("{}/JPEGImages/{}".format(rootdir,filename), img) #寫入圖像JPEGImages 140 fwrite.write(filename.split(".")[0] + "\n") #寫入txt中 main 底下的文件夾 141 xmlpath = "{}/Annotations/{}.xml".format(rootdir,filename.split(".")[0]) 142 writexml(filename, img, bboxes, xmlpath) #調用函數 143 print("success number is ", index) 144 index += 1 145 146 fwrite.close() 147 148 if __name__=="__main__": 149 img_sets = ["train","val"] 150 for img_set in img_sets: 151 convertimgset(img_set) 152 #修改文件名 153 shutil.move(rootdir + "/ImageSets/Main/" + "train.txt", rootdir + "/ImageSets/Main/" + "trainval.txt") 154 shutil.move(rootdir + "/ImageSets/Main/" + "val.txt", rootdir + "/ImageSets/Main/" + "test.txt")
通過上面三個步驟我們就生成了VOC格式的數據集,現在我們只需要放到工程目錄下並且進行修改 就可以開始訓練了。
詳細修改方法見下:
https://www.cnblogs.com/WSX1994/p/11216953.html