天天看點

DOTA資料集分割圖檔分割裁剪對應的txt将txt轉換為xml效果展示

DOTA資料集分割

  • 圖檔分割
  • 裁剪對應的txt
  • 将txt轉換為xml
  • 效果展示

圖檔分割

将圖檔分割成1000x1000大小的圖,步長是800

# -*- coding: utf-8 -*-
import cv2
import os

def tianchong_you(img):
    size = img.shape
    #if size[0]>=1000 and size[1]<1000:
    constant = cv2.copyMakeBorder(img,0,0,0,1000-size[1],cv2.BORDER_CONSTANT,value=(107,113,115))#填充值為資料集均值
    #else:
        #    print('圖像不符合要求')
        #   return 0
    return constant
def tianchong_xia(img):
    size = img.shape
# if size[0]<1000 and size[1]>=1000:
    constant = cv2.copyMakeBorder(img,0,1000-size[0],0,0,cv2.BORDER_CONSTANT,value=(107,113,115))
    #else:
    #    print('圖像不符合要求')
    #   return 0
    return constant
def tianchong_xy(img):
    size = img.shape
    #if size[0]<1000 and size[1]<1000:
    constant = cv2.copyMakeBorder(img,0,1000-size[0],0,1000-size[1],cv2.BORDER_CONSTANT,value=(107,113,115))
    #else:
    #      print('圖像不符合要求')
    #      return 0
    return constant
def caijian(path,path_out,size_w=1000,size_h=1000,step=800):#重疊度為200
    ims_list=os.listdir(path)
    #print(ims_list)
    count = 0
    for im_list in ims_list:
        number = 0
        name = im_list.split('.')[0] # 去處“.tiff字尾”
        img = cv2.imread(ims_path+im_list)
        size = img.shape
        if size[0]>=1000 and size[1]>=1000:
            count = count + 1
            for h in range(0,size[0]-1,step):
                star_h = h
                for w in range(0,size[1]-1,step):
                    star_w = w
                    end_h = star_h + size_h
                    if end_h > size[0]:
                        star_h = size[0] - size_h 
                        end_h = star_h + size_h
                    end_w = star_w + size_w
                    if end_w > size[1]:
                        star_w = size[1] - size_w
                    end_w = star_w + size_w
                    cropped = img[star_h:end_h, star_w:end_w]
                    name_img = name + '_'+ str(star_h) +'_' + str(star_w)#用起始坐标來命名切割得到的圖像,為的是友善後續标簽資料抓取
                    cv2.imwrite('{}/{}.jpg'.format(path_out,name_img),cropped)
                    number = number + 1
        if size[0]>=1000 and size[1]<1000:
            print('圖檔{}需要在右面補齊'.format(name))
            count = count + 1
            img0 = tianchong_you(img)
            for h in range(0,size[0]-1,step):
                star_h = h
                star_w = 0
                end_h = star_h + size_h
                if end_h > size[0]:
                    star_h = size[0] - size_h 
                    end_h = star_h + size_h
                end_w = star_w + size_w
                cropped = img0[star_h:end_h, star_w:end_w]
                name_img = name + '_'+ str(star_h) +'_' + str(star_w)
                cv2.imwrite('{}/{}.jpg'.format(path_out,name_img),cropped)
                number = number + 1
        if size[0]<1000 and size[1]>=1000:
            count = count + 1
            print('圖檔{}需要在下面補齊'.format(name))
            img0 = tianchong_xia(img)
            for w in range(0,size[1]-1,step):
                star_h = 0
                star_w = w
                end_w = star_w + size_w
                if end_w > size[1]:
                    star_w = size[1] - size_w 
                    end_w = star_w + size_w
                end_h = star_h + size_h
                cropped = img0[star_h:end_h, star_w:end_w]
                name_img = name + '_'+ str(star_h) +'_' + str(star_w)
                cv2.imwrite('{}/{}.jpg'.format(path_out,name_img),cropped) 
                number = number + 1   
        if size[0]<1000 and size[1]<1000:
            count = count + 1  
            print('圖檔{}需要在下面和右面補齊'.format(name))
            img0 = tianchong_xy(img)
            cropped = img0[0:1000, 0:1000]
            name_img = name + '_'+ '0' +'_' + '0'
            cv2.imwrite('{}/{}.jpg'.format(path_out,name_img),cropped) 
            number = number + 1             
        print('圖檔{}切割成{}張'.format(name,number)) 
        print('共完成{}張圖檔'.format(count))      

if __name__ == '__main__':
    ims_path='part1/images/'# 圖像資料集的路徑
    # txt_path = '/home/***/data/VOCdevkit/mydataset/Annotations/txt/'
    path = './qiege/' #切割得到的資料集存放路徑     
    caijian(ims_path,path,size_w=1000,size_h=1000,step=800)


           

裁剪對應的txt

# -*- coding: utf-8 -*-
import cv2
import os


category_set = ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 
'small-vehicle', 'large-vehicle', 'ship', 
'tennis-court', 'basketball-court',  
'storage-tank', 'soccer-ball-field', 
'roundabout', 'harbor', 
'swimming-pool', 'helicopter','container-crane'] 

def tqtxt(path,path_txt,path_out,size_h=1000,size_w=1000):
    ims_list=os.listdir(path)
    for im_list in ims_list:
        name_list = []
        name = im_list.split('.')[0]
        name_list = name.split('_')
        if len(name_list)<2:
            continue
        h = int(name_list[1])
        w = int(name_list[2])
        txtpath = path_txt + name_list[0] + '.txt'
        txt_outpath = path_out + name + '.txt'
        f = open(txt_outpath,'a')
        with open(txtpath, 'r') as f_in:   #打開txt檔案          
            i = 0
            lines = f_in.readlines()
            #print(len(lines))
            #splitlines = [x.strip().split(' ') for x in lines]  #根據空格分割
            for line  in lines:
                if i in [0,1]:
                    f.write(line)#txt前兩行直接複制過去
                    i = i+1
                    continue
                splitline = line.split(' ')
                label = splitline[8]
                kunnan = splitline[9]
                if label not in category_set:#隻書寫指定的類别     
                    continue            
                x1 = int(float(splitline[0]))
                y1 = int(float(splitline[1]))
                x2 = int(float(splitline[2]))
                y2 = int(float(splitline[3]))
                x3 = int(float(splitline[4]))
                y3 = int(float(splitline[5]))  
                x4 = int(float(splitline[6]))
                y4 = int(float(splitline[7]))
                if w<=x1<=w+size_w and w<=x2<=w+size_w and w<=x3<=w+size_w and w<=x4<=w+size_w and h<=y1<=h+size_h and h<=y2<=h+size_h and h<=y3<=h+size_h and h<=y4<=h+size_h:                     
                    f.write('{} {} {} {} {} {} {} {} {} {}'.format(float(x1-w),float(y1-h),float(x2-w),float(y2-h),float(x3-w),float(y3-h),float(x4-w),float(y4-h),label,kunnan))
        f.close()

if __name__ == '__main__':
    ims_path='./qiege/'# 圖像資料集的路徑
    txt_path = './labelTxt/'#原資料集标簽檔案
    path = './txt_caijian/'#切割後資料集的标簽檔案存放路徑      
    tqtxt(ims_path,txt_path,path,size_h=1000,size_w=1000)

           

将txt轉換為xml

# -*- coding:UTF-8 -*-
import os
import cv2
from xml.dom.minidom import Document 
import sys, importlib
stdi, stdo, stde = sys.stdin, sys.stdout, sys.stderr
importlib.reload(sys)
# sys.setdefaultencoding('utf-8')
sys.stdin, sys.stdout, sys.stderr = stdi, stdo, stde

category_set =  ['plane', 'baseball-diamond', 'bridge', 'ground-track-field', 
'small-vehicle', 'large-vehicle', 'ship', 
'tennis-court', 'basketball-court',  
'storage-tank', 'soccer-ball-field', 
'roundabout', 'harbor', 
'swimming-pool', 'helicopter','container-crane'] 

def custombasename(fullname):  
    return os.path.basename(os.path.splitext(fullname)[0])


def limit_value(a,b):
    if a<1:
        a = 1
    if a>=b:
        a = b-1
    return a

    
def readlabeltxt(txtpath, height, width, hbb = True):
    print(txtpath)
    with open(txtpath, 'r') as f_in:   #打開txt檔案          
        lines = f_in.readlines()
        splitlines = [x.strip().split(' ') for x in lines]  #根據空格分割
        # print(splitlines)
        boxes = []
        for i, splitline  in enumerate(splitlines):
            if i in [0,1]:  #DOTA資料集前兩行對于我們來說是無用的
                continue
            
            print(splitline)
            label = splitline[8]
            kunnan = splitline[9]
            if label not in category_set:#隻書寫制定的類别  
                print(label)    
                continue            
            x1 = int(float(splitline[0]))
            y1 = int(float(splitline[1]))
            x2 = int(float(splitline[2]))
            y2 = int(float(splitline[3]))
            x3 = int(float(splitline[4]))
            y3 = int(float(splitline[5]))  
            x4 = int(float(splitline[6]))
            y4 = int(float(splitline[7]))
            #如果是hbb
            if hbb:
                xx1 = min(x1,x2,x3,x4)
                xx2 = max(x1,x2,x3,x4)
                yy1 = min(y1,y2,y3,y4)
                yy2 = max(y1,y2,y3,y4)
                
                xx1 = limit_value(xx1, width)
                xx2 = limit_value(xx2, width)
                yy1 = limit_value(yy1, height)
                yy2 = limit_value(yy2, height)
                
                box = [xx1,yy1,xx2,yy2,label,kunnan]
                boxes.append(box)            
            else:  #否則是obb                        
                x1 = limit_value(x1, width)
                y1 = limit_value(y1, height)
                x2 = limit_value(x2, width)
                y2 = limit_value(y2, height)
                x3 = limit_value(x3, width)
                y3 = limit_value(y3, height)   
                x4 = limit_value(x4, width)
                y4 = limit_value(y4, height)
                               
                box = [x1,y1,x2,y2,x3,y3,x4,y4,label]
                boxes.append(box)
    return boxes
 
def writeXml(tmp, imgname, w, h, d, bboxes, hbb = True):  
    doc = Document()  
    #owner  
    annotation = doc.createElement('annotation')  
    doc.appendChild(annotation)  
    #owner  
    folder = doc.createElement('folder')  
    annotation.appendChild(folder)  
    folder_txt = doc.createTextNode("VOC2007")  
    folder.appendChild(folder_txt)  
  
    filename = doc.createElement('filename')  
    annotation.appendChild(filename)  
    filename_txt = doc.createTextNode(imgname)  
    filename.appendChild(filename_txt)  
    #ones#  
    source = doc.createElement('source')  
    annotation.appendChild(source)  
  
    database = doc.createElement('database')  
    source.appendChild(database)  
    database_txt = doc.createTextNode("My Database")  
    database.appendChild(database_txt)  
  
    annotation_new = doc.createElement('annotation')  
    source.appendChild(annotation_new)  
    annotation_new_txt = doc.createTextNode("VOC2007")  
    annotation_new.appendChild(annotation_new_txt)  
  
    image = doc.createElement('image')  
    source.appendChild(image)  
    image_txt = doc.createTextNode("flickr")  
    image.appendChild(image_txt) 
    #owner
    owner = doc.createElement('owner')  
    annotation.appendChild(owner)  
  
    flickrid = doc.createElement('flickrid')  
    owner.appendChild(flickrid)  
    flickrid_txt = doc.createTextNode("NULL")  
    flickrid.appendChild(flickrid_txt) 
    
    ow_name = doc.createElement('name')  
    owner.appendChild(ow_name)  
    ow_name_txt = doc.createTextNode("idannel")  
    ow_name.appendChild(ow_name_txt)
    #onee#  
    #twos#  
    size = doc.createElement('size')  
    annotation.appendChild(size)  
  
    width = doc.createElement('width')  
    size.appendChild(width)  
    width_txt = doc.createTextNode(str(w))  
    width.appendChild(width_txt)  
  
    height = doc.createElement('height')  
    size.appendChild(height)  
    height_txt = doc.createTextNode(str(h))  
    height.appendChild(height_txt)  
  
    depth = doc.createElement('depth') 
    size.appendChild(depth)  
    depth_txt = doc.createTextNode(str(d))  
    depth.appendChild(depth_txt)  
    #twoe#  
    segmented = doc.createElement('segmented')  
    annotation.appendChild(segmented)  
    segmented_txt = doc.createTextNode("0")  
    segmented.appendChild(segmented_txt)  
    
    for bbox in bboxes:
        #threes#  
        object_new = doc.createElement("object")  
        annotation.appendChild(object_new)  
        
        name = doc.createElement('name')  
        object_new.appendChild(name)  
        name_txt = doc.createTextNode(str(bbox[-2]))  
        name.appendChild(name_txt)  
  
        pose = doc.createElement('pose')  
        object_new.appendChild(pose)  
        pose_txt = doc.createTextNode("Unspecified")  
        pose.appendChild(pose_txt)  
  
        truncated = doc.createElement('truncated')  
        object_new.appendChild(truncated)  
        truncated_txt = doc.createTextNode("0")  
        truncated.appendChild(truncated_txt)  
  
        difficult = doc.createElement('difficult')  
        object_new.appendChild(difficult)  
        difficult_txt = doc.createTextNode(bbox[-1])  
        difficult.appendChild(difficult_txt)  
        #threes-1#  
        bndbox = doc.createElement('bndbox')  
        object_new.appendChild(bndbox)  
  
        if hbb: 
            xmin = doc.createElement('xmin')  
            bndbox.appendChild(xmin)  
            xmin_txt = doc.createTextNode(str(bbox[0]))
            xmin.appendChild(xmin_txt)  
  
            ymin = doc.createElement('ymin')  
            bndbox.appendChild(ymin)  
            ymin_txt = doc.createTextNode(str(bbox[1]))
            ymin.appendChild(ymin_txt)    
  
            xmax = doc.createElement('xmax')  
            bndbox.appendChild(xmax)  
            xmax_txt = doc.createTextNode(str(bbox[2]))
            xmax.appendChild(xmax_txt)  
        
            ymax = doc.createElement('ymax')  
            bndbox.appendChild(ymax)  
            ymax_txt = doc.createTextNode(str(bbox[3]))
            ymax.appendChild(ymax_txt) 
        else:          
            x0 = doc.createElement('x0')  
            bndbox.appendChild(x0)  
            x0_txt = doc.createTextNode(str(bbox[0]))
            x0.appendChild(x0_txt)  
      
            y0 = doc.createElement('y0')  
            bndbox.appendChild(y0)  
            y0_txt = doc.createTextNode(str(bbox[1]))
            y0.appendChild(y0_txt)    
      
            x1 = doc.createElement('x1')  
            bndbox.appendChild(x1)  
            x1_txt = doc.createTextNode(str(bbox[2]))
            x1.appendChild(x1_txt)  
      
            y1 = doc.createElement('y1')  
            bndbox.appendChild(y1)  
            y1_txt = doc.createTextNode(str(bbox[3]))
            y1.appendChild(y1_txt) 
            
            x2 = doc.createElement('x2')  
            bndbox.appendChild(x2)  
            x2_txt = doc.createTextNode(str(bbox[4]))
            x2.appendChild(x2_txt)  
      
            y2 = doc.createElement('y2')  
            bndbox.appendChild(y2)  
            y2_txt = doc.createTextNode(str(bbox[5]))
            y2.appendChild(y2_txt)
     
            x3 = doc.createElement('x3')  
            bndbox.appendChild(x3)  
            x3_txt = doc.createTextNode(str(bbox[6]))
            x3.appendChild(x3_txt)  
      
            y3 = doc.createElement('y3')  
            bndbox.appendChild(y3)  
            y3_txt = doc.createTextNode(str(bbox[7]))
            y3.appendChild(y3_txt)
    
    xmlname = os.path.splitext(imgname)[0]  
    tempfile = os.path.join(tmp ,xmlname+'.xml')
    with open(tempfile, 'wb') as f:
        f.write(doc.toprettyxml(indent='\t', encoding='utf-8'))
    return  

if __name__ == '__main__':
    data_path = './qiege/'
    images_path = os.path.join(data_path) #樣本圖檔路徑
    labeltxt_path = os.path.join('./txt_caijian/') #DOTA标簽的所在路徑
    anno_new_path = os.path.join('./caijian_xml/')  #新的voc格式存儲位置(hbb形式)
    ext = '.jpg'  #樣本圖檔的字尾
    filenames=os.listdir(labeltxt_path)    #擷取每一個txt的名稱   
    for filename in filenames:    
        filepath=labeltxt_path + '/'+filename    #每一個DOTA标簽的具體路徑
        picname = os.path.splitext(filename)[0] + ext  
        pic_path = os.path.join(images_path, picname)   
        print(pic_path)
        im= cv2.imread(pic_path)            #讀取相應的圖檔               
        (H,W,D) = im.shape                  #傳回樣本的大小
        boxes = readlabeltxt(filepath, H, W, hbb = True)           #預設是矩形(hbb)得到gt
        if len(boxes)==0:
            print('檔案為空',filepath)
        #讀取對應的樣本圖檔,得到H,W,D用于書寫xml

        #書寫xml
        writeXml(anno_new_path, picname, W, H, D, boxes, hbb = True)
        print('正在處理%s'%filename)

           

效果展示

使用labelImg軟體打開對應的分割後的圖檔檔案夾和對應的xml檔案夾得到:

DOTA資料集分割圖檔分割裁剪對應的txt将txt轉換為xml效果展示