图像识别模型中图片标注文件的txt和xml类型相互转换

图像识别学习记录

最近学习图像识别在训练模型时需要将不同模型需要的标注格式来回批量转换,本文介绍了2种方法可以将XML和TXT标注信息相互转换。
网上看了很别人的例子但是发现很多都会在顶部出现,<?xml version=‘1.0’>’。
在这里插入图片描述
尝试了很多方法后发现https://blog.csdn.net/donkey_1993/article/details/96327270和https://blog.csdn.net/weixin_43202256/article/details/83185089的思路很有效,就是通过一个已存在的标准格式的XML文件将其他的在这上面做修改后输出成新的XML文件。这种方法就不会存在注释且简单代码量少。

————————————————
版权声明:本文为CSDN博主「和美琪一起的日子里」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_43202256/article/details/83185089

一.TXT to XML

首先介绍第一种TXT转成XML格式
我的txt文件的格式如下存储了图片信息的txt文件格式(filename x_min,y_min,x_max,y_max,label)
我做的是一个人和带帽子人的识别,0为没戴帽子的人,1为带帽子的人。
我的txt格式
要批量转换的xml文件格式如下
我的模板格式

from lxml.etree import Element, SubElement, tostring, ElementTree
import numpy as np
import cv2
import copy




def cv_imread(file_path):
    cv_img=cv2.imdecode(np.fromfile(file_path,dtype=np.uint8),-1)#当图片的路径存在中文时,使用此函数读图就不会报错了
    return cv_img
def TXTtoXML(train_file,folderphoto,savepathfinal):
    with open(train_file) as f:
        trainfiles = f.readlines()
        tree = ElementTree()
        for line in trainfiles:
            trainFile = line.split()#将该行按空格切分
            #print(trainFile,(len(trainFile)))
            path = folderphoto+trainFile[0]
            filename=trainFile[0]
            print(filename)
            print(type(filename))
            photonum=filename[0:-4]
            jpg_dirtory = path
            img_name = jpg_dirtory.split('/')[-1]
            print(path)
            im = cv_imread(path)
            w = im.shape[1] #img.shape[1]是图片的宽度
            h = im.shape[0]#img.shape[0]是图片的高度
            d = im.shape[2]#img.shape[0]是图片的深度
            # print w,h,d
            tree.parse(template_file)
            root = tree.getroot()
            root.find('filename').text = img_name
            root.find('path').text = path
            sz=root.find('size')
            sz.find('height').text = str(w)
            sz.find('width').text = str(h)
            sz.find('depth').text = str(d)
            print(path)
            print(len(trainFile))#检测到人的个数减一
            for i in range(1,len(trainFile),1):
                detail= trainFile[i].split(',')
                #print(type(detial))
                xmin = str(int(float(detail[0])))
                ymin = str(int(float(detail[1])))
                xmax = str(int(float(detail[2])))
                ymax = str(int(float(detail[3])))
                label = detail[4]#类型我这里用0表示person,1表示带hat带帽子的人
                print(xmin, ymin, xmax, ymax, label)  # 判断有多少个空格分隔的,第0个是文件名,第1个是第一个目标的信息,第二个是第二个目标的信息。将其用‘,’分割
                if i==1:#因为我这是多目标检测所以需要加个判断,当只有一个框的时候替换原来的模板上的object
                    obj = root.find('object')
                    obj.find('name').text = label.replace('0', 'person').replace('1','hat')
                    bb = obj.find('bndbox')
                    bb.find('xmin').text = xmin
                    bb.find('ymin').text = ymin
                    bb.find('xmax').text = xmax
                    bb.find('ymax').text = ymax
                else:#当写入第二个以上框的数据时添加ojbect
                    root = tree.getroot()
                    obj_ori = root.find('object')
                    obj = copy.deepcopy(obj_ori)  # 注意这里深拷贝
                    obj.find('name').text = label.replace('0', 'person').replace('1','hat')
                    bb = obj.find('bndbox')
                    bb.find('xmin').text = xmin
                    bb.find('ymin').text = ymin
                    bb.find('xmax').text = xmax
                    bb.find('ymax').text = ymax
                    root.append(obj)

            savepath=savepathfinal+photonum+'.xml'
            tree.write(savepath, encoding='utf-8')

if __name__ == "__main__":
    template_file = 'E:/000000.xml'#XML实例
    train_file = 'C:/Users/YXY/Desktop/TXTNEW/yidabiao.txt' # 存储了图片信息的txt文件格式(filename x_min,y_min,x_max,y_max,label)
    folderphoto='C:/Users/YXY/Desktop/python脚本工具/photo/'#原始图片的路径
    savepathfinal=r'E:/testxml/'#生成的xml文件存储路径
    TXTtoXML(train_file,folderphoto,savepathfinal)

二.XML to TXT

接下来介绍将XML转换成txt的代码,转换后的格式就跟最上面的txt内的内容一样。

import os
import os.path
import xml.etree.ElementTree as ET
import glob


def xml_to_txt(xmlpath,txtpath):

    os.chdir(xmlpath)
    annotations = os.listdir('.')
    annotations = glob.glob(str(annotations)+'*.xml')
    file_save = '/'+'train' + '.txt'
    file_txt = os.path.join(txtpath, file_save)
    f_w = open(file_txt, 'w')

    for i,file in enumerate(annotations):

        in_file = open(file,encoding='gb18030', errors='ignore')#可能是文本中会出现的一些特殊符号超出了gbk的编码范围,可以选择编码范围更广的‘gb18030’
        tree=ET.parse(in_file)
        root = tree.getroot()

        L= ''
        filename = root.find('filename').text

        for obj in root.iter('object'):
                name = obj.find('name').text

                class_num = class_names.index(name)

                xmlbox = obj.find('bndbox')

                x1 = xmlbox.find('xmin').text
                x2 = xmlbox.find('xmax').text
                y1 = xmlbox.find('ymin').text
                y2 = xmlbox.find('ymax').text
                L+=x1+','+y1+','+x2+','+y2+','+str(class_num)+' '
        f_w.write(filename+' '+L+'\n')

if __name__ == "__main__":
    class_names = ['person','hat']#看你自己时用的哪些字符对分类进行命名对应修改。
    xmlpath='E:/testxml'
    txtpath='E:/testtxt'
    xml_to_txt(xmlpath,txtpath)

————————————————

要使用Python调用SVM训练的XML模型识别图片并标出目标位置,需要进行以下步骤: 1. 导入所需的Python库和模块: ``` import cv2 import numpy as np import xml.etree.ElementTree as ET ``` 2. 加载训练好的XML模型 ``` tree = ET.parse("svm_model.xml") root = tree.getroot() svm = cv2.ml.SVM_load(str(root[1].text)) ``` 此处采用了Python的xml.etree.ElementTree模块加载了XML模型,并通过OpenCV的cv2.ml.SVM_load函数进行了加载。 3. 加载需要识别的图片,并对其进行预处理 ``` img = cv2.imread("test.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.equalizeHist(gray) ``` 读取需要识别的图片,并将其转换为灰度图像,并对其进行直方图均衡化处理。 4. 在图像进行目标识别 ``` _, contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) roi = gray[y:y+h, x:x+w] roi = cv2.resize(roi, (80, 80)) hog = cv2.HOGDescriptor((80, 80), (40, 40), (20, 20), (10, 10), 9) features = hog.compute(roi) features = np.transpose(features) _, result = svm.predict(features) if result == 1: cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) ``` 在图像找到所有的轮廓,并依次对每个轮廓进行处理。对于每个轮廓,首先获取其所在矩形的坐标,再从原图将其提取出来,并将其resize至80x80。然后利用HOG算法对其特征进行提取,并将特征向量带入之前加载的SVM模型进行识别。若结果为1,则认为该矩形是目标区域,将其用矩形框标出。 5. 显示标注后的图像 ``` cv2.imshow("result", img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 最后,将标注后的图像展示给用户。 需要注意的是,上述代码没有给出如何提取轮廓的方法,因此在实际使用时,需要根据具体问题进行调整。同时,由于SVM需要对特征向量作为输入,因此关于特征的提取也需要进行一定的调整,使其能够最大程度地反映出图片的目标信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值