因为在大图上进行使用labelme进行了标注,但在实际训练过程中发现大图(大概4000x4000)训练的结果并不好,小目标尺寸相比之下非常小(50x50),所以考虑将大图进行裁剪后再进行训练,同时根据已经标注好的json格式文件生成对应的小图的标注。
#将一整张大图切分成多张小图并修改对应的json标注
import cv2
import json
import os
# 读取大图的JSON文件
def splitImgandJson(IPath_json, IPath_img, OPath_json, OPath_img):
events = os.listdir(IPath_json)
#循环处理每一张图像和标注
for onevent in events:
name = onevent.split('.json')[0]
img_name = name + '.jpg'
with open(os.path.join(IPath_json, onevent), 'r') as json_file:
large_json_data = json.load(json_file)
# 读取大图的JPEG图像
large_image = cv2.imread(os.path.join(IPath_img, img_name))
# 定义每个小图的大小
crop_width, crop_height = 500, 500 # 可以根据需要调整大小
# 循环裁剪图像并生成新的JSON文件
L_H = large_image.shape[0]
L_W = large_image.shape[1]
for i in range(0, L_H, crop_height):
for j in range(0, L_W, crop_width):
# 裁剪图像
small_image = large_image[i:i + crop_height, j:j + crop_width]
# 创建新的JSON数据,基于大图的JSON数据进行调整
small_json_data = large_json_data.copy()
# 遍历大图标注看是否存在在小图中
new_target = [] # 替换'shapes'
for items in large_json_data[('shapes')]:
# 提取边界框坐标
x1, y1 = items["points"][0]
x2, y2 = items["points"][1]
# 判断目标框在小图中的位置
# 1、目标框全在小图中
new_item = items.copy()
if (j <= x1) and (x2 <= j + crop_width) and (i <= y1) and (y2 <= i + crop_height):
new_item['points'] = [[x1 - j, y1 - i], [x2 - j, y2 - i]]
new_target.append(new_item)
continue
# 2、某一点在小图中并且所占面积超过目标面积的40%(比例可以根据需要调整)
elif ((j < x1 < j + crop_width) and (i < y1 < i + crop_height)) or (
(j < x2 < j + crop_width) and (i < y1 < i + crop_height)) or (
(j < x1 < j + crop_width) and (i < y2 < i + crop_height)) or ((
j < x2 < j + crop_width) and (i < y2 < i + crop_height)):
x_min = max(j, x1)-j
y_min = max(i, y1)-i
x_max = min(x2, j + crop_width)-j
y_max = min(y2, i + crop_height)-i
if (x_max - x_min) * (y_max - y_min) > 0.4 * (x2 - x1) * (y2 - y1):
new_item['points'] = [[x_min, y_min], [x_max, y_max]]
new_target.append(new_item)
continue
else:
continue
if new_target != []:
small_json_data['shapes'] = new_target
small_json_data["imageWidth"] = crop_width
small_json_data["imageHeight"] = crop_height
# 保存小图的JSON文件
small_json_filename = f'{name}_{i}_{j}.json'
with open(os.path.join(OPath_json, small_json_filename), 'w') as small_json_file:
json.dump(small_json_data, small_json_file, indent=4)
# 保存小图的JPEG图像
small_image_filename = f'{name}_{i}_{j}.jpg'
cv2.imwrite(os.path.join(OPath_img, small_image_filename), small_image)
# 完成后,你会得到多个小图像和对应的JSON文件
if __name__ == '__main__':
IPath_json = 'D:\Projects\Python\dataB\Json'
IPath_img = 'D:\Projects\Python\dataB\JPEGImgs'
OPath_json = 'D:\Projects\Python\dataB\json_s500'
OPath_img = 'D:\Projects\Python\dataB\img_s500'
if not os.path.exists(OPath_json):
os.mkdir(OPath_json)
if not os.path.exists(OPath_img):
os.mkdir(OPath_img)
splitImgandJson(IPath_json,IPath_img,OPath_json,OPath_img)