【学习笔记】使用python批量读取并修改xml文件(2)

在大老板的安排下最近在某公司实习,实习期间要求实现一个图像识别模块的封装。无奈基础太薄弱,只能将任务细分,单独学习来实现。以此为背景……


这一篇记录一些在实际使用中踩到的。在实际使用中,我在A文件夹下对图片进行了标注,随后将图片移动到B文件夹下。那么相应的,标注后的xml文件中,<path>标签的值就应该修改。

最初的思路是,我遍历了xml文件,那么我只需要将‘新地址’+xml文件写入到新的<path>中即可。

paths[i].firstChild.data='/home/kanghao/SSD-Tensorflow/yibiao512/JPEGImages/'+xmlFile

即这一句代码,使用后发现自己脑子抽了……<path>中的标签值为:

<path>/home/kanghao/learning_something/about_xml/yibiao512/img/a0000000.jpg</path>

重点是后面跟随的是图片的扩展名。

于是想到是否可以再次遍历图片文件夹,获取图片信息之后再与新地址相连?在实际操作中不知如何同时遍历两个文件夹……_(°:з」∠)_秃头

于是采取小黄鸭debug方法,在与小伙伴讲解诉求的过程中猛然发现,我要获取的不就是<filename>标签的值吗?获取了这个值之后,添加的新地址后面就好了呀。于是按照这个思路,完整代码如下:

#coding:utf-8
### V1.0版
### 针对xml文件,要修改的地方是<folder><path><width><height><bndbox>
### 程序瑕疵,在计算bud box时使用float格式,openCV画框函数为int格式
### 因此会产生误差

import os
import os.path
import xml.dom.minidom

#path="../xml/"
path='/home/kanghao/SSD-Tensorflow/yibiao512/Annotations/'
files=os.listdir(path) #得到文件夹下所有文件名称
for xmlFile in files: #遍历文件夹
	
	if not os.path.isdir(xmlFile): #判断是否是文件夹,不是文件夹才打开
		print xmlFile
			
		#xml读取操作		
		#将获取到的xml文件名送入到dom解析
		#错误代码:dom=xml.dom.minidom.parse(xmlFile)
		dom=xml.dom.minidom.parse(os.path.join(path,xmlFile))
		root=dom.documentElement
		
		###获取标签对xmin/ymin之间的值
		# ~ folder=root.getElementsByTagName('folder')
		paths=root.getElementsByTagName('path')
		filenames=root.getElementsByTagName('filename')
		# ~ xmin=root.getElementsByTagName('xmin')
		# ~ ymin=root.getElementsByTagName('ymin')

		# ~ #修改相应标签的值
		# ~ # 修改<folder>
		# ~ for i in range(len(folder)):
			# ~ print folder[i].firstChild.data
			# ~ folder[i].firstChild.data='xml'
			# ~ print folder[i].firstChild.data
		for i in range(len(filenames)):
			fn = filenames[i].firstChild.data
		
		###############################################################################################################		
		### 如何修改path?每个xml文件对应不同名字的图片???                                                                
		### 解决方式如下,测试成功×----------->开始的思路有问题,                                                            
		###paths[i].firstChild.data='/home/kanghao/SSD-Tensorflow/yibiao512/JPEGImages/'+fn语句中,fn使用的是xmlFiles    
		###那么修改后的path中后缀加的是xml文件,不是对应的jpg文件。 思路2————————>直接读取filename标签中的值,添加到地址后即可     
		###############################################################################################################   
		# 修改<path>
		for i in range(len(paths)):
			print paths[i].firstChild.data
			paths[i].firstChild.data='/home/kanghao/SSD-Tensorflow/yibiao512/JPEGImages/'+fn
			print paths[i].firstChild.data
		# ~ # 修改<xmin>	
		# ~ for k in range(len(xmin)):
			# ~ print xmin[k].firstChild.data
			# ~ xia = unicode.encode(xmin[k].firstChild.data)
			# ~ xmin[k].firstChild.data=float(xia)/1.25
			# ~ print xmin[k].firstChild.data
		# ~ # 修改<ymin>	
		# ~ for j in range(len(ymin)):
			# ~ print ymin[j].firstChild.data
			# ~ yia = unicode.encode(ymin[j].firstChild.data)
			# ~ ymin[j].firstChild.data=float(yia)/1.0666667
			# ~ print ymin[j].firstChild.data

		#保存修改到xml文件中
		with open(os.path.join(path,xmlFile),'w') as fh:
			dom.writexml(fh)
		# ~ with open(os.path.join(path2,jpgFile),'w') as fh:
			# ~ dom.writexml(fh)
			print('恭喜,写入xmin/ymin成功!')

那一大坨注释,就是为了方便自己理解……_(°:з」∠)_秃头again。

对了,#coding:utf-8要写在开头,编译器才能以utf-8的各种编译。

one more thing……

我想用openCV的cv2.rectangle()函数来画框,验证我按比例变化是否准确,相关代码如下:

#coding:utf-8
import os
import cv2
import numpy as np
import xml.dom.minidom
import pandas as pd
from PIL import Image, ImageDraw, ImageFont

input_file="/home/kanghao/learning_something/about_xml/xml/"
dirs_name=os.listdir("/home/kanghao/learning_something/about_xml/jpg/") #图片地址


for img in dirs_name:
	
	im=cv2.imread("/home/kanghao/learning_something/about_xml/jpg/"+img) #读取图片
	dom=xml.dom.minidom.parse(input_file+img[:-4]+".xml") # 读取图片对应的label信息 xml文件
	root=dom.documentElement
	
	objs=root.getElementsByTagName("object")
	
	name=[]
	xmin=[]
	ymin=[]
	xmax=[]
	ymax=[] 
	
	for obj in objs:
		
		name1=obj.getElementsByTagName('name')
		n=name1[0].firstChild.data
		xmin1=obj.getElementsByTagName('xmin')
		xi=xmin1[0].firstChild.data
		ymin1=obj.getElementsByTagName('ymin')
		yi=ymin1[0].firstChild.data
		xmax1=obj.getElementsByTagName('xmax')
		xa=xmax1[0].firstChild.data
		ymax1=obj.getElementsByTagName('ymax')
		ya=ymax1[0].firstChild.data
		
		xmin.append(float(xi.strip()))
		print(xmin)
		ymin.append(float(yi.strip()))
		xmax.append(float(xa.strip()))
		ymax.append(float(ya.strip()))
		name.append(n.strip())
		
	for i in range(0,len(xmin)):
		
		#画box
		cv2.rectangle(im, (int(xmin[i]),int(ymin[i])), (int(xmax[i]),int(ymax[i])), (0,255,0), 4)
	
	cv2img = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
	pilimg = Image.fromarray(cv2img)
	draw = ImageDraw.Draw(pilimg)
	# ~ # 写标注
	# ~ for i in range(0,len(xmin)):
		# ~ font = ImageFont.truetype("simhei.ttf", 40, encoding="utf-8")
		# ~ draw.text((xmin[i], ymin[i]-40), name[i], (255, 0, 0), font=font)
		
	cv2charimg = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)
	
	#保存图片
	cv2.imwrite("/home/kanghao/learning_something/about_xml/xml/"+img,cv2charimg)

但是问题来了,cv2.rectangle函数中都是int型的数据类型,我在做了除法之后都是float型数据,因此会在取整时产生误差。误差大概如下图所示:

感觉还能接受……但是还是希望看到的大神指点一下,谢谢!

猜你喜欢

转载自blog.csdn.net/yourgreatfather/article/details/84031289
今日推荐