目标检测图像数据预处理阶段常用的脚本集合

保持图片格式统一

import os
import cv2 as cv
 
image_path = 'J:/102HorizontalProject/zong/image'    #设置图片读取的路径
save_path = 'J:/yolov5-master-cow/data/images'    #设置图片保存的路径
 
if not os.path.exists(save_path):    #判断路径是否正确,如果正确就打开
    os.makedirs(save_path)
 
image_file = os.listdir(image_path)
 
for image in image_file:
    if image.split('.')[-1] in ['bmp', 'jpg', 'jpeg', 'png', 'JPG', 'PNG']:
        str = image.rsplit(".", 1)    #从右侧判断是否有符号“.”,并对image的名称做一次分割。如112345.jpeg分割后的str为["112345","jpeg"]
        output_img_name = str[0] + ".jpg"    #取列表中的第一个字符串与“.jpg”放在一起。
        src = cv.imread(os.path.join(image_path, image))
        newimg = cv.imwrite(save_path + '/' + output_img_name, src)
print('FINISHED')

拍照后的图像进行缩放resize到指定长宽大小。用到cv2。

import os
import cv2

'''设置原始图片存放路径,不能有中文'''
datadir = "F:/picdata/SISD10raw/"

'''设置目标像素大小,此处设为1280'''
IMG_SIZE = 1280

'''使用os.path模块的join方法生成路径'''
path = os.path.join(datadir)

'''使用os.listdir(path)函数,返回path路径下所有文件的名字,以及文件夹的名字'''
img_list = os.listdir(path)

for i in img_list:
    img_array = cv2.imread(os.path.join(path, i), cv2.IMREAD_COLOR)
    '''调用cv2.resize函数resize图片'''
    new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE))
    img_name = str(i)  # 保存的图片与处理前图片同名
    '''生成图片存储的目标路径'''
    save_path = 'F:/picdata/SISD10/'+str(i)
    '''调用cv.2的imwrite函数保存图片'''
    cv2.imwrite(save_path, new_array)

jpg图片名字批量重命名rename,总位数一致,都是0开头,右对齐。

import os


def myrename(path):
    file_list = os.listdir(path)
    for i, fi in enumerate(file_list):
        old_dir = os.path.join(path, fi)
        filename = str(i + 1) + "." + str(fi.split(".")[-1])
        new_dir = os.path.join(path, filename)
        try:
            os.rename(old_dir, new_dir)
        except Exception as e:
            print(e)
            print("Failed!")
        else:
            print("SUcess!")


if __name__ == "__main__":
    path = r"F:/picdata/SISD10"
    myrename(path)
    # myrename执行后图片按1,2,3,,,,顺序
    # 执行后面的代码,将进一步修改为00001,00002,00003,,,,
    filelist = os.listdir(path)
    filetype = '.jpg'
    for file in filelist:
        Olddir = os.path.join(path, file)
        if os.path.isdir(Olddir):
            continue
        # os.path.splitext("path"):分离文件名与扩展名
        filename = os.path.splitext(file)[0]
        filetype = os.path.splitext(file)[1]
        print(filename.zfill(5))
        # zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0
        Newdir = os.path.join(path, filename.zfill(5) + filetype)  # 数字5是定义为5位数,可随意修改需要的
        print(Newdir)
        os.rename(Olddir, Newdir)

 多人协同打标的情况下,xml文件路径可能不同,   需要把 <path>F:\picdata\SISD10\00001.jpg</path>

批量改成G盘目录,保持一致。注意转义符\\

<path>G:\picdata\SISD10\00001.jpg</path>

多字段要替换,就继续用if

import os

if __name__=='__main__':

    work_dir = 'F:/picdata/test/test1/'
    new_dir = 'F:/picdata/test/test2/'
    for parent, dirnames, filenames in os.walk(work_dir,  followlinks=True):
        for filename in filenames:
            file_path = os.path.join(parent, filename)
            file = open(file_path,"r+",encoding='UTF-8')
            newFile = open(new_dir + filename,"w",encoding='UTF-8')
            for line in file.readlines():
                if("F:\\" in line):
                    line = line.replace("F:\\","G:\\")
                newFile.writelines(line)
            print (filename)
            newFile.close()
            file.close()

 yolov7需要的数据文件结构,如果已经有yolov5格式划分好的数据集,如

datasets
├─images
│  ├─test
│  ├─train
│  └─val
├─labels
   ├─test
   ├─train
   └─val

则用这个代码生成datasets目录下3个txt文件:train.txtval.txttest.txt

参考:http://t.csdn.cn/AAWoJ

import os
from tqdm import tqdm

if __name__ == '__main__':
    rootdir = 'G:/A_lwd_paper/linetrash_datasets_new/A_data_samewithautol911'
    rootimagesdir = os.path.join(rootdir, 'images')
    rootlabelsdir = os.path.join(rootdir, 'labels')
    assert os.path.exists(rootimagesdir), f'{rootimagesdir} not exists.'
    assert os.path.exists(rootlabelsdir), f'{rootlabelsdir} not exists.'

    imagesets = ['train', 'val', 'test']    # 将images/train val test中的图像的绝对地址分别写入txt中

    for sets in imagesets:
        imagesdir = os.path.join(rootimagesdir, sets)
        with open(os.path.join(rootdir, f'{sets}.txt'), 'w') as f:
            filelist = os.listdir(imagesdir)
            for images in tqdm(filelist):
                f.write(os.path.join(imagesdir, images) + '\n')

labelme2voc

#!/usr/bin/env python

from __future__ import print_function

import argparse
import glob
import os
import os.path as osp
import sys

import imgviz
import numpy as np

import labelme


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    parser.add_argument("input_dir", help="input annotated directory")
    parser.add_argument("output_dir", help="output dataset directory")
    parser.add_argument("--labels", help="labels file", required=True)
    parser.add_argument(
        "--noviz", help="no visualization", action="store_true"
    )
    args = parser.parse_args()

    if osp.exists(args.output_dir):
        print("Output directory already exists:", args.output_dir)
        sys.exit(1)
    os.makedirs(args.output_dir)
    os.makedirs(osp.join(args.output_dir, "JPEGImages"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClass"))
    os.makedirs(osp.join(args.output_dir, "SegmentationClassPNG"))
    if not args.noviz:
        os.makedirs(
            osp.join(args.output_dir, "SegmentationClassVisualization")
        )
    os.makedirs(osp.join(args.output_dir, "SegmentationObject"))
    os.makedirs(osp.join(args.output_dir, "SegmentationObjectPNG"))
    if not args.noviz:
        os.makedirs(
            osp.join(args.output_dir, "SegmentationObjectVisualization")
        )
    print("Creating dataset:", args.output_dir)

    class_names = []
    class_name_to_id = {}
    for i, line in enumerate(open(args.labels).readlines()):
        class_id = i - 1  # starts with -1
        class_name = line.strip()
        class_name_to_id[class_name] = class_id
        if class_id == -1:
            assert class_name == "__ignore__"
            continue
        elif class_id == 0:
            assert class_name == "_background_"
        class_names.append(class_name)
    class_names = tuple(class_names)
    print("class_names:", class_names)
    out_class_names_file = osp.join(args.output_dir, "class_names.txt")
    with open(out_class_names_file, "w") as f:
        f.writelines("\n".join(class_names))
    print("Saved class_names:", out_class_names_file)

    for filename in glob.glob(osp.join(args.input_dir, "*.json")):
        print("Generating dataset from:", filename)

        label_file = labelme.LabelFile(filename=filename)

        base = osp.splitext(osp.basename(filename))[0]
        out_img_file = osp.join(args.output_dir, "JPEGImages", base + ".jpg")
        out_cls_file = osp.join(
            args.output_dir, "SegmentationClass", base + ".npy"
        )
        out_clsp_file = osp.join(
            args.output_dir, "SegmentationClassPNG", base + ".png"
        )
        if not args.noviz:
            out_clsv_file = osp.join(
                args.output_dir,
                "SegmentationClassVisualization",
                base + ".jpg",
            )
        out_ins_file = osp.join(
            args.output_dir, "SegmentationObject", base + ".npy"
        )
        out_insp_file = osp.join(
            args.output_dir, "SegmentationObjectPNG", base + ".png"
        )
        if not args.noviz:
            out_insv_file = osp.join(
                args.output_dir,
                "SegmentationObjectVisualization",
                base + ".jpg",
            )

        img = labelme.utils.img_data_to_arr(label_file.imageData)
        imgviz.io.imsave(out_img_file, img)

        cls, ins = labelme.utils.shapes_to_label(
            img_shape=img.shape,
            shapes=label_file.shapes,
            label_name_to_value=class_name_to_id,
        )
        ins[cls == -1] = 0  # ignore it.

        # class label
        labelme.utils.lblsave(out_clsp_file, cls)
        np.save(out_cls_file, cls)
        if not args.noviz:
            clsv = imgviz.label2rgb(
                cls,
                imgviz.rgb2gray(img),
                label_names=class_names,
                font_size=15,
                loc="rb",
            )
            imgviz.io.imsave(out_clsv_file, clsv)

        # instance label
        labelme.utils.lblsave(out_insp_file, ins)
        np.save(out_ins_file, ins)
        if not args.noviz:
            instance_ids = np.unique(ins)
            instance_names = [str(i) for i in range(max(instance_ids) + 1)]
            insv = imgviz.label2rgb(
                ins,
                imgviz.rgb2gray(img),
                label_names=instance_names,
                font_size=15,
                loc="rb",
            )
            imgviz.io.imsave(out_insv_file, insv)


if __name__ == "__main__":
    main()

xml_to_yolo_rotation

类别,cx,cy,w,h,angle

#!/usr/bin/env python
# coding: utf-8

# ## convert xml to [yolov5-rotation](https://github.com/acai66/yolov5_rotation) format. [旋转版yolov5](https://github.com/acai66/yolov5_rotation)标签格式转换

# In[1]:


import xml.etree.ElementTree as ET
from tqdm import tqdm # pip install tqdm
import os
import math


# In[2]:


workdir = 'H:/picdata/' # datasets root path. 数据集路径
images_dir = os.path.join(workdir, 'SISD10') # images path. 图像路径
labels_dir = os.path.join(workdir, 'SID10rotatelabelxml') # xml labels path. xml标签路径
# yolov5_all_images = os.path.join(workdir, 'yolov5_all_images') # all images for yolov5 rotation. 转换后旋转版yolov5可用的图像路径
yolov5_all_labels = os.path.join(workdir, 'SID10rotatetxt') # all labels for yolov5 rotation. 转换后旋转版yolov5可用的txt标签路径
for d in [yolov5_all_labels]:
    if not os.path.exists(d):
        os.mkdir(d)


# In[3]:


all_files = [i for i in os.listdir(labels_dir) if i[-4:] == '.xml']


# In[4]:


print('labels count: ', len(all_files))


# In[5]:

#todo
keep_class_names = ['cup','forceps','kidneydish','needleholder','retractor','scalpel','scalpelhandle','scissors','sutureneedle','tampon'] # auto scan if blank. 如果留空,会自动扫描类别


# In[6]:


class_names = dict(zip(keep_class_names, range(len(keep_class_names))))


# ## convert. 转换

# In[7]:


auto_scan = False
class_index = 0
if len(class_names) == 0:
    auto_scan = True
    print('Auto scan classnames enabled.')

for file in tqdm(all_files):
    file_path = os.path.join(labels_dir, file)
    tree = ET.parse(file_path)
    root = tree.getroot()
    
    img_size = root.find('size')
    width = float(img_size.find('width').text)
    height = float(img_size.find('height').text)
    
    objs = root.findall('object')
    
    with open(os.path.join(yolov5_all_labels, file[:-4] + '.txt'), 'w+') as f:
        for obj in objs:
            name = obj.find('name').text.strip()
            if name not in class_names.keys():
                if auto_scan:
                    class_names[name] = class_index
                    class_index = class_index + 1
                else:
                    continue
            rbb = obj.find('robndbox')
            if not rbb:
                print('no robndbox in %s' % (file_path))
            cx = float(rbb.find('cx').text)
            cy = float(rbb.find('cy').text)
            w = float(rbb.find('w').text)
            h = float(rbb.find('h').text)
            angle = float(rbb.find('angle').text)
            if angle > math.pi:
                angle = angle - math.pi
            
            degree = round(angle / math.pi * 180)
            if h > w:     # swap w,h if w is not longside. 宽不是长边时,交换宽高
                w, h = h, w
                if degree < 90:
                    degree = degree + 90
                else:
                    degree = degree - 90
            cv_degree = degree # 180 - degree     # opencv angle format. opencv格式角度
            if cv_degree == 180:
                cv_degree = 0
            assert cv_degree >= 0 and cv_degree < 180
            
            f.write('{} {} {} {} {} {}\n'.format(class_names[name], cx/width, cy/height, w/width, h/height, cv_degree))
    # break


# In[8]:


print('class_names: ', class_names)


# In[9]:


sorted_keys = [i[0] for i in sorted(class_names.items(), key = lambda kv:(kv[1], kv[0]))]


# In[10]:


print('names: [ "{}" ]'.format('", "'.join(sorted_keys)))


yolo_rotation_to_xml

旋转yolo转回到xml文件。angle角度稍微有小数点后3位误差,原因可能是txt中保留的小数点位数,原xml转txt约了一次。txt转回xml又约了一次。原xml中w和h不一定w>h,但转出到txt一定是w>h,再转回xml时,和原xml不一样。

# 参考 https://deepinout.com/python/python-qa/t_how-to-generate-xml-using-python.html
# 参考 https://zhuanlan.zhihu.com/p/383660741
import os
# import xml.etree.ElementTree as ET
from lxml import etree as ET
from PIL import Image
import numpy as np
import math
# 图片文件夹
img_path = 'E:\picdata\SISD10\\'

# txt文件夹
labels_path = './SID10rotatelabeltxt/'

# xml存放的文件夹
annotations_path = './test4/'

labels = os.listdir(labels_path)

# 类别
classes = ['cup','forceps','kidneydish','needleholder','retractor','scalpel','scalpelhandle','scissors','sutureneedle','tampon']  #类别名

# 图片的高度、宽度、深度
sh =1280
sw =1280
sd =3

def write_xml(imgname, sw, sh, sd, filepath, labeldicts):
    '''
    imgname: 没有扩展名的图片名称
    '''

    # 创建Annotation根节点
    root = ET.Element('annotation', {'verified': 'no'})
    ET.SubElement(root, 'folder').text = "SISD10"
    # 创建filename子节点,无扩展名                 
    ET.SubElement(root, 'filename').text = str(imgname)
    ET.SubElement(root, 'path').text = str(img_path+img_id+'.jpg')

    source = ET.SubElement(root,'source')
    ET.SubElement(source, 'database').text = "Unknown"
    # 创建size子节点 
    size = ET.SubElement(root,'size')
    ET.SubElement(size, 'width').text = str(sw)
    ET.SubElement(size, 'height').text = str(sh)
    ET.SubElement(size, 'depth').text = str(sd)

    ET.SubElement(root, 'segmented').text = "0"

    for labeldict in labeldicts:
        objects = ET.SubElement(root, 'object')
        ET.SubElement(objects, 'type').text = 'robndbox'
        ET.SubElement(objects, 'name').text = labeldict['name']
        ET.SubElement(objects, 'pose').text = 'Unspecified'
        ET.SubElement(objects, 'truncated').text = '0'
        ET.SubElement(objects, 'difficult').text = '0'
        robndbox = ET.SubElement(objects,'robndbox')
        ET.SubElement(robndbox, 'cx').text = str(round(labeldict['cx'],6))
        ET.SubElement(robndbox, 'cy').text = str(round(labeldict['cy'],6))
        ET.SubElement(robndbox, 'w').text = str(round(labeldict['w'],6))
        ET.SubElement(robndbox, 'h').text = str(round(labeldict['h'],6))
        ET.SubElement(robndbox, 'angle').text = str(round(labeldict['angle'],6))
    tree = ET.ElementTree(root)
    tree.write(filepath, encoding='utf-8',pretty_print=True)#每个元素会自动换行和缩进


for label in labels:
    with open(labels_path + label, 'r') as f:
        img_id = os.path.splitext(label)[0]
        contents = f.readlines()
        labeldicts = []
        for content in contents:
            # 图片格式,我这里是jpg,你如果是png注意修改
            img = np.array(Image.open(img_path + label.strip('.txt') + '.jpg'))

            # 图片的高度、宽度、深度
            sh, sw, sd = img.shape[0], img.shape[1], img.shape[2]
            content = content.strip('\n').split()
            cx = float(content[1])*sw
            cy = float(content[2])*sh
            w = float(content[3])*sw
            h = float(content[4])*sh
            angle = float(content[5])*math.pi/180

            # 坐标的转换,x_center y_center width height angle -> cx cy w h angle
            new_dict = {'name': classes[int(content[0])],
                        'difficult': '0',
                        'cx': cx,
                        'cy': cy,
                        'w': w,
                        'h': h,
                        'angle': angle
                        }
            labeldicts.append(new_dict)
        write_xml(img_id, sw, sh, sd, annotations_path + label.strip('.txt') + '.xml', labeldicts)
        print(img_id + '.txt to .xml is Done')

roxml2xml

https://githubfast.com/walynlee/RoLabelImg_Transform/blob/master/roxml2xml.py

import xml.etree.ElementTree as ET
import math
import os

def rotate_point(point, angle, origin):
    angle_rad = math.radians(angle)  # 将角度angle从度数转换为弧度
    ox, oy = origin
    px, py = point
    qx = ox + math.cos(angle_rad) * (px - ox) - math.sin(angle_rad) * (py - oy)
    qy = oy + math.sin(angle_rad) * (px - ox) + math.cos(angle_rad) * (py - oy)
    return qx, qy

def rotate_bbox(bbox, angle, origin):
    rotated_bbox = []
    for point in bbox:
        rotated_point = rotate_point(point, angle, origin)
        rotated_bbox.append(rotated_point)
    return rotated_bbox

def process_xml(xml_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()

    # Iterate through each object in the XML and update the bounding box coordinates
    for obj in root.findall('object'):
        robndbox = obj.find('robndbox')
        if robndbox is not None:
            cx = float(robndbox.find('cx').text)
            cy = float(robndbox.find('cy').text)
            w = float(robndbox.find('w').text)
            h = float(robndbox.find('h').text)
            angle = float(robndbox.find('angle').text)

            rotated_bbox = rotate_bbox([(cx, cy), (cx + w, cy), (cx + w, cy + h), (cx, cy + h)], angle, (cx, cy))
            min_x = min(rotated_bbox[0][0], rotated_bbox[3][0])
            max_x = max(rotated_bbox[1][0], rotated_bbox[2][0])
            min_y = min(rotated_bbox[0][1], rotated_bbox[1][1])
            max_y = max(rotated_bbox[2][1], rotated_bbox[3][1])

            # Create new <bndbox> elements
            bndbox = ET.SubElement(obj, 'bndbox')
            xmin = ET.SubElement(bndbox, 'xmin')
            ymin = ET.SubElement(bndbox, 'ymin')
            xmax = ET.SubElement(bndbox, 'xmax')
            ymax = ET.SubElement(bndbox, 'ymax')

            # Set the values for <bndbox> elements
            xmin.text = str(int(min_x))
            ymin.text = str(int(min_y))
            xmax.text = str(int(max_x))
            ymax.text = str(int(max_y))

            # Remove the <robndbox> element
            obj.remove(robndbox)

    # Save the modified XML back to the original file
    tree.write(xml_path)

# Specify the input directory containing XML files and the output directory
input_directory = r'F:\walyn\walyn\nanodet\retinal_hole\val_xml'


# Iterate through each XML file in the input directory
for filename in os.listdir(input_directory):
    if filename.endswith('.xml'):
        xml_path = os.path.join(input_directory, filename)
        print(xml_path)
        process_xml(xml_path)

print("Processing complete.")

xml_to_yolo_obb

4个点坐标(x,y) + 类别

# 文件名称   :roxml_to_dota.py
# 功能描述   :把rolabelimg标注的xml文件转换成dota能识别的xml文件,
#             再转换成dota格式的txt文件
#            把旋转框 cx,cy,w,h,angle,或者矩形框cx,cy,w,h,转换成四点坐标x1,y1,x2,y2,x3,y3,x4,y4
import os
import xml.etree.ElementTree as ET
import math

cls_list=['你的类别']
def edit_xml(xml_file, dotaxml_file):
    """
    修改xml文件
    :param xml_file:xml文件的路径
    :return:
    """
    tree = ET.parse(xml_file)
    objs = tree.findall('object')
    for ix, obj in enumerate(objs):
        x0 = ET.Element("x0")  # 创建节点
        y0 = ET.Element("y0")
        x1 = ET.Element("x1")
        y1 = ET.Element("y1")
        x2 = ET.Element("x2")
        y2 = ET.Element("y2")
        x3 = ET.Element("x3")
        y3 = ET.Element("y3")
        # obj_type = obj.find('bndbox')
        # type = obj_type.text
        # print(xml_file)

        if (obj.find('robndbox') == None):
            obj_bnd = obj.find('bndbox')
            obj_xmin = obj_bnd.find('xmin')
            obj_ymin = obj_bnd.find('ymin')
            obj_xmax = obj_bnd.find('xmax')
            obj_ymax = obj_bnd.find('ymax')
            #以防有负值坐标
            xmin = max(float(obj_xmin.text),0)
            ymin = max(float(obj_ymin.text),0)
            xmax = max(float(obj_xmax.text),0)
            ymax = max(float(obj_ymax.text),0)
            obj_bnd.remove(obj_xmin)  # 删除节点
            obj_bnd.remove(obj_ymin)
            obj_bnd.remove(obj_xmax)
            obj_bnd.remove(obj_ymax)
            x0.text = str(xmin)
            y0.text = str(ymax)
            x1.text = str(xmax)
            y1.text = str(ymax)
            x2.text = str(xmax)
            y2.text = str(ymin)
            x3.text = str(xmin)
            y3.text = str(ymin)
        else:
            obj_bnd = obj.find('robndbox')
            obj_bnd.tag = 'bndbox'  # 修改节点名
            obj_cx = obj_bnd.find('cx')
            obj_cy = obj_bnd.find('cy')
            obj_w = obj_bnd.find('w')
            obj_h = obj_bnd.find('h')
            obj_angle = obj_bnd.find('angle')
            cx = float(obj_cx.text)
            cy = float(obj_cy.text)
            w = float(obj_w.text)
            h = float(obj_h.text)
            angle = float(obj_angle.text)
            obj_bnd.remove(obj_cx)  # 删除节点
            obj_bnd.remove(obj_cy)
            obj_bnd.remove(obj_w)
            obj_bnd.remove(obj_h)
            obj_bnd.remove(obj_angle)

            x0.text, y0.text = rotatePoint(cx, cy, cx - w / 2, cy - h / 2, -angle)
            x1.text, y1.text = rotatePoint(cx, cy, cx + w / 2, cy - h / 2, -angle)
            x2.text, y2.text = rotatePoint(cx, cy, cx + w / 2, cy + h / 2, -angle)
            x3.text, y3.text = rotatePoint(cx, cy, cx - w / 2, cy + h / 2, -angle)


        # obj.remove(obj_type)  # 删除节点
        obj_bnd.append(x0)  # 新增节点
        obj_bnd.append(y0)
        obj_bnd.append(x1)
        obj_bnd.append(y1)
        obj_bnd.append(x2)
        obj_bnd.append(y2)
        obj_bnd.append(x3)
        obj_bnd.append(y3)

        tree.write(dotaxml_file, method='xml', encoding='utf-8')  # 更新xml文件


# 转换成四点坐标
def rotatePoint(xc, yc, xp, yp, theta):
    xoff = xp - xc;
    yoff = yp - yc;
    cosTheta = math.cos(theta)
    sinTheta = math.sin(theta)
    pResx = cosTheta * xoff + sinTheta * yoff
    pResy = - sinTheta * xoff + cosTheta * yoff
    return str(int(xc + pResx)), str(int(yc + pResy))


def totxt(xml_path, out_path):
    # 想要生成的txt文件保存的路径,这里可以自己修改

    files = os.listdir(xml_path)
    i=0
    for file in files:

        tree = ET.parse(xml_path + os.sep + file)
        root = tree.getroot()

        name = file.split('.')[0]

        output = out_path +'\\'+name + '.txt'
        file = open(output, 'w')
        i=i+1
        objs = tree.findall('object')
        for obj in objs:
            cls = obj.find('name').text
            box = obj.find('bndbox')
            x0 = int(float(box.find('x0').text))
            y0 = int(float(box.find('y0').text))
            x1 = int(float(box.find('x1').text))
            y1 = int(float(box.find('y1').text))
            x2 = int(float(box.find('x2').text))
            y2 = int(float(box.find('y2').text))
            x3 = int(float(box.find('x3').text))
            y3 = int(float(box.find('y3').text))
            if x0<0:
                x0=0
            if x1<0:
                x1=0
            if x2<0:
                x2=0
            if x3<0:
                x3=0
            if y0<0:
                y0=0
            if y1<0:
                y1=0
            if y2<0:
                y2=0
            if y3<0:
                y3=0
            for cls_index,cls_name in enumerate(cls_list):
                if cls==cls_name:
                    file.write("{} {} {} {} {} {} {} {} {} {}\n".format(x0, y0, x1, y1, x2, y2, x3, y3, cls,cls_index))
        file.close()
        # print(output)
        print(i)

if __name__ == '__main__':
    # -----**** 第一步:把xml文件统一转换成旋转框的xml文件 ****-----
    roxml_path = r" 已标注并需要转换的xml文件"  
    dotaxml_path = r'存储dota格式的xml文件的输出路径'  #
    out_path = r'存储data格式yolov5_obb可训练的txt文件的路径'   
    filelist = os.listdir(roxml_path)
    for file in filelist:
        edit_xml(os.path.join(roxml_path, file), os.path.join(dotaxml_path, file))

    # -----**** 第二步:把旋转框xml文件转换成txt格式 ****-----
    totxt(dotaxml_path, out_path)

xml2yolo

import copy
from lxml.etree import Element, SubElement, tostring, ElementTree

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

classes = ["cup","forceps","kidneydish","needleholder","retractor","scapel","scapelhandle","scissors","sutureneedle","tampon"]  # 目标类别

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))


def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def convert_annotation(image_id):
    in_file = open('F:/picdata/SISD10label/%s.xml' % (image_id), encoding='UTF-8')  # xml文件路径

    out_file = open('F:/picdata/SISD10labelyolo/%s.txt' % (image_id), 'w')  # 生成txt格式文件
    tree = ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        cls = obj.find('name').text
        # print(cls)
        if cls not in classes:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
             float(xmlbox.find('ymax').text))
        bb = convert((w, h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')


xml_path = os.path.join(CURRENT_DIR, 'F:/picdata/SISD10label')

# xml list
img_xmls = os.listdir(xml_path)
for img_xml in img_xmls:
    label_name = img_xml.split('.')[0]
    print(label_name)
    convert_annotation(label_name)

json2txt

import json
import os
import glob
import os.path as osp
 
 
def labelme2yolov2Seg(jsonfilePath="", resultDirPath="", classList=["bowl","cup","forceps","kidneydish","needleholder","retractor","scapel","scapelhandle","sutureneedle","tampon"]):
    """
    此函数用来将labelme软件标注好的数据集转换为yolov5_7.0sege中使用的数据集
    :param jsonfilePath: labelme标注好的*.json文件所在文件夹
    :param resultDirPath: 转换好后的*.txt保存文件夹
    :param classList: 数据集中的类别标签
    :return:
    """
    # 0.创建保存转换结果的文件夹
    if(not os.path.exists(resultDirPath)):
        os.mkdir(resultDirPath)
 
    # 1.获取目录下所有的labelme标注好的Json文件,存入列表中
    jsonfileList = glob.glob(osp.join(jsonfilePath, "*.json"))
    print(jsonfileList)  # 打印文件夹下的文件名称
 
    # 2.遍历json文件,进行转换
    for jsonfile in jsonfileList:
        # 3. 打开json文件
        with open(jsonfile, "r") as f:
            file_in = json.load(f)
 
            # 4. 读取文件中记录的所有标注目标
            shapes = file_in["shapes"]
 
            # 5. 使用图像名称创建一个txt文件,用来保存数据
            with open(resultDirPath + "\\" + jsonfile.split("\\")[-1].replace(".json", ".txt"), "w") as file_handle:
                # 6. 遍历shapes中的每个目标的轮廓
                for shape in shapes:
                    # 7.根据json中目标的类别标签,从classList中寻找类别的ID,然后写入txt文件中
                    file_handle.writelines(str(classList.index(shape["label"])) + " ")
 
                    # 8. 遍历shape轮廓中的每个点,每个点要进行图像尺寸的缩放,即x/width, y/height
                    for point in shape["points"]:
                        x = point[0]/file_in["imageWidth"]  # mask轮廓中一点的X坐标
                        y = point[1]/file_in["imageHeight"]  # mask轮廓中一点的Y坐标
                        file_handle.writelines(str(x) + " " + str(y) + " ")  # 写入mask轮廓点
 
                    # 9.每个物体一行数据,一个物体遍历完成后需要换行
                    file_handle.writelines("\n")
            # 10.所有物体都遍历完,需要关闭文件
            file_handle.close()
        # 10.所有物体都遍历完,需要关闭文件
        f.close()
 
if __name__ == "__main__":
    jsonfilePath = "F:\picdata\SISD10dataset\data_annotated"  # 要转换的json文件所在目录
    resultDirPath = "F:\picdata\SISD10dataset\data_txt"  # 要生成的txt文件夹
    labelme2yolov2Seg(jsonfilePath=jsonfilePath, resultDirPath=resultDirPath, classList=["__ignore__","_background_","bowl","cup","forceps","kidneydish","needleholder","retractor","scapel","scapelhandle","sutureneedle","tampon"]) # 更改为自己的类别名

划分train val test

import os, shutil, random
import numpy as np
 
postfix = 'jpg'  # 这里要注意下,文件夹里的图片格式要都是jpg,如果是PNG那就都得是PNG
base_path = 'F:\数据集处理\SISD10dataset\img_data'   # 先手动把txt文件放进图片文件夹JPEGImages中
dataset_path = 'F:\数据集处理\SISD10dataset\SISD10seg'  # 自动新建一个文件夹SISDseg
val_size, test_size = 0.1, 0.0  # 这里把test设置为0,也就是train:val = 9:1
# val_size = 0.1
 
os.makedirs(dataset_path, exist_ok=True)
os.makedirs(f'{dataset_path}/images', exist_ok=True)
os.makedirs(f'{dataset_path}/images/train', exist_ok=True)
os.makedirs(f'{dataset_path}/images/val', exist_ok=True)
os.makedirs(f'{dataset_path}/images/test', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/train', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/val', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/test', exist_ok=True)
 
path_list = np.array([i.split('.')[0] for i in os.listdir(base_path) if 'txt' in i])
random.shuffle(path_list)
train_id = path_list[:int(len(path_list) * (1 - val_size - test_size))]
# train_id = path_list[:int(len(path_list) * (1 - val_size))]
 
# val_id = path_list[int(len(path_list) * (1 - val_size - test_size)):int(len(path_list) * (1 - test_size))]
val_id = path_list[int(len(path_list) * (1 - val_size - test_size)):int(len(path_list) * (1 - test_size))]
test_id = path_list[int(len(path_list) * (1 - test_size)):]
 
for i in train_id:
    shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/train/{i}.{postfix}')
    shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/train/{i}.txt')
 
for i in val_id:
    shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/val/{i}.{postfix}')
    shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/val/{i}.txt')
 
for i in test_id:
    shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/test/{i}.{postfix}')
    shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/test/{i}.txt')

anaconda 手动添加系统变量

http://t.csdn.cn/uWgPv

Pycharm中Terminal用不了conda指令解决办法 

http://t.csdn.cn/Ot5fJ

 PowerShell窗口

Set-ExecutionPolicy RemoteSigned

Y   回车

conda init powershell

conda配置国内镜像源将Anaconda设置为国内镜像源的方法_anaconda国内源_流沙没尘居士的博客-CSDN博客

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/fastai/
conda config --set show_channel_urls yes

改变conda虚拟环境的默认路径

http://t.csdn.cn/3cHfM

创建新环境,并指定python版本

conda create --name=labelImg python=3.6

进入刚建立的新环境

conda activate labelimg

pip升级到最新版

python -m pip install --upgrade pip

pip配置国内镜像源

Python-pip镜像源配置及国内常用镜像源_pypi镜像源_KwokRoot的博客-CSDN博客

windows下:新建文件C:\Users\Administrator\pip\pip.ini 

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = https://pypi.tuna.tsinghua.edu.cn
pip install pyqt5

pip install labelImg==1.8.6 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

(labelImg) F:\picdata>labelImg SISD10 predefined_classes.txt

..

..

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值