写在前面的话
标注使用的软件是labelme,当一张图有多个同名的 polygon标注 和 point标注 ,这个代码的作用是把它们分开成独立的标注文件,方便后续使用。下面【原图和标注】是原始的标注结果,再下面的【单个目标裁剪保存】是分开后的结果。
提示:这里会用到Polygon().contains()
函数,作用是判断标注的 point 是否在 ploygon 的内部,这里默认标注的点都在多边形的内部。该函数需要下载shapely函数库
pip install shapely
原图和标注
单个目标裁剪保存
完整代码
import copy
import json
import glob
import cv2
import os
import numpy as np
from shapely.geometry import Polygon
from shapely.geometry import Point
load_img_dir = 'C://Users/Chengguo/Desktop/bugger/pigs/t01bd99031cb1a0e08d.jpg' # 原始图片和json文件的路径
load_json_dir = 'C://Users/Chengguo/Desktop/bugger/pigs/t01bd99031cb1a0e08d.json' # 原始图片和json文件的路径
save_data_dir = 'C://Users/Chengguo/Desktop/bugger/pigs/' # 裁剪后图片和json文件保存的路径
def crop_jsons(load_data_dir, save_data_dir):
for jf in [load_data_dir]:
with open(jf, "r") as f:
json_str = f.read()
origin_dict = json.loads(json_str) # json格式转python格式
#创建一个可以修改的字典,主要修改文件名和【shapes】属性
your_dict = copy.deepcopy(origin_dict)
#多个命名为pig的多边形
pig_masks = [i for i in origin_dict['shapes'] if i['label'] == 'pig']
num_pig = len(pig_masks)
#遍历同名的多边形
for i, pig_mask in enumerate(pig_masks):
all_shapes = []
xmin = np.array(pig_mask['points'])[:, 0].min()
xmax = np.array(pig_mask['points'])[:, 0].max()
ymin = np.array(pig_mask['points'])[:, 1].min()
ymax = np.array(pig_mask['points'])[:, 1].max()
box_h = int(ymax - ymin)
box_w = int(xmax - xmin)
# seg_img = np.zeros([box_h, box_w], dtype=np.int32)
# seg_points = np.array(pig_mask['pig'], dtype=np.int32)
# cv2.fillPoly(seg_img, seg_points, (255, 0, 0))
your_dict["imageData"] = None # python中None即是null
your_dict["imagePath"] = f"_{
i}_" + os.path.basename(jf)[:-5] + '.jpg' # 图像文件名
# your_dict["imageHeight"] = box_h
# your_dict["imageWidth"] = box_w
#遍历所有的标注点
for joint in origin_dict['shapes']:
if joint['shape_type'] == 'polygon':#跳过多边形
continue
box_joints = {
}
#判断标注的 **point** 是否在 **ploygon** 的内部,只保留在多边形内部的点
if Polygon(pig_mask['points']).contains(Point(joint['points'][0])):
box_joints['label'] = joint['label']
box_joints['points'] = joint['points']
box_joints['group_id'] = None
box_joints['shape_type'] = 'point'
box_joints['flags'] = {
}
all_shapes.append(box_joints)#加入符合条件的点
all_shapes.append(pig_mask)#加入多边形
your_dict['shapes'] = all_shapes#替换
'''保存json文件'''
save_dir = save_data_dir + f"new/_{
i}_" + os.path.basename(jf)
with open(save_dir, "w", encoding="UTF-8") as f1:#保存json
json.dump(your_dict, f1, ensure_ascii=False, indent=2)
def main():
crop_jsons(load_json_dir, save_data_dir)
if __name__ == "__main__":
main()