在大老板的安排下最近在某公司实习,实习期间要求实现一个图像识别模块的封装。无奈基础太薄弱,只能将任务细分,单独学习来实现。以此为背景……
这一篇记录一些在实际使用中踩到的坑。在实际使用中,我在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型数据,因此会在取整时产生误差。误差大概如下图所示:
感觉还能接受……但是还是希望看到的大神指点一下,谢谢!