当前位置:   article > 正文

使用自己训练的yolov3或yolov4模型自动标注成voc格式数据_yolov4标注格式

yolov4标注格式

yolo数据格式转voc格式:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time :2021/8/31 下午3:06
  4. # @Author :
  5. # @ProjectName :mmdetection-master
  6. # @File :yolo2voc.py
  7. # @Description :
  8. import os
  9. import codecs
  10. import cv2
  11. def vocXMLFormat(filePath, imgName, imgW, imgH, objNames, locs, depth=3, truncated=0, difficult=0):
  12. """
  13. Generate xml annotation file,eg:
  14. vocXMLFormat("0000.xml", "0001.png", 608, 608, ["person", "TV"], [[24, 32, 156, 145], [124, 76, 472, 384]])
  15. Args:
  16. filePath:The path of the file saved in the generated xml
  17. imgName:xml file annotates the name of the picture
  18. imgW:
  19. imgH:
  20. objNames:The object contained in the picture, format: ["object label 1", "object label 2"...]
  21. locs:The picture contains the coordinates of the object, format: [[x,y,w,h],[x,y,w,h]...]
  22. depth:
  23. truncated:
  24. difficult:
  25. Returns:
  26. """
  27. if (objNames == None) or (locs == None):
  28. print("The objNames or locs is None!!!")
  29. return
  30. with codecs.open(filePath, 'w', 'utf-8') as xml:
  31. xml.write('<?xml version="1.0" encoding="UTF-8"?>\n')
  32. xml.write('<annotation>\n')
  33. xml.write('\t<folder>' + 'voc format' + '</folder>\n')
  34. xml.write('\t<filename>' + imgName + '</filename>\n')
  35. xml.write('\t<path>' + imgName + '</path>\n')
  36. xml.write('\t<source>\n')
  37. xml.write('\t\t<database>weiz</database>\n')
  38. xml.write('\t</source>\n')
  39. xml.write('\t<size>\n')
  40. xml.write('\t\t<width>' + str(imgW) + '</width>\n')
  41. xml.write('\t\t<height>' + str(imgH) + '</height>\n')
  42. xml.write('\t\t<depth>' + str(depth) + '</depth>\n')
  43. xml.write('\t</size>\n')
  44. xml.write('\t<segmented>0</segmented>\n')
  45. for ind, name in enumerate(objNames):
  46. xml.write('\t<object>\n')
  47. xml.write('\t\t<name>' + name + '</name>\n')
  48. xml.write('\t\t<pose>Unspecified</pose>\n')
  49. xml.write('\t\t<truncated>' + str(truncated) + '</truncated>\n')
  50. xml.write('\t\t<difficult>' + str(difficult) + '</difficult>\n')
  51. xml.write('\t\t<bndbox>\n')
  52. xml.write('\t\t\t<xmin>' + str(locs[ind][0]) + '</xmin>\n')
  53. xml.write('\t\t\t<ymin>' + str(locs[ind][1]) + '</ymin>\n')
  54. xml.write('\t\t\t<xmax>' + str(locs[ind][0] + locs[ind][2]) + '</xmax>\n')
  55. xml.write('\t\t\t<ymax>' + str(locs[ind][1] + locs[ind][3]) + '</ymax>\n')
  56. xml.write('\t\t</bndbox>\n')
  57. xml.write('\t</object>\n')
  58. xml.write('</annotation>')
  59. xml.close()
  60. print("The {} accomplish!".format(filePath))
  61. def read_line(file_name):
  62. """
  63. read file by line
  64. :param file_name:
  65. :return:
  66. """
  67. lines = []
  68. file = open(file_name)
  69. for line in file:
  70. line = line.strip('\n')
  71. lines.append(line)
  72. file.close()
  73. return lines
  74. def showAnnotions(image, locs, labels):
  75. """
  76. show annotions
  77. :param locs:
  78. :param labels:
  79. :return:
  80. """
  81. for ind, (x, y, w, h) in enumerate(locs):
  82. cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
  83. cv2.putText(image, labels[ind], (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1)
  84. cv2.imshow("iamge", image)
  85. cv2.waitKey(30)
  86. txt_path = "/home/zyy/桌面/label"
  87. image_path = "/home/zyy/桌面/images"
  88. save_xml_path = "/home/zyy/桌面/xml"
  89. def main():
  90. txt_list = os.listdir(txt_path)
  91. label_list = read_line("/home/zyy/桌面/label.txt")
  92. for txt_name in txt_list:
  93. image_name, _ = os.path.splitext(txt_name)
  94. for extension in ["png", "jpg"]: # read image
  95. image_name_path = image_name + '.' + extension
  96. image_name_path = os.path.join(image_path, image_name_path)
  97. if os.path.exists(image_name_path):
  98. image = cv2.imread(image_name_path)
  99. image_h, image_w, image_channel = image.shape
  100. break
  101. else:
  102. continue
  103. txt_name_path = os.path.join(txt_path, txt_name)
  104. lines = read_line(txt_name_path)
  105. object_locs = []
  106. object_labels = []
  107. for line in lines:
  108. ind, center_x, center_y, w, h = line.split(' ')
  109. x = (float(center_x) - float(w) / 2) * image_w
  110. y = (float(center_y) - float(h) / 2) * image_h
  111. w = float(w) * image_w
  112. h = float(h) * image_h
  113. object_locs.append([int(x), int(y), int(w), int(h)])
  114. object_labels.append(label_list[int(ind)])
  115. # showAnnotions(image, object_locs, object_labels)
  116. xml_name_path = os.path.join(save_xml_path, image_name + ".xml")
  117. vocXMLFormat(xml_name_path, os.path.split(image_name_path)[-1], image_w, image_h, object_labels, object_locs, image_channel)
  118. if __name__ == "__main__":
  119. main()

信息都在代码里,只需要自己实现getLabelInfo(img)检测部分即可,也可以参考我写的

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time :2020/11/3 14:00
  4. # @Author :weiz
  5. # @ProjectName :autoLabeling
  6. # @File :dataLabeling.py
  7. # @Description :数据标注文件
  8. import os
  9. import codecs
  10. import cv2
  11. import yoloMain
  12. def vocXMLFormat(filePath, imgName, imgW, imgH, objNames, locs, depth=3, truncated=0, difficult=0):
  13. """
  14. 生成xml数据文件;eg:
  15. vocXMLFormat("0000.xml", "0001.png", 608, 608, ["person", "TV"], [[24, 32, 156, 145], [124, 76, 472, 384]])
  16. :param filePath: 生成xml所保存文件的路径
  17. :param imgName: xml文件标注图片的名字
  18. :param imgW: 图片的宽
  19. :param imgH: 图片的高
  20. :param objNames: 图片包含的目标,格式:["目标1","目标2"...]
  21. :param locs: 图片包含目标的坐标,格式:[[x,y,w,h],[x,y,w,h]...]
  22. :param depth: 图片的深度,默认是3
  23. :param truncated: 是否被截断(0表示完整)
  24. :param difficult: 目标是否难以识别(0表示容易识别)
  25. :return:
  26. """
  27. if (objNames == None) or (locs == None):
  28. print("The objNames or locs is None!!!")
  29. return
  30. with codecs.open(filePath, 'w', 'utf-8') as xml:
  31. xml.write('<?xml version="1.0" encoding="UTF-8"?>\n')
  32. xml.write('<annotation>\n')
  33. xml.write('\t<folder>' + 'voc format' + '</folder>\n')
  34. xml.write('\t<filename>' + imgName + '</filename>\n')
  35. xml.write('\t<path>' + imgName + '</path>\n')
  36. xml.write('\t<source>\n')
  37. xml.write('\t\t<database>weiz</database>\n')
  38. xml.write('\t</source>\n')
  39. xml.write('\t<size>\n')
  40. xml.write('\t\t<width>' + str(imgW) + '</width>\n')
  41. xml.write('\t\t<height>' + str(imgH) + '</height>\n')
  42. xml.write('\t\t<depth>' + str(depth) + '</depth>\n')
  43. xml.write('\t</size>\n')
  44. xml.write('\t<segmented>0</segmented>\n')
  45. for ind, name in enumerate(objNames):
  46. xml.write('\t<object>\n')
  47. xml.write('\t\t<name>' + name + '</name>\n')
  48. xml.write('\t\t<pose>Unspecified</pose>\n')
  49. xml.write('\t\t<truncated>' + str(truncated) + '</truncated>\n')
  50. xml.write('\t\t<difficult>' + str(difficult) + '</difficult>\n')
  51. xml.write('\t\t<bndbox>\n')
  52. xml.write('\t\t\t<xmin>' + str(locs[ind][0]) + '</xmin>\n')
  53. xml.write('\t\t\t<ymin>' + str(locs[ind][1]) + '</ymin>\n')
  54. xml.write('\t\t\t<xmax>' + str(locs[ind][0] + locs[ind][2]) + '</xmax>\n')
  55. xml.write('\t\t\t<ymax>' + str(locs[ind][1] + locs[ind][3]) + '</ymax>\n')
  56. xml.write('\t\t</bndbox>\n')
  57. xml.write('\t</object>\n')
  58. xml.write('</annotation>')
  59. xml.close()
  60. print("The {} accomplish!".format(filePath))
  61. def autoLabeling(yoloModel, modelSign, savePath, img, imgName=None, extraName=None, depth=3, truncated=0, difficult=0):
  62. """
  63. 生成标注图片img的xml文件
  64. :param yoloModel: yolov3或者yolov4
  65. :param modelSign: 模型标识位,3表示yolov3,4表示yolov4
  66. :param savePath: 保存路径
  67. :param img: 图片
  68. :param imgName: 图片的名字
  69. :param extraName: 附加额外的名字:默认是从000001.png开始命名图片;如果该参数为hsh,则命名从hsh_000001.png开始
  70. :param depth: 图片的深度
  71. :param truncated: 是否被截断(0表示完整)
  72. :param difficult: 目标是否难以识别(0表示容易识别)
  73. :return:
  74. """
  75. global savePathFolderNum
  76. if savePathFolderNum == -1:
  77. try:
  78. savePathFolderNum = 0
  79. fileList = os.listdir(savePath)
  80. for file in fileList: # 统计png文件的个数
  81. if "png" in os.path.splitext(file)[-1]:
  82. savePathFolderNum = savePathFolderNum + 1
  83. except FileNotFoundError:
  84. os.mkdir(savePath)
  85. savePathFolderNum = 0
  86. if imgName == None: # 确定保存图片的名字
  87. if extraName != None:
  88. imgName = extraName + '_' + "{:0>6d}".format(savePathFolderNum)
  89. else:
  90. imgName = "{:0>6d}".format(savePathFolderNum)
  91. else:
  92. if extraName != None:
  93. imgName = extraName + '_' + imgName
  94. imgPath = os.path.join(savePath, imgName + ".png")
  95. xmlPath = os.path.join(savePath, imgName + ".xml")
  96. locs, labels = getLabelInfo(yoloModel, modelSign, img)
  97. if len(labels) > 0:
  98. savePathFolderNum = savePathFolderNum + 1
  99. vocXMLFormat(xmlPath, imgName + ".png", img.shape[1], img.shape[0], labels, locs, depth, truncated, difficult)
  100. cv2.imwrite(imgPath, img)
  101. return locs, labels
  102. def getLabelInfo(yoloModel, modelSign, img):
  103. """
  104. 实现图片的检测,并返回标注信息,eg:
  105. labels = ["person", "TV"]
  106. locs = [[24, 32, 156, 145], [124, 76, 472, 384]]
  107. :param yoloModel:
  108. :param modelSign:
  109. :param img:
  110. :return: 返回labels和locs,格式:["目标1","目标2"...]和[[x,y,w,h],[x,y,w,h]...]
  111. """
  112. if modelSign == 3:
  113. boxes, labels, confs, timeLabel = yoloMain.runningYolov3(yoloModel, img)
  114. else:
  115. boxes, labels, confs, timeLabel = yoloMain.runningYolov4(yoloModel, img)
  116. locs = []
  117. if boxes == []:
  118. return locs, labels
  119. for x1, y1, x2, y2 in boxes:
  120. w = x2 - x1
  121. h = y2 - y1
  122. locs.append([x1, y1, w, h])
  123. return locs, labels
  124. def showAnnotions(image, locs, labels):
  125. """
  126. 显示标注
  127. :param locs:
  128. :param labels:
  129. :return:
  130. """
  131. for ind, (x, y, w, h) in enumerate(locs):
  132. cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
  133. cv2.putText(image, labels[ind], (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1)
  134. def videoAnnotation(videoPath, savePath, gap=10, yoloModels=3):
  135. """
  136. 自动标注视频数据
  137. :param videoPath: 视频的路径
  138. :param savePath: 标注后保存的路径
  139. :param gap: 每多少帧才标注
  140. :param yoloModels: 使用yolov3或者yolov4模型,默认使用yolov3
  141. :return:
  142. """
  143. if yoloModels != 4: # 使用yolov3
  144. yoloModels = yoloMain.getYolov3()
  145. modelSign = 3
  146. else: # 使用yolov4
  147. yoloModels = yoloMain.getYolov4()
  148. modelSign = 4
  149. cap = cv2.VideoCapture(videoPath)
  150. frameNum = 0
  151. videoName = os.path.splitext(os.path.basename(videPath))[0]
  152. while True:
  153. ok, img = cap.read()
  154. frameNum = frameNum + 1
  155. if not ok:
  156. break
  157. if frameNum % gap != 0:
  158. continue
  159. locs, labels = autoLabeling(yoloModels, modelSign, savePath, img, extraName=videoName)
  160. showAnnotions(img, locs, labels)
  161. cv2.imshow('video', img)
  162. if cv2.waitKey(1) & 0xFF == 27:
  163. cap.release() # 关闭摄像头
  164. break
  165. cv2.destroyAllWindows()
  166. def imagesAnnotation(imagesPath, savePath, yoloModels=3):
  167. """
  168. 图片自动标注
  169. :param imagesPath:
  170. :param savePath:
  171. :param yoloModels:
  172. :return:
  173. """
  174. if yoloModels != 4: # 使用yolov3
  175. yoloModels = yoloMain.getYolov3()
  176. modelSign = 3
  177. else: # 使用yolov4
  178. yoloModels = yoloMain.getYolov4()
  179. modelSign = 4
  180. imagesList = os.listdir(imagesPath)
  181. for imageName in imagesList:
  182. imagePath = os.path.join(imagesPath, imageName)
  183. image = cv2.imread(imagePath)
  184. locs, labels = autoLabeling(yoloModels, modelSign, savePath, image, os.path.splitext(imageName)[0])
  185. showAnnotions(image, locs, labels)
  186. cv2.imshow("image", image)
  187. if cv2.waitKey(1) & 0xFF == 27:
  188. break
  189. cv2.destroyAllWindows()
  190. videPath = "./videos/004.avi"
  191. imagesPath = "./srcImages" # 待标注的图片
  192. savePath = "C:/Users/weiz/Desktop/annotions" # 该文件可以不存在,会自动创建
  193. savePathFolderNum = -1 # 所存路径文件的个数,-1表示还没有读取
  194. yoloMoels = 3 # 3表示使用yolov3模型标注,4表示使用yolov4标注
  195. if __name__ == "__main__":
  196. #videoAnnotation(videPath, savePath, 10, yoloMoels)
  197. imagesAnnotation(imagesPath, savePath, yoloMoels)

        c++版本写入xml文件。

  1. #include <iostream>
  2. #include <fstream>
  3. #include <vector>
  4. #include <string>
  5. /*
  6. imgPath:图片存储路径,eg:./abcdeg/ssf.png
  7. objNames:目标的labels
  8. locs:与objNames对应的位置信息,存储格式是[x,y,w,h]
  9. imgW:图片宽
  10. imgH:图片高
  11. */
  12. int vocXMLFormat(const std::string& imgPath, const std::vector<std::string>& objNames, const std::vector<std::vector<int>>& locs, int imgW, int imgH, int depth = 3, int truncated = 0, int difficult = 0) {
  13. std::string xmlPath;
  14. std::string imgName;
  15. int point_index = -1;
  16. int img_name_index = imgPath.length() - 1;
  17. while (('/' != imgPath[img_name_index]) && (img_name_index >= 0)) {
  18. if ((point_index < 0) && ('.' == imgPath[img_name_index])) {
  19. point_index = img_name_index;
  20. }
  21. // 适配windows的路径
  22. if ('\\' == imgPath[img_name_index]) {
  23. break;
  24. }
  25. img_name_index = img_name_index - 1;
  26. }
  27. xmlPath = imgPath.substr(0, point_index) + ".xml";
  28. imgName = imgPath.substr(img_name_index + 1, imgPath.length());
  29. std::cout << "xml save path:" << xmlPath << " img name:" << imgName << std::endl;
  30. std::ofstream xmlFile(xmlPath);
  31. if (xmlFile) {
  32. std::string data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  33. xmlFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  34. xmlFile << "<annotation>\n";
  35. xmlFile << "\t<folder>voc format</folder>\n";
  36. xmlFile << "\t<filename>" + imgName + "</filename>\n";
  37. xmlFile << "\t<path>" + imgPath + "</path>\n";
  38. xmlFile << "\t<source>\n";
  39. xmlFile << "\t\t<database>weiz</database>\n";
  40. xmlFile << "\t</source>\n";
  41. xmlFile << "\t<size>\n";
  42. xmlFile << "\t\t<width>" + std::to_string(imgW) + "</width>\n";
  43. xmlFile << "\t\t<height>" + std::to_string(imgH) + "</height>\n";
  44. xmlFile << "\t\t<depth>" + std::to_string(depth) + "</depth>\n";
  45. xmlFile << "\t</size>\n";
  46. xmlFile << "\t<segmented>0</segmented>\n";
  47. for (int i = 0; i < objNames.size(); ++i) {
  48. xmlFile << "\t<object>\n";
  49. xmlFile << "\t\t<name>" + objNames[i] + "</name>\n";
  50. xmlFile << "\t\t<pose>Unspecified</pose>\n";
  51. xmlFile << "\t\t<truncated>" + std::to_string(truncated) + "</truncated>\n";
  52. xmlFile << "\t\t<difficult>" + std::to_string(difficult) + "</difficult>\n";
  53. xmlFile << "\t\t<bndbox>\n";
  54. xmlFile << "\t\t\t<xmin>" + std::to_string(locs[i][0]) + "</xmin>\n";
  55. xmlFile << "\t\t\t<ymin>" + std::to_string(locs[i][1]) + "</ymin>\n";
  56. xmlFile << "\t\t\t<xmax>" + std::to_string(locs[i][0] + locs[i][2]) + "</xmax>\n";
  57. xmlFile << "\t\t\t<ymax>" + std::to_string(locs[i][1] + locs[i][3]) + "</ymax>\n";
  58. xmlFile << "\t\t</bndbox>\n";
  59. xmlFile << "\t</object>\n";
  60. }
  61. xmlFile << "</annotation>";
  62. xmlFile.close();
  63. }
  64. else {
  65. std::cerr << "无法打开文件!" << std::endl;
  66. return 1;
  67. }
  68. return 0;
  69. }
  70. int main()
  71. {
  72. //seg_roi();
  73. std::string imgPath = "./sdfdsfe.jpeg";
  74. std::vector<std::string> objNames = {"sss","bbb"};
  75. std::vector<std::vector<int>> locs;
  76. std::vector<int> aa = { 1,2,3,4 };
  77. std::vector<int> bb = { 5,6,7,8 };
  78. locs.push_back(aa); locs.push_back(bb);
  79. vocXMLFormat(imgPath, objNames, locs, 1920, 1080);
  80. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/728058
推荐阅读
相关标签
  

闽ICP备14008679号