大场景图片切图python脚本

大场景图片切图python脚本

同时对原图和xml标注进行切割
优点:
1、使用了overlap的分割方法
2、对边界的小目标框进行了省略

# -*- coding: utf-8 -*-
"""
@Author  : zengwb
@Time    : 2021/4/17
@Software: PyCharm
"""
import os
import cv2
import time
import codecs
import xml.etree.ElementTree as ET
from tqdm import tqdm
import shutil
from tqdm import trange                  # 显示进度条
from multiprocessing import cpu_count    # 查看cpu核心数
from multiprocessing import Pool
import numpy as npdef get(root, name):  ##获取根目录vars = root.findall(name)return vars  ###并返回一个列表
def get_and_check(root, name, length):vars = root.findall(name)if len(vars) == 0:raise NotImplementedError('Can not find %s in %s.'%(name, root.tag))if length > 0 and len(vars) != length:raise NotImplementedError('The size of %s is supposed to be %d, but is %d.'%(name, length, len(vars)))if length == 1:vars = vars[0]return varsdef deal_xml(xml_f):  ###处理xml的函数tree = ET.parse(xml_f)root = tree.getroot()  ###根目路的object_list=[]    ###目标的列表# 处理每个标注的检测框for obj in get(root, 'object'): ###遍历所有的objet字段# 取出检测框类别名称category = get_and_check(obj, 'name', 1).text# 更新类别ID字典bndbox = get_and_check(obj, 'bndbox', 1)xmin = int(get_and_check(bndbox, 'xmin', 1).text) - 1ymin = int(get_and_check(bndbox, 'ymin', 1).text) - 1xmax = int(get_and_check(bndbox, 'xmax', 1).text)ymax = int(get_and_check(bndbox, 'ymax', 1).text)assert (xmax > xmin)assert (ymax > ymin)o_width = abs(xmax - xmin)o_height = abs(ymax - ymin)obj_info=[xmin,ymin,xmax,ymax,category]object_list.append(obj_info)return object_listdef exist_objs(list_1,list_2, sliceHeight, sliceWidth):'''list_1:当前slice的图像list_2:原图中的所有目标return:原图中位于当前slicze中的目标集合'''return_objs=[]### 设置最小目标的尺寸min_h, min_w = 35, 35  # 有些目标GT会被窗口切分,太小的丢掉s_xmin, s_ymin, s_xmax, s_ymax = list_1[0], list_1[1], list_1[2], list_1[3]  ###获取当前切片中的图像for vv in list_2:xmin, ymin, xmax, ymax,category=vv[0],vv[1],vv[2],vv[3],vv[4]  ###获取原图中的切片图像# 1111111if s_xmin<=xmin<s_xmax and s_ymin<=ymin<s_ymax:  # 目标点的左上角在切图区域中if s_xmin<xmax<=s_xmax and s_ymin<ymax<=s_ymax:  # 目标点的右下角在切图区域中x_new=xmin-s_xminy_new=ymin-s_yminreturn_objs.append([x_new,y_new,x_new+(xmax-xmin),y_new+(ymax-ymin),category])if s_xmin<=xmin<s_xmax and ymin < s_ymin:  # 目标点的左上角在切图区域上方# 22222222if s_xmin < xmax <= s_xmax and s_ymin < ymax <= s_ymax:  # 目标点的右下角在切图区域中x_new = xmin - s_xminy_new = 0if xmax - s_ymax - x_new > min_w and ymax - s_ymax - y_new > min_h:return_objs.append([x_new, y_new, xmax - s_ymax, ymax - s_ymax, category])# 33333333if xmax > s_xmax and s_ymin < ymax <= s_ymax:  # 目标点的右下角在切图区域右方x_new = xmin - s_xminy_new = 0if s_xmax-s_xmin - x_new > min_w and ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, s_xmax-s_xmin, ymax - s_ymin, category])if s_ymin < ymin <= s_ymax and xmin < s_xmin:  # 目标点的左上角在切图区域左方# 444444if s_xmin < xmax <= s_xmax and s_ymin < ymax <= s_ymax:  # 目标点的右下角在切图区域中x_new = 0y_new = ymin - s_yminif xmax - s_xmin - x_new > min_w and ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, xmax - s_xmin, ymax - s_ymin, category])# 555555if s_xmin < xmax < s_xmax and ymax >= s_ymax:   # 目标点的右下角在切图区域下方x_new = 0y_new = ymin - s_yminif xmax - s_xmin - x_new > min_w and s_ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, xmax - s_xmin, s_ymax - s_ymin, category])# 666666if s_xmin >= xmin  and ymin <= s_ymin:  # 目标点的左上角在切图区域左上方if s_xmin<xmax<=s_xmax and s_ymin<ymax<=s_ymax:  # 目标点的右下角在切图区域中x_new = 0y_new = 0if xmax - s_xmin - x_new > min_w and ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, xmax - s_xmin, ymax - s_ymin, category])# 777777if s_xmin <= xmin < s_xmax and s_ymin <= ymin < s_ymax:  # 目标点的左上角在切图区域中if ymax >= s_ymax and xmax >= s_xmax:              # 目标点的右下角在切图区域右下方x_new = xmin - s_xminy_new = ymin - s_yminif s_xmax - s_xmin - x_new > min_w and s_ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, s_xmax - s_xmin, s_ymax - s_ymin, category])# 8888888if s_xmin < xmax < s_xmax and ymax >= s_ymax:  # 目标点的右下角在切图区域下方x_new = xmin - s_xminy_new = ymin - s_yminif xmax - s_xmin - x_new > min_w and s_ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, xmax - s_xmin, s_ymax - s_ymin, category])# 999999if xmax > s_xmax and s_ymin < ymax <= s_ymax:  # 目标点的右下角在切图区域右方x_new = xmin - s_xminy_new = ymin - s_yminif s_xmax - s_xmin - x_new > min_w and ymax - s_ymin - y_new > min_h:return_objs.append([x_new, y_new, s_xmax - s_xmin, ymax - s_ymin, category])return return_objs
def bbox_iou(box1, box2):""":param box1: = [xmin1, ymin1, xmax1, ymax1]:param box2: = [xmin2, ymin2, xmax2, ymax2]:return: """xmin1, ymin1, xmax1, ymax1 = box1xmin2, ymin2, xmax2, ymax2 = box2# 计算每个矩形的面积s1 = (xmax1 - xmin1) * (ymax1 - ymin1)  # b1的面积s2 = (xmax2 - xmin2) * (ymax2 - ymin2)  # b2的面积# 计算相交矩形xmin = max(xmin1, xmin2)ymin = max(ymin1, ymin2)xmax = min(xmax1, xmax2)ymax = min(ymax1, ymax2)w = max(0, xmax - xmin)h = max(0, ymax - ymin)a1 = w * h  # C∩G的面积a2 = s2# + s2 - a1iou = a1 / a2 #iou = a1/ (s1 + s2 - a1)return iou
def exist_objs_iou(list_1, list_2, sliceHeight, sliceWidth,win_h, win_w):# 根据iou判断框是否保留,并返回bboxreturn_objs=[]s_xmin, s_ymin, s_xmax, s_ymax = list_1[0], list_1[1], list_1[2], list_1[3]for single_box in list_2:xmin, ymin, xmax, ymax, category=single_box[0],single_box[1],single_box[2],single_box[3],single_box[4]iou = bbox_iou(list_1, single_box[:4])if iou > 0.2:if iou == 1:x_new=xmin-s_xminy_new=ymin-s_yminreturn_objs.append([x_new, y_new, x_new+(xmax-xmin), y_new+(ymax-ymin),category])else:xlist = np.sort([xmin, xmax, s_xmin, s_xmax])ylist = np.sort([ymin, ymax, s_ymin, s_ymax])#print(win_h, win_w, list_1, single_box, xlist[1] - s_xmin, ylist[1] - s_ymin)return_objs.append([xlist[1] - s_xmin, ylist[1] - s_ymin, xlist[2] - s_xmin, ylist[2] - s_ymin, category])return return_objs
def make_slice_voc(outpath,exiset_obj_list,sliceHeight=1024, sliceWidth=1024):name=outpath.split('/')[-1]##with codecs.open(os.path.join(slice_voc_dir,  name[:-4] + '.xml'), 'w', 'utf-8') as xml:xml.write('<annotation>\n')xml.write('\t<filename>' + name + '</filename>\n')xml.write('\t<size>\n')xml.write('\t\t<width>' + str(sliceWidth) + '</width>\n')xml.write('\t\t<height>' + str(sliceHeight) + '</height>\n')xml.write('\t\t<depth>' + str(3) + '</depth>\n')xml.write('\t</size>\n')cnt = 1for obj in exiset_obj_list:#bbox = obj[:4]class_name = obj[-1]xmin, ymin, xmax, ymax = bbox#xml.write('\t<object>\n')xml.write('\t\t<name>' + class_name + '</name>\n')xml.write('\t\t<bndbox>\n')xml.write('\t\t\t<xmin>' + str(int(xmin)) + '</xmin>\n')xml.write('\t\t\t<ymin>' + str(int(ymin)) + '</ymin>\n')xml.write('\t\t\t<xmax>' + str(int(xmax)) + '</xmax>\n')xml.write('\t\t\t<ymax>' + str(int(ymax)) + '</ymax>\n')xml.write('\t\t</bndbox>\n')xml.write('\t</object>\n')cnt += 1assert cnt > 0xml.write('</annotation>')###############################################################################
def slice_im(List_subsets, outdir, raw_images_dir, raw_ann_dir, i=None, sliceHeight=640, sliceWidth=640,zero_frac_thresh=0.2, overlap=0.2, verbose=True):cnt = 0# print(List_subsets)for per_img_name in tqdm(List_subsets):# print(per_img_name)# if 'c' not in per_img_name:#     continueo_name, _ = os.path.splitext(per_img_name)out_name = str(o_name) + '_' + str(cnt)image_path = os.path.join(raw_images_dir, per_img_name)ann_path = os.path.join(raw_ann_dir, per_img_name[:-4] + '.xml')image0 = cv2.imread(image_path, 1)  # colorext = '.' + image_path.split('.')[-1]win_h, win_w = image0.shape[:2]# if slice sizes are large than image, pad the edges# 避免出现切图的大小比原图还大的情况object_list = deal_xml(ann_path)pad = 0if sliceHeight > win_h:pad = sliceHeight - win_hif sliceWidth > win_w:pad = max(pad, sliceWidth - win_w)# pad the edge of the image with black pixelsif pad > 0:border_color = (0, 0, 0)image0 = cv2.copyMakeBorder(image0, pad, pad, pad, pad,cv2.BORDER_CONSTANT, value=border_color)win_size = sliceHeight * sliceWidtht0 = time.time()n_ims = 0n_ims_nonull = 0dx = int((1. - overlap) * sliceWidth)   # 153dy = int((1. - overlap) * sliceHeight)for y0 in range(0, image0.shape[0], dy):for x0 in range(0, image0.shape[1], dx):n_ims += 1##这一步确保了不会出现比要切的图像小的图,其实是通过调整最后的overlop来实现的#举例:h=6000,w=8192.若使用640来切图,overlop:0.2*640=128,间隔就为512.所以小图的左上角坐标的纵坐标y0依次为:#:0,512,1024,....,5120,接下来并非为5632,因为5632+640>6000,所以y0=6000-640if y0 + sliceHeight > image0.shape[0]:y = image0.shape[0] - sliceHeightelse:y = y0if x0 + sliceWidth > image0.shape[1]:x = image0.shape[1] - sliceWidthelse:x = x0#slice_xmax = x + sliceWidthslice_ymax = y + sliceHeightexiset_obj_list=exist_objs([x,y,slice_xmax,slice_ymax],object_list, sliceHeight, sliceWidth)# exiset_obj_list = exist_objs_iou([x,y,slice_xmax,slice_ymax],object_list, sliceHeight, sliceWidth, win_h, win_w)if exiset_obj_list!=[]:  # 如果为空,说明切出来的这一张图不存在目标# extract imagewindow_c = image0[y:y + sliceHeight, x:x + sliceWidth]# get black and white imagewindow = cv2.cvtColor(window_c, cv2.COLOR_BGR2GRAY)# find threshold that's not black#ret, thresh1 = cv2.threshold(window, 2, 255, cv2.THRESH_BINARY)non_zero_counts = cv2.countNonZero(thresh1)zero_counts = win_size - non_zero_countszero_frac = float(zero_counts) / win_size# print "zero_frac", zero_fra# skip if image is mostly emptyif zero_frac >= zero_frac_thresh:if verbose:print("Zero frac too high at:", zero_frac)continue# else saveelse:outpath = os.path.join(outdir, out_name + \'-' + str(y) + '_' + str(x) + '_' + str(sliceHeight) + '_' + str(sliceWidth) + \'_' + str(pad) + '_' + str(win_w) + '_' + str(win_h) + ext)#cnt += 1# if verbose:#     print("outpath:", outpath)cv2.imwrite(outpath, window_c)n_ims_nonull += 1#------制作新的xml------make_slice_voc(outpath,exiset_obj_list,sliceHeight,sliceWidth)if __name__ == "__main__":not_use_multiprocessing = Trueraw_images_dir = ''   # 这里就是原始的图片raw_ann_dir = ''slice_voc_dir = ''  # 切出来的标签也保存为voc格式outdir = ''if not os.path.exists(slice_voc_dir):os.makedirs(slice_voc_dir)if not os.path.exists(outdir):os.makedirs(outdir)List_imgs = os.listdir(raw_images_dir)if not_use_multiprocessing:slice_im(List_imgs, outdir, raw_images_dir, raw_ann_dir, sliceHeight=768, sliceWidth=768)else:Len_imgs = len(List_imgs)   # 数据集长度num_cores = cpu_count()  # cpu核心数# print(num_cores, Len_imgs)if num_cores >= 8:  # 八核以上,将所有数据集分成八个子数据集num_cores = 8subset1 = List_imgs[:Len_imgs // 8]subset2 = List_imgs[Len_imgs // 8: Len_imgs // 4]subset3 = List_imgs[Len_imgs // 4: (Len_imgs * 3) // 8]subset4 = List_imgs[(Len_imgs * 3) // 8: Len_imgs // 2]subset5 = List_imgs[Len_imgs // 2: (Len_imgs * 5) // 8]subset6 = List_imgs[(Len_imgs * 5) // 8: (Len_imgs * 6) // 8]subset7 = List_imgs[(Len_imgs * 6) // 8: (Len_imgs * 7) // 8]subset8 = List_imgs[(Len_imgs * 7) // 8:]List_subsets = [subset1, subset2, subset3, subset4, subset5, subset6, subset7, subset8]p = Pool(num_cores)for i in range(num_cores):p.apply_async(slice_im, args=(List_subsets[i], outdir, raw_images_dir, raw_ann_dir, i))p.close()p.join()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/62310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python项目日志打点功能实现方法

一、入门介绍 1.1 logging和logger的区别 logging和logger是Python的logging模块中的两个关键概念&#xff0c;它们在功能和用途上有明显的区别。 logging是一个Python标准库&#xff0c;是一个用于记录日志的标准模块。它提供了一个灵活的框架&#xff0c;可以用来记录不同级…

Qt应用开发(基础篇)——对话框窗口 QDialog

一、前言 QDialog类继承于QWidget&#xff0c;是Qt基于对话框窗口(消息窗口QMessageBox、颜色选择窗口QColorDialog、文件选择窗口QFileDialog等)的基类。 QDialog窗口是顶级的窗口&#xff0c;一般情况下&#xff0c;用来当做用户短期任务(确认、输入、选择)或者和用户交流(提…

一、安装GoLang环境和开发工具

一、安装GoLang环境 GoLang中国镜像站 下载后对应的环境包以后&#xff0c;一路下一步就好了&#xff0c;安装路径的话&#xff0c;尽量就安装到默认的文件目录下。 二、配置Go的环境变量 右击此电脑–>属性–>高级系统设置–>环境变量&#xff0c;打开环境变量设置…

MySQL高阶语句之常用查询

目录 常用查询 按关键字排序 区间判断及查询不重复记录 对结果进行分组 限制结果条目 设置别名 通配符 子查询 常用查询 &#xff08;增、删、改、查&#xff09; 对 MySQL 数据库的查询&#xff0c;除了基本的查询外&#xff0c;有时候需要对查询的结果集进行处理。 …

设计模式之工厂模式(万字长文)

文章目录 概述工厂模式的优点包括工厂模式有几种主要的变体看一个具体需求使用传统的方式来完成传统的方式的优缺点 简单工厂模式基本介绍使用简单工厂模式简单工厂模式的优缺点优点&#xff1a;缺点&#xff1a; 工厂方法模式看一个新的需求思路 1思路 2工厂方法模式介绍工厂方…

生成式AI,赋能数字劳动力的关键工具

人们认为&#xff0c;生成式人工智能是一种可以让他们用自己的话来提问或生成副本和图像的工具。事实也是如此&#xff0c;人工智能在这两方面上都做的非常好&#xff0c;但让人意想不到的是&#xff0c;它还蕴含着改变我们个人和专业工作的巨大潜力&#xff0c;能帮我们访问、…

Unity记录4.5-存储-随角色加载的Tilemap

文章首发见博客&#xff1a;https://mwhls.top/4820.html。 无图/格式错误/后续更新请见首发页。 更多更新请到mwhls.top查看 欢迎留言提问或批评建议&#xff0c;私信不回。 汇总&#xff1a;Unity 记录 摘要&#xff1a;随着角色移动而动态加载的tilemap。 思路-2023/08/18 …

nextTick原理

nextTick 是 Vue 提供的一个异步方法&#xff0c;用于在 DOM 更新之后执行回调函数。它的原理是利用 JavaScript 的事件循环机制来实现异步执行。 具体来说&#xff0c;当我们调用 nextTick 方法时&#xff0c;Vue 会将传入的回调函数添加到一个队列中。在下一个事件循环中&am…

Django(7)-项目实战-发布会签到管理系统

本文使用django实现一个简单的发布会签到管理系统 登录功能 模板页面 sign/templates/index.html <!DOCTYPE html> <html> <head><title>Login Page</title> </head> <body><h1>发布会管理</h1><form action=&qu…

springboot实战(一)之项目搭建

环境准备 ideajdk1.8springboot版本 2.7.15 项目开始 1.打开idea&#xff0c;点击new project 2.选择spring initillizr 核对&#xff1a;Server Url是否是&#xff1a;start.spring.io&#xff0c;然后根据自己依次设置项目名称、存储位置和包名&#xff0c;如下&#xff…

北京开发APP的费用明细

开发APP项目时&#xff0c;在功能确定后需要知道有哪些可能的费用&#xff0c;安排项目预算。北京开发APP的费用明细可能会包括以下几个部分&#xff0c;每个部分都会产生一些费用。今天和大家分享APP费用明细有哪些&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&…

C语言 - 程序的分文件编写

说明过程 C语言程序可以通过分文件编写来提高代码的结构性和可维护性。下面是一个简单的示例&#xff0c;展示了C语言程序如何分文件编写&#xff1a; 创建多个源文件&#xff1a;将程序的不同部分分别写在不同的源文件中&#xff0c;每个文件包含一个或多个相关的函数。比如&…

vue2 自定义指令,插槽

一、学习目标 1.自定义指令 基本语法&#xff08;全局、局部注册&#xff09;指令的值v-loading的指令封装 2.插槽 默认插槽具名插槽作用域插槽 二、自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v-if、v-bind、v-on… 这都是Vue给咱们内置的一些指令&#xff0c;…

大数据之Maven

一、Maven的作用 作用一&#xff1a;下载对应的jar包 避免jar包重复下载配置&#xff0c;保证多个工程共用一份jar包。Maven有一个本地仓库&#xff0c;可以通过pom.xml文件来记录jar所在的位置。Maven会自动从远程仓库下载jar包&#xff0c;并且会下载所依赖的其他jar包&…

《信息系统项目管理师教程(第4版)》第17章 采购管理、合同管理 知识点整理,xmind思维导图

已上传采购管理xmind思维导图&#xff0c;需要的同学可以直接下载哦。 一、规划采购管理 二、实施采购 三、控制采购 四、合同管理 4.1 合同类型 4.2 合同管理过程 签订履行变更档案&#xff0c;合同档案管理是整个合同管理的基础&#xff0c;要求采用电脑打印文本&#xff…

考研408 | 【操作系统】终章

I/O设备的基本概念和分类 I/O设备&#xff1a; I/O设备的分类 1.按使用特性&#xff1a; 2.按传输速率分类&#xff1a; 3.按信息交换的单位分类&#xff1a; 总结&#xff1a; I/O控制器 I/O设备的机械部件&#xff1a; I/O设备的电子部件&#xff08;I/O控制器&#…

国标视频融合云平台EasyCVR视频汇聚平台的应用场景及其功能说明

一、平台简介 EasyCVR国标视频融合云平台是一款基于端-边-云一体化架构的视频融合AI智能分析网关平台。EasyCVR平台支持视频汇聚、融合管理&#xff0c;兼容多类型设备、多协议接入。其提供的视频功能包括&#xff1a;视频监控、无插件直播录像、云存储、检索回放、智能告警、…

uniapp微信小程序使用stomp.js实现STOMP传输协议的实时聊天

简介&#xff1a; 原生微信小程序中使用 本来使用websocket&#xff0c;后端同事使用了stomp协议&#xff0c;导致前端也需要对应修改。 如何使用 1.yarn add stompjs 2.版本 “stompjs”: “^2.3.3” 3.在static/js中新建stomp.js和websocket.js&#xff0c;然后在需要使用…

E8267D 是德科技矢量信号发生器

描述 最先进的微波信号发生器 安捷伦E8267D PSG矢量信号发生器是业界首款集成式微波矢量信号发生器&#xff0c;I/Q调制最高可达44 GHz&#xff0c;典型输出功率为23 dBm&#xff0c;最高可达20 GHz&#xff0c;对于10 GHz信号&#xff0c;10 kHz偏移时的相位噪声为-120 dBc/…

Linux防火墙命令

开启防火墙 systemctl start firewalld关闭防火墙 systemctl stop firewalld # 暂时关闭防火墙 systemctl disable firewalld # 永久关闭防火墙(禁用开机自启) systemctl enable firewalld # 永久开启防火墙(启用开机自启)重启防火墙 systemctl restart firewalld重载规则 …