DOTA数据集图像及标签裁剪

DOTA数据集图像及标签裁剪

批量裁剪DOTA数据集图片及标签,只需修改main中的路径,及裁剪的尺寸size_w,size_h,重叠步长step。不区分DOTA版本,都可用。
裁剪完成后的标签格式和DOTA原始标签格式保持一致,若要用yolo之类的进行训练,可再将裁剪后的标签转换为yolo格式

import cv2
import os


#  图像宽不足裁剪宽度,填充至裁剪宽度
def fill_right(img, size_w):
    size = img.shape
    #  填充值为数据集均值
    img_fill_right = cv2.copyMakeBorder(img, 0, 0, 0, size_w - size[1],
                                        cv2.BORDER_CONSTANT, value=(107, 113, 115))
    return img_fill_right


#  图像高不足裁剪高度,填充至裁剪高度
def fill_bottom(img, size_h):
    size = img.shape
    img_fill_bottom = cv2.copyMakeBorder(img, 0, size_h - size[0], 0, 0,
                                         cv2.BORDER_CONSTANT, value=(107, 113, 115))
    return img_fill_bottom


#  图像宽高不足裁剪宽高度,填充至裁剪宽高度
def fill_right_bottom(img, size_w, size_h):
    size = img.shape
    img_fill_right_bottom = cv2.copyMakeBorder(img, 0, size_h - size[0], 0, size_w - size[1],
                                               cv2.BORDER_CONSTANT, value=(107, 113, 115))
    return img_fill_right_bottom


#  图像切割
#  img_floder 图像文件夹
#  out_img_floder 图像切割输出文件夹
#  size_w 切割图像宽
#  size_h 切割图像高
#  step 切割步长
def image_split(img_floder, out_img_floder, size_w, size_h, step):
    print("进行图像的裁剪--------------------------------")
    img_list = os.listdir(img_floder)
    count = 0
    for img_name in img_list:
        number = 0
        #  去除.png后缀
        name = img_name[:-4]
        img = cv2.imread(img_floder + "" + img_name)
        size = img.shape
        #  若图像宽高大于切割宽高
        if size[0] >= size_h and size[1] >= size_w:
            count = count + 1
            for h in range(0, size[0] - 1, step):
                start_h = h
                for w in range(0, size[1] - 1, step):
                    start_w = w
                    end_h = start_h + size_h
                    if end_h > size[0]:
                        start_h = size[0] - size_h
                        end_h = start_h + size_h
                    end_w = start_w + size_w
                    if end_w > size[1]:
                        start_w = size[1] - size_w
                    end_w = start_w + size_w
                    cropped = img[start_h: end_h, start_w: end_w]
                    #  用起始坐标来命名切割得到的图像,为的是方便后续标签数据抓取
                    name_img = name + '_' + str(start_h) + '_' + str(start_w)
                    cv2.imwrite('{}/{}.png'.format(out_img_floder, name_img), cropped)
                    number = number + 1
        #  若图像高大于切割高,但宽小于切割宽
        elif size[0] >= size_h and size[1] < size_w:
            print('图片{}需要在右面补齐'.format(name))
            count = count + 1
            img0 = fill_right(img, size_w)
            for h in range(0, size[0] - 1, step):
                start_h = h
                start_w = 0
                end_h = start_h + size_h
                if end_h > size[0]:
                    start_h = size[0] - size_h
                    end_h = start_h + size_h
                end_w = start_w + size_w
                cropped = img0[start_h: end_h, start_w: end_w]
                name_img = name + '_' + str(start_h) + '_' + str(start_w)
                cv2.imwrite('{}/{}.png'.format(out_img_floder, name_img), cropped)
                number = number + 1
        #  若图像宽大于切割宽,但高小于切割高
        elif size[0] < size_h and size[1] >= size_w:
            count = count + 1
            print('图片{}需要在下面补齐'.format(name))
            img0 = fill_bottom(img, size_h)
            for w in range(0, size[1] - 1, step):
                start_h = 0
                start_w = w
                end_w = start_w + size_w
                if end_w > size[1]:
                    start_w = size[1] - size_w
                    end_w = start_w + size_w
                end_h = start_h + size_h
                cropped = img0[start_h: end_h, start_w: end_w]
                name_img = name + '_' + str(start_h) + '_' + str(start_w)
                cv2.imwrite('{}/{}.png'.format(out_img_floder, name_img), cropped)
                number = number + 1
        #  若图像宽高小于切割宽高
        elif size[0] < size_h and size[1] < size_w:
            count = count + 1
            print('图片{}需要在下面和右面补齐'.format(name))
            img0 = fill_right_bottom(img, size_w, size_h)
            cropped = img0[0: size_h, 0: size_w]
            name_img = name + '_' + '0' + '_' + '0'
            cv2.imwrite('{}/{}.png'.format(out_img_floder, name_img), cropped)
            number = number + 1
        print('{}.png切割成{}张.'.format(name, number))
    print('共完成{}张图片'.format(count))



def txt_split(out_img_floder, txt_floder, out_txt_floder, size_h, size_w):
    print("进行标签文件的裁剪----------------------------")
    img_list = os.listdir(out_img_floder)
    for img_name in img_list:
        #  去除.png后缀
        name = img_name[:-4]
        #  得到原图像(也即txt)索引 + 切割高 + 切割宽
        name_list = name.split('_')
        txt_name = name_list[0]
        h = int(name_list[1])
        w = int(name_list[2])
        txtpath = txt_floder + "" + txt_name + '.txt'
        out_txt_path = out_txt_floder + "" + name + '.txt'
        f = open(out_txt_path, 'a')
        #  打开txt文件
        with open(txtpath, 'r') as f_in:
            lines = f_in.readlines()
            #  逐行读取
            for line in lines:
                splitline = line.split(',')
                # print("---",splitline[0].split('(')[1])
                # print("---", splitline[1].split(')')[0])
                # print("---", splitline[2].split('(')[1])
                # print("---", splitline[3].split(')')[0])
                label = splitline[4]
                x1 = int(splitline[0].split('(')[1])
                y1 = int(splitline[1].split(')')[0])
                x2 = int(splitline[2].split('(')[1])
                y2 = int(splitline[3].split(')')[0])

                if w <= x1 <= w + size_w and w <= x2 <= w + size_w and h <= y1 <= h + size_h and h <= y2 <= h + size_h:
                    f.write('({},{}),({},{}),{}'.format(int(x1 - w),
                            int(y1 - h), int(x2 - w), int(y2 - h),
                            label))
        print('{}.txt切割完成.'.format(name))
    f.close()


'''
对裁剪后的影像中的标签实现自动抓取
'''
def tqtxt(path,path_txt,path_out,size_h,size_w):
    ims_list=os.listdir(path)
    for im_list in ims_list:
        name_list = []
        name = im_list[:-4]
        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()
             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]

                 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='D:/data/DOTA/images/val/'             # 图像数据集的路径
    out_img_path='D:/data/DOTA/images/val_1024/'  # 裁剪后图像数据集的路径
    txt_path = 'D:/data/DOTA/val/vallabelTxt-v1.5/DOTA-v1.5_val/'  #原数据集标签文件
    out_txt_path = 'D:/data/DOTA/val/val1.5_1024/'                         #裁剪后数据集的标签文件存放路径

    size_w =1024
    size_h = 1024
    step=400    #重叠步长
    #1.图像裁剪
    image_split(ims_path, out_img_path, size_w=size_w, size_h=size_h, step=step)
    #2.标签裁剪
    tqtxt(out_img_path,txt_path,out_txt_path,size_w=size_w,size_h =size_h)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值