python图像处理与标注处理流程

文章目录

  • 1. 判断xml和图像文件在两个文件夹是否一一对应.py
  • 2. 判断xml中标签是否为空,移动空xml和图像到指定路径.py
  • 3. 删除坐标有问题的xml和对应的图像.py
  • 4.1 给标注的单个图像画框.py
  • 4.2 图像批量显示标注位置
  • 4.3 根据xml的类别给标注的图像批量画框(对图像分类显示标注位置)
  • 5.1 从一堆图像里复制出我们要的图像文件.py
  • 5.2 根据txt文件保存需要的图像到新文件夹.py
  • 6.1 再筛xml
  • 6.2 再保存对应的xml文件到新文件夹.py
  • 7.1 滑动窗口式的裁剪图片与标注框.py
  • 7.2 expot.py
  • 8.删掉不要的裁剪图像和对应的xml.py
  • 9. 扣框或者中心裁剪.py
  • 10. 根据xml计算目标长宽面积等.py
  • 11. 删掉不符合分辨率的图像.py
  • 12. 划分训练集测试集的图像和xml.py

1. 判断xml和图像文件在两个文件夹是否一一对应.py

import cv2
import os
import shutil

def check_img(img_path):
    imgs = os.listdir(img_path)
    for img in imgs:
        if img.split(".")[-1] != "jpg":
            print(img)
            shutil.move(img_path + "/" + img, "./error/" + img)


def check_anno(anno_path):
    anno_files = os.listdir(anno_path)
    for file in anno_files:
        if file.split(".")[-1] != "xml":
            print(file)
            shutil.move(anno_path + "/" + file, "./error/" + file)


def ckeck_img_label(img_path, anno_path):
    imgs = os.listdir(img_path)
    anno_files = os.listdir(anno_path)

    files = [i.split(".")[0] for i in anno_files]

    for img in imgs:
        if img.split(".")[0] not in files:
            print(img)
            shutil.move(img_path + "/" + img, "./error/" + img)

    imgs = os.listdir(img_path)
    images = [j.split(".")[0] for j in imgs]

    for file in anno_files:
        if file.split(".")[0] not in images:
            print(file)
            shutil.move(anno_path + "/" + file, "./error/" + file)


if __name__ == "__main__":
    if not os.path.exists("./error/"):
        os.makedirs("./error")
    img_path = r"./11yueimgs/"
    anno_path = r"./11yuexmls/"
    print("============check image=========")
    check_img(img_path)
    print("============check anno==========")
    check_anno(anno_path)
    print("============check both==========")
    ckeck_img_label(img_path, anno_path)

2. 判断xml中标签是否为空,移动空xml和图像到指定路径.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 移动标签为空的xml,并同步移动相应图片,把不要的放到新文件夹下
import os
import xml.etree.ElementTree as ET
import shutil

origin_ann_dir = './11yuexmls/'  # 设置原始标签路径为 Annos
new_ann_dir = './trashxmls/'  # 设置新标签路径 Annotations
origin_pic_dir = './11yueimgs/'
new_pic_dir = './trashimgs/'
k = 0
p = 0
q = 0
if not os.path.exists(new_ann_dir):
    os.mkdir(new_ann_dir)
if not os.path.exists(new_pic_dir):
    os.mkdir(new_pic_dir)

for dirpaths, dirnames, filenames in os.walk(origin_ann_dir):  # os.walk游走遍历目录名
    for filename in filenames:
        print("process...")
        k = k + 1
        print(k)
        if os.path.isfile(r'%s%s' % (origin_ann_dir, filename)):  # 获取原始xml文件绝对路径,isfile()检测是否为文件 isdir检测是否为目录
            origin_ann_path = os.path.join(r'%s%s' % (origin_ann_dir, filename))  # 如果是,获取绝对路径(重复代码)
            new_ann_path = os.path.join(r'%s%s' % (new_ann_dir, filename))
            tree = ET.parse(origin_ann_path)  # ET是一个xml文件解析库,ET.parse()打开xml文件。parse--"解析"
            root = tree.getroot()  # 获取根节点
            if len(root.findall('object')):
                p = p + 1
            else:
                print(filename)
                old_xml = origin_ann_dir + filename
                new_xml = new_ann_dir + filename
                old_pic = origin_pic_dir + filename.replace("xml", "jpg")
                new_pic = new_pic_dir + filename.replace("xml", "jpg")
                q = q + 1
                shutil.move(old_pic, new_pic)
                shutil.move(old_xml, new_xml)
print("ok, ", p)
print("empty, ", q)

3. 删除坐标有问题的xml和对应的图像.py

import xml.etree.ElementTree as xml_tree
import os
import shutil
"""
删除xmin,ymin>=xmax,ymax坐标的xml和对应的图像
"""
def check_box(path):
    files = os.listdir(path)
    i = 0
    for anna_file in files:
        tree = xml_tree.parse(path + "/" + anna_file)
        root = tree.getroot()
        for obj in root.findall('object'):

            bbox = obj.find('bndbox')
            if (float(bbox.find('ymin').text) >= float(bbox.find('ymax').text)) or (
                    float(bbox.find('xmin').text) >= float(bbox.find('xmax').text)):
                print(anna_file)
                i += 1
                try:
                    shutil.move(path + "/" + anna_file, "./error2/" + anna_file)
                    shutil.move("./11yueimgs/" + anna_file.split(".")[0] + ".jpg",
                                "./error2/" + anna_file.split(".")[0] + ".jpg")
                except:
                    pass

    print(i)

if __name__ == "__main__":
    if not os.path.exists("./error2"):
        os.mkdir("./error2")
    check_box("./11yuexmls")

4.1 给标注的单个图像画框.py


#!/usr/bin/python
# -*- coding: UTF-8 -*-
# get annotation object bndbox location
import os
import cv2
"""
(单张图像显示标注位置)
"""
try:
    import xml.etree.cElementTree as ET  # 解析xml的c语言版的模块
except ImportError:
    import xml.etree.ElementTree as ET

##get object annotation bndbox loc start
def GetAnnotBoxLoc(AnotPath):  # AnotPath VOC标注文件路径
    tree = ET.ElementTree(file=AnotPath)  # 打开文件,解析成一棵树型结构
    root = tree.getroot()  # 获取树型结构的根
    ObjectSet = root.findall('object')  # 找到文件中所有含有object关键字的地方,这些地方含有标注目标
    ObjBndBoxSet = {
     }  # 以目标类别为关键字,目标框为值组成的字典结构
    for Object in ObjectSet:
        # code有可能是name,这个要根据xml文件内容修改
        ObjName = Object.find('code').text
        BndBox = Object.find('bndbox')
        x1 = int(BndBox.find('xmin').text)  # -1 #-1是因为程序是按0作为起始位置的
        y1 = int(BndBox.find('ymin').text)  # -1
        x2 = int(BndBox.find('xmax').text)  # -1
        y2 = int(BndBox.find('ymax').text)  # -1
        BndBoxLoc = [x1, y1, x2, y2]
        if ObjName in ObjBndBoxSet:
            ObjBndBoxSet[ObjName].append(BndBoxLoc)  # 如果字典结构中含有这个类别了,那么这个目标框要追加到其值的末尾
        else:
            ObjBndBoxSet[ObjName] = [BndBoxLoc]  # 如果字典结构中没有这个类别,那么这个目标框就直接赋值给其值吧
    return ObjBndBoxSet

##get object annotation bndbox loc end

def display(objBox, pic):
    img = cv2.imread(pic)

    for key in objBox.keys():
        for i in range(len(objBox[key])):
            cv2.rectangle(img, (objBox[key][i][0], objBox[key][i][1]), (objBox[key][i][2], objBox[key][i][3]),
                          (0, 0, 255), 2)
            cv2.putText(img, key, (objBox[key][i][0], objBox[key][i][1]), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 1)
    cv2.namedWindow('img', cv2.WINDOW_NORMAL)#opencv显示图像一部分,这个可以显示全部
    cv2.imshow('img', img)
    cv2.imwrite('display.jpg', img)
    cv2.waitKey(0)


if __name__ == '__main__':
    pic = r"C:\Desktop\0.jpg"# 图片路径
    ObjBndBoxSet = GetAnnotBoxLoc(r"E:\xx\xml\2.xml")# xml路径
    print(ObjBndBoxSet)
    display(ObjBndBoxSet, pic)

4.2 图像批量显示标注位置

import cv2
import numpy as np

import xml.dom.minidom
import os
import argparse
"""
(图像批量显示标注位置)
"""

def main():
    # JPG文件的地址
    img_path = './imgs/'
    # XML文件的地址
    anno_path = './xmls/'
    # 存结果的文件夹
    cut_path = './outs/'
    # 获取文件夹中的文件
    imagelist = os.listdir(img_path)

    for image in imagelist:
        image_pre, ext = os.path.splitext(image)
        img_file = img_path + image
        # 读取图片
        img = cv2.imread(img_file)
        xml_file = anno_path + image_pre + '.xml'
        # 打开xml文档
        DOMTree = xml.dom.minidom.parse(xml_file)
        # 得到文档元素对象
        collection = DOMTree.documentElement
        # 得到标签名为object的信息
        objects = collection.getElementsByTagName("object")

        for object in objects:
            # print("start")
            # 每个object中得到子标签名为name的信息
            namelist = object.getElementsByTagName('code')
            # 通过此语句得到具体的某个name的值
            objectname = namelist[0].childNodes[0].data
            bndbox = object.getElementsByTagName('bndbox')[0]
            xmin = bndbox.getElementsByTagName('xmin')[0]
            xmin_data = xmin.childNodes[0].data
            ymin = bndbox.getElementsByTagName('ymin')[0]
            ymin_data = ymin.childNodes[0].data
            xmax = bndbox.getElementsByTagName('xmax')[0]
            xmax_data = xmax.childNodes[0].data
            ymax = bndbox.getElementsByTagName('ymax')[0]
            ymax_data = ymax.childNodes[0].data
            xmin = int(xmin_data)
            xmax = int(xmax_data)
            ymin = int(ymin_data)
            ymax = int(ymax_data)
            # img_cut = img[ymin:ymax, xmin:xmax, :]  # 截取框住的目标
            # cv2.imwrite(cut_path + 'cut_img_{}.jpg'.format(image_pre), img)
            cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), thickness=2)  # 生成原始值
            cv2.putText(img, objectname, (xmin, ymin), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0, 255, 0), thickness=2)
            cv2.imwrite(cut_path + '{}.jpg'.format(image_pre), img)


if __name__ == '__main__':
    main()

4.3 根据xml的类别给标注的图像批量画框(对图像分类显示标注位置)

from __future__ import division
import os
from PIL import Image
import xml.dom.minidom
import numpy as np
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
import cv2
"""
根据xml的类别给标注的图像批量画框(对图像分类显示标注位置)
"""

ImgPath = './11yueimgs/'
AnnoPath = './11yuexmls/'
ProcessedPath = './class_kuang/'
if not os.path.exists(ProcessedPath):
    os.makedirs(ProcessedPath)
imagelist = os.listdir(ImgPath)
for image in imagelist:
    image_pre, ext = os.path.splitext(image)
    imgfile = ImgPath + image
    print(imgfile)
    if not os.path.exists(AnnoPath + image_pre + '.xml'): continue
    xmlfile = AnnoPath + image_pre + '.xml'
    DomTree = xml.dom.minidom.parse(xmlfile)
    annotation = DomTree.documentElement
    objectlist = annotation.getElementsByTagName('object')
    img = cv2.imread(imgfile)
    for objects in objectlist:
        namelist = objects.getElementsByTagName('code')
        # 通过此语句得到具体的某个name的值
        objectname = namelist[0].childNodes[0].data
        bndbox = objects.getElementsByTagName('bndbox')[0]
        xmin = bndbox.getElementsByTagName('xmin')[0]
        xmin_data = xmin.childNodes[0].data
        ymin = bndbox.getElementsByTagName('ymin')[0]
        ymin_data = ymin.childNodes[0].data
        xmax = bndbox.getElementsByTagName('xmax')[0]
        xmax_data = xmax.childNodes[0].data
        ymax = bndbox.getElementsByTagName('ymax')[0]
        ymax_data = ymax.childNodes[0].data
        xmin = int(xmin_data)
        xmax = int(xmax_data)
        ymin = int(ymin_data)
        ymax = int(ymax_data)
        savepath = ProcessedPath + objectname
        if not os.path.exists(savepath):
            os.makedirs(savepath)
        cv2.rectangle(img, (int(xmin), int(ymin)), (int(xmax), int(ymax)), (0, 255, 0),
                      thickness=2)  # 生成原始值
        cv2.putText(img, objectname,(int(xmin), int(ymin)), cv2.FONT_HERSHEY_COMPLEX, 0.7, (0, 255, 0), thickness=2)
        cv2.imwrite(savepath + '/' + image_pre + '.jpg',img)

5.1 从一堆图像里复制出我们要的图像文件.py

# -*- coding:utf-8 -*-
# import sys
# sys.path.append('D:\\Program files\\Anaconda\\libs')
import os #os:操作系统相关的信息模块
import random #导入随机函数
"""
根据需求,先筛选出需要的图像根据txt中图片的名字批量提取对应的图片并保存到另一个文件夹
1.先获得需要转换的图像名称的txt文件
"""

#存放原始图片地址
data_base_dir = "./11yueimgs"
file_list = [] #建立列表,用于保存图片信息
#读取图片文件,并将图片地址、图片名和标签写到txt文件中
write_file_name = '11yue_need_imgs.txt'
write_file = open(write_file_name, "w") #以只写方式打开write_file_name文件
for file in os.listdir(data_base_dir): #file为current_dir当前目录下图片名
    if file.endswith(".jpg"): #如果file以jpg结尾
        write_name = file #图片路径 + 图片名 + 标签
        file_list.append(write_name) #将write_name添加到file_list列表最后
    sorted(file_list) #将列表中所有元素随机排列
    number_of_lines = len(file_list) #列表中元素个数
    #将图片信息写入txt文件中,逐行写入
for current_line in range(number_of_lines):
    write_file.write(file_list[current_line][:-4] + '\n')#关闭文件

5.2 根据txt文件保存需要的图像到新文件夹.py

# -*- coding: UTF-8 -*-
#!/usr/bin/env python
import sys
import re
from PIL import Image,ImageFile
import os
ImageFile.LOAD_TRUNCATED_IMAGES = True
if not os.path.exists("./outimgs"):
    os.makedirs("./outimgs")
# sys.path.append('E:\\CODE')
data = []
for line in open("./11yue_need_imgs.txt", "r"):  # 设置文件对象并读取每一行文件
    data.append(line)
for a in data:
  im = Image.open('./imgs/{}'.format(a[:-1])+".jpg")#打开改路径下的line3记录的的文件名
  im.save('./outimgs/{}'.format(a[:-1])+".jpg") #把文件夹中指定的文件名称的图片另存到该路径下(+".jpg"看自己的txt文件内容后缀是否包含)
  im.close()

6.1 再筛xml

# -*- coding:utf-8 -*-
import sys
sys.path.append('D:\\Program files\\Anaconda\\libs')
import os #os:操作系统相关的信息模块
import random #导入随机函数
#存放原始图片地址
data_base_dir = r"F:\zy\2haotu"
file_list = [] #建立列表,用于保存图片信息
#读取图片文件,并将图片地址、图片名和标签写到txt文件中
write_file_name = 'image.txt'
write_file = open(write_file_name, "w") #以只写方式打开write_file_name文件
for file in os.listdir(data_base_dir): #file为current_dir当前目录下图片名
    if file.endswith(".jpg"): #如果file以jpg结尾
        write_name = file #图片路径 + 图片名 + 标签
        file_list.append(write_name) #将write_name添加到file_list列表最后
    sorted(file_list) #将列表中所有元素随机排列
    number_of_lines = len(file_list) #列表中元素个数
    #将图片信息写入txt文件中,逐行写入
for current_line in range(number_of_lines):
    write_file.write(file_list[current_line][:-4] +'\n')#关闭文件

6.2 再保存对应的xml文件到新文件夹.py

import os
import shutil


if __name__ == '__main__':
    f = open("./image.txt","r")   #存放有XML文件名字的txt

    line = f.readline()
    line = line[:-1]
    if not os.path.exists("./out"):
        os.makedirs("./out")
    while line:
        line = f.readline()
        line = line.strip('\n')
        print(line)
        # path = os.getcwd()
        new_path = r"F:/zy/6yuexmls/"+line+".xml"   #路径为保存XML文件的文件夹(位置为我们所有的xml文件,从中移动到out文件夹下)
        print(new_path)
        try:
            shutil.move(new_path, './out')   #提取后保存的位置
        except:
            print("Not find error.")
        # print(path)
    f.close()

7.1 滑动窗口式的裁剪图片与标注框.py

"""
这里是实现分辨率为w_h裁剪成多张a_a大小的图片(a<=w且a<=h),以大小为a/2的步长滑动,裁剪同时修改标注框。
1.把这个文件命名为xml_parse.py
"""

import xml.dom.minidom as xmldom
import os.path


def voc_xml_parse(xml_path):
    object_list = []
    domobj = xmldom.parse(xml_path)
    elementobj = domobj.documentElement
    folderobj = elementobj.getElementsByTagName("folder")[0]
    filenameobj = elementobj.getElementsByTagName("filename")[0]
    # sourceobj = elementobj.getElementsByTagName("source")[0]
    # ownerobj = elementobj.getElementsByTagName("owner")[0]
    sizeobj = elementobj.getElementsByTagName("size")[0]
    # segmentedobj = elementobj.getElementsByTagName("segmented")[0]
    head = {
     'folder': folderobj, 'filename': filenameobj, 'size': sizeobj,}
    object_list = elementobj.getElementsByTagName("object")
    return head, object_list


def voc_xml_modify(modify_xml_path, head, object_list):
    dom = xmldom.Document()
    root = dom.createElement('annotation')
    dom.appendChild(root)
    for obj in head.values():
        root.appendChild(obj)
    for obj in object_list:
        root.appendChild((obj))
    with open(modify_xml_path, 'w', encoding='utf-8') as f:
        dom.writexml(f, addindent='\t', newl='\n', encoding='utf-8')
    return

7.2 expot.py

# coding:utf-8
import cv2
import os
import codecs
import xml_parse
import xml.dom.minidom as xmldom
import xml.etree.ElementTree as ET
import numpy as np
from PIL import Image
from tqdm import tqdm
import sys

sys.setrecursionlimit(10000)


def load_image_into_numpy_array(image):
    (im_width, im_height) = image.size
    return np.array(image.getdata()).reshape(
        (im_height, im_width, 3)).astype(np.uint16)


def crop_xml_modify(head, objectlist, hmin, wmin, new_height, new_width, origin_xml__path):
    filenameobj = head['filename']
    sizeobj = head['size']
    width = sizeobj.getElementsByTagName('width')[0]
    width.childNodes[0].data = str(new_width)
    # print(str(WIDTH))
    height = sizeobj.getElementsByTagName('height')[0]
    height.childNodes[0].data = str(new_height)
    # tree = ET.parse(origin_xml__path)
    # root = tree.getroot()
    obj = objectlist
    i = 0
    while (i < obj.length):
        # for obj in objectlist1:
        bndbox = obj[i].getElementsByTagName('bndbox')[0]
        xmin = bndbox.getElementsByTagName('xmin')[0]
        XMIN = float(xmin.childNodes[0].data)
        ymin = bndbox.getElementsByTagName('ymin')[0]
        YMIN = float(ymin.childNodes[0].data)
        xmax = bndbox.getElementsByTagName('xmax')[0]
        XMAX = float(xmax.childNodes[0].data)
        ymax = bndbox.getElementsByTagName('ymax')[0]
        YMAX = float(ymax.childNodes[0].data)
        if (XMIN >= wmin) and (XMAX <= (wmin + new_width)) and (YMIN >= hmin) and (YMAX <= (hmin + new_height)):
            xmin.childNodes[0].data = str(int(XMIN - wmin))
            xmax.childNodes[0].data = str(int(XMAX - wmin))
            ymin.childNodes[0].data = str(int(YMIN - hmin))
            ymax.childNodes[0].data = str(int(YMAX - hmin))
        else:
            obj.remove(obj[i])
            i = i - 1  # 一定要向前提一个位置 删除的话用for是会出错的 耽搁了好久。。。
            # obj = objectlist1[i-1]
        i = i + 1
    return head, obj


def crop_dataset(imgpath, output_shape, annotation, cropAnno, cropImg, stride):
    origin_image = cv2.imread(imgpath)
    # image = Image.open(imgpath)
    # image_np = load_image_into_numpy_array(image)
    # origin_image = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)
    height, width = origin_image.shape[:2]
    # print(height)
    # print(width)
    domobj = xmldom.parse(annotation)
    elementobj = domobj.documentElement
    name = elementobj.getElementsByTagName("name")
    size = len(name)
    # tree = ET.parse(origin_xml__path)
    # root = tree.getroot()
    x = 0
    newheight = output_shape
    newwidth = output_shape
    while x < width:
        y = 0
        if x + newwidth <= width:
            while y < height:
                # 裁剪为output_shape*output_shape
                # newheight = output_shape
                # newwidth = output_shape
                head, objectlist = xml_parse.voc_xml_parse(annotation)
                if y + newheight <= height:
                    hmin = y
                    hmax = y + newheight
                    wmin = x
                    wmax = x + newwidth
                else:
                    hmin = height - newheight
                    hmax = height
                    wmin = x
                    wmax = x + newwidth
                    y = height  # test
                modify_head, modify_objectlist = crop_xml_modify(head, objectlist, hmin, wmin, newheight, newwidth,
                                                                 origin_xml__path)
                cropAnno1 = cropAnno + '_' + str(wmax) + '_' + str(hmax) + '_' + str(output_shape) + '.xml'
                xml_parse.voc_xml_modify(cropAnno1, modify_head, modify_objectlist)
                cropImg1 = cropImg + '_' + str(wmax) + '_' + str(hmax) + '_' + str(output_shape) + '.png'
                cv2.imwrite(cropImg1, origin_image[hmin: hmax, wmin: wmax])
                y = y + stride
                if y + output_shape == height:  # 第一张图就已经涵盖了height*height
                    y = height
                # if y + newheight > height:
                #     break
        else:
            while y < height:
                # 裁剪为output_shape*output_shape
                # newheight = output_shape
                # newwidth = output_shape
                head, objectlist = xml_parse.voc_xml_parse(annotation)
                if y + newheight <= height:
                    hmin = y
                    hmax = y + newheight
                    wmin = width - newwidth
                    wmax = width
                else:
                    hmin = height - newheight
                    hmax = height
                    wmin = width - newwidth
                    wmax = width
                    y = height  # test
                modify_head, modify_objectlist = crop_xml_modify(head, objectlist, hmin, wmin, newheight, newwidth,
                                                                 origin_xml__path)
                cropAnno1 = cropAnno + '_' + str(wmax) + '_' + str(hmax) + '_' + str(output_shape) + '.xml'
                xml_parse.voc_xml_modify(cropAnno1, modify_head, modify_objectlist)
                cropImg1 = cropImg + '_' + str(wmax) + '_' + str(hmax) + '_' + str(output_shape) + '.png'
                cv2.imwrite(cropImg1, origin_image[hmin: hmax, wmin: wmax])
                y = y + stride
                # if y + newheight > height:
                #     break
            x = width
        x = x + stride
        if x + output_shape == width:  # 第一张图就已经涵盖了height*height
            x = width
        # if x + newwidth > width:
        #     break


if __name__ == '__main__':
    # output_shape 为想要裁剪成的图片尺寸
    output_shape = 2048  # 512 1024
    stride = int(output_shape / 2)
    imgpath = './myimgs/'  # 原图路径
    annotation = './myxmls/'  # 原图对应的标注xml文件路径
    cropAnno = './myoutxmls/'  # 裁剪后存储xml的路径
    cropImg = './myoutimgs/'  # 裁剪后存储图片的路径
    if not os.path.exists(cropImg):
        os.mkdir(cropImg)
    if not os.path.exists(cropAnno):
        os.mkdir(cropAnno)

    for each in tqdm(os.listdir(annotation)):
        # each = os.listdir(annotation)
        name = each.split('.')[0]
        origin_img_path = os.path.join(imgpath, name + '.jpg')
        origin_xml__path = os.path.join(annotation, name + '.xml')
        crop_img_path = os.path.join(cropImg, name)
        crop_xml__path = os.path.join(cropAnno, name)
        # tree = ET.parse(origin_xml__path)
        # root = tree.getroot()
        crop_dataset(origin_img_path, output_shape, origin_xml__path, crop_xml__path, crop_img_path, stride)

8.删掉不要的裁剪图像和对应的xml.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 移动标签为空的xml,并同步移动相应图片
import os
import xml.etree.ElementTree as ET
import shutil

origin_ann_dir = './data/Annotations/'  # 设置原始标签路径为 Annos
new_ann_dir = './trashxml/'  # 设置新标签路径 Annotations
origin_pic_dir = './data/images/'
new_pic_dir = './trashimg/'
k = 0
p = 0
q = 0
for dirpaths, dirnames, filenames in os.walk(origin_ann_dir):  # os.walk游走遍历目录名
    for filename in filenames:
        print("process...")
        k = k + 1
        print(k)
        if os.path.isfile(r'%s%s' % (origin_ann_dir, filename)):  # 获取原始xml文件绝对路径,isfile()检测是否为文件 isdir检测是否为目录
            origin_ann_path = os.path.join(r'%s%s' % (origin_ann_dir, filename))  # 如果是,获取绝对路径(重复代码)
            new_ann_path = os.path.join(r'%s%s' % (new_ann_dir, filename))
            tree = ET.parse(origin_ann_path)  # ET是一个xml文件解析库,ET.parse()打开xml文件。parse--"解析"
            root = tree.getroot()  # 获取根节点
            if len(root.findall('object')):
                p = p + 1
            else:
                print(filename)
                old_xml = origin_ann_dir + filename
                new_xml = new_ann_dir + filename
                old_pic = origin_pic_dir + filename.replace("xml", "jpg")
                new_pic = new_pic_dir + filename.replace("xml", "jpg")
                q = q + 1
                shutil.move(old_pic, new_pic)
                shutil.move(old_xml, new_xml)
print("ok, ", p)
print("empty, ", q)

9. 扣框或者中心裁剪.py

from __future__ import division

import os

from PIL import Image,ImageFile

import xml.dom.minidom

import numpy as np
ImageFile.LOAD_TRUNCATED_IMAGES = True

ImgPath = './Q/'

AnnoPath = './xml/'

ProcessedPath = './kuang/'

imagelist = os.listdir(ImgPath)

for image in imagelist:

    image_pre, ext = os.path.splitext(image)

    imgfile = ImgPath + image

    print(imgfile)

    if not os.path.exists(AnnoPath + image_pre + '.xml'): continue

    xmlfile = AnnoPath + image_pre + '.xml'

    DomTree = xml.dom.minidom.parse(xmlfile)

    annotation = DomTree.documentElement

    filenamelist = annotation.getElementsByTagName('filename')  # []

    # filename = filenamelist[0].childNodes[0].data

    objectlist = annotation.getElementsByTagName('object')

    i = 1

    for objects in objectlist:

        namelist = objects.getElementsByTagName('code')

        objectname = namelist[0].childNodes[0].data

        savepath = ProcessedPath + objectname

        if not os.path.exists(savepath):
            os.makedirs(savepath)

        bndbox = objects.getElementsByTagName('bndbox')

        cropboxes = []

        for box in bndbox:

            x1_list = box.getElementsByTagName('xmin')

            x1 = int(x1_list[0].childNodes[0].data)

            y1_list = box.getElementsByTagName('ymin')

            y1 = int(y1_list[0].childNodes[0].data)

            x2_list = box.getElementsByTagName('xmax')

            x2 = int(x2_list[0].childNodes[0].data)

            y2_list = box.getElementsByTagName('ymax')

            y2 = int(y2_list[0].childNodes[0].data)

            w = x2 - x1

            h = y2 - y1

            obj = np.array([x1, y1, x2, y2])# 抠框
            # obj = np.array([x1-(640-x2+x1)/2, y1-(640-x2+x1)/2, x1-(640-x2+x1)/2+640, y1-(640-x2+x1)/2+640])
            shift = np.array([[1, 1, 1, 1]])

            XYmatrix = np.tile(obj, (1, 1))

            cropboxes = XYmatrix * shift
            print(cropboxes)
            img = Image.open(imgfile)

            for cropbox in cropboxes:
                cropedimg = img.crop(cropbox)

                cropedimg.save(savepath + '/' + image_pre + '_' + str(i) + '.jpg')

                i += 1

10. 根据xml计算目标长宽面积等.py

# -*- coding:utf-8 -*-
import os
import xml.etree.ElementTree as ET
import numpy as np

#np.set_printoptions(suppress=True, threshold=np.nan)  #10,000,000
np.set_printoptions(suppress=True, threshold=10000000)  #10,000,000
import matplotlib
from PIL import Image

def parse_obj(xml_path, filename):
    tree = ET.parse(xml_path + filename)
    objects = []
    for obj in tree.findall('object'):
        obj_struct = {
     }
        obj_struct['name'] = obj.find('name').text
        bbox = obj.find('bndbox')
        obj_struct['bbox'] = [int(bbox.find('xmin').text),
                              int(bbox.find('ymin').text),
                              int(bbox.find('xmax').text),
                              int(bbox.find('ymax').text)]
        objects.append(obj_struct)
    return objects


def read_image(image_path, filename):
    im = Image.open(image_path + filename)
    W = im.size[0]
    H = im.size[1]
    area = W * H
    im_info = [W, H, area]
    return im_info

if __name__ == '__main__':
    image_path = '/VOCdevkit/VOC2007/JPEGImages/'
    xml_path = '/VOCdevkit/VOC2007/Annotations/'
    filenamess = os.listdir(xml_path)
    filenames = []
    for name in filenamess:
        name = name.replace('.xml', '')
        filenames.append(name)
    print(filenames)
    recs = {
     }
    ims_info = {
     }
    obs_shape = {
     }
    classnames = []
    num_objs={
     }
    obj_avg = {
     }
    for i, name in enumerate(filenames):
        print('正在处理 {}.xml '.format(name))
        recs[name] = parse_obj(xml_path, name + '.xml')
        print('正在处理 {}.jpg '.format(name))
        ims_info[name] = read_image(image_path, name + '.jpg')
    print('所有信息收集完毕。')
    print('正在处理信息......')
    for name in filenames:
        im_w = ims_info[name][0]
        im_h = ims_info[name][1]
        im_area = ims_info[name][2]
        for object in recs[name]:
            if object['name'] not in num_objs.keys():
                num_objs[object['name']] = 1
            else:
                num_objs[object['name']] += 1
            #num_objs += 1
            ob_w = object['bbox'][2] - object['bbox'][0]
            ob_h = object['bbox'][3] - object['bbox'][1]
            ob_area = ob_w * ob_h
            w_rate = ob_w / im_w
            h_rate = ob_h / im_h
            area_rate = ob_area / im_area
            if not object['name'] in obs_shape.keys():
                obs_shape[object['name']] = ([[ob_w,
                                               ob_h,
                                               ob_area,
                                               w_rate,
                                               h_rate,
                                               area_rate]])
            else:
                obs_shape[object['name']].append([ob_w,
                                                  ob_h,
                                                  ob_area,
                                                  w_rate,
                                                  h_rate,
                                                  area_rate])
        if object['name'] not in classnames:
            classnames.append(object['name'])  # 求平均

    for name in classnames:
        obj_avg[name] = (np.array(obs_shape[name]).sum(axis=0)) / num_objs[name]
        print('{}的情况如下:*******\n'.format(name))
        print('  目标平均W={}'.format(obj_avg[name][0]))
        print('  目标平均H={}'.format(obj_avg[name][1]))
        print('  目标平均area={}'.format(obj_avg[name][2]))
        print('  目标平均与原图的W比例={}'.format(obj_avg[name][3]))
        print('  目标平均与原图的H比例={}'.format(obj_avg[name][4]))
        print('  目标平均原图面积占比={}\n'.format(obj_avg[name][5]))
    print('信息统计计算完毕。')

11. 删掉不符合分辨率的图像.py

# -*- coding:utf-8 -*-
from PIL import Image
import os
import sys


def get_urllist():
    base = r'E:\Mysoft\trash\trash02\my\\'  # 这个是要清理的文件夹
    list = os.listdir(base)
    urllist = []
    for i in list:
        url = base + i
        urllist.append(url)
    return urllist


def get_imgSize(filename):
    print(filename)
    img = Image.open(filename)
    imgSize = img.size
    print(imgSize)

    return imgSize


if __name__ == '__main__':
    file_list = get_urllist()
    print("test1")
    for a in file_list:
        try:
            imgSize = get_imgSize(a)
            maxSize = max(imgSize)
            minSize = min(imgSize)
            print(maxSize, minSize)
            if (maxSize != 640 and minSize != 640 ):
                os.remove(a)
                print("已移除小于360x360分辨率的图片:%s" % a)
            else:
                pass
        except:
            os.remove(a)

12. 划分训练集测试集的图像和xml.py

import os
from shutil import copy2

# 原始路径
image_original_path = "./img/"
label_original_path = "./anno/"
# 上级目录
parent_path = os.path.dirname(os.getcwd())
# 训练集路径(生成的文件夹在当前目录的上一级目录)
train_image_path = os.path.join(parent_path, "trainimg/")
train_label_path = os.path.join(parent_path, "trainanno/")
# 测试集路径
test_image_path = os.path.join(parent_path, 'testimg/')
test_label_path = os.path.join(parent_path, 'testanno/')


# 检查文件夹是否存在
def mkdir():
    if not os.path.exists(train_image_path):
        os.makedirs(train_image_path)
    if not os.path.exists(train_label_path):
        os.makedirs(train_label_path)

    if not os.path.exists(test_image_path):
        os.makedirs(test_image_path)
    if not os.path.exists(test_label_path):
        os.makedirs(test_label_path)


def main():
    mkdir()
    # 复制移动图片数据
    all_image = os.listdir(image_original_path)
    print(all_image)
    for i in range(len(all_image)):
        if i % 8 != 0:
            copy2(os.path.join(image_original_path, all_image[i]), train_image_path)
        else:
            copy2(os.path.join(image_original_path, all_image[i]), test_image_path)

    # 复制移动标注数据
    all_label = os.listdir(label_original_path)
    for i in range(len(all_label)):
        if i % 8 != 0:
            copy2(os.path.join(label_original_path, all_label[i]), train_label_path)
        else:
            copy2(os.path.join(label_original_path, all_label[i]), test_label_path)


if __name__ == '__main__':
    main()

你可能感兴趣的:(python,python,深度学习,机器学习)