对labelme已经标注的图片和json文件做resize操作

尝试解决的问题

项目中要使用实例分割网络将图片中的目标分割出来,但是原图普遍非常大,大部分是 (5000pixels * 6000pixels) 这样的规格,如果直接传到网络中进行训练,计算量会非常大。所以考虑先离线resize好了之后作为数据集再训练网络,而不是在输入网络之间才resize(这样会很浪费时间)。

实现代码

废话少说,直接上代码即可:代码逻辑大概为先统计文件夹中的是图片的文件格式,例如有 {'jpg', 'JPG', 'png'} 这三种,接着使用 glob 库找到包含这几种后缀格式的所有图片文件,对这些照片使用 cv2.resize() 函数进行等比例缩放,缩放后保存到目标文件夹去。另外也要对json格式的标注文件中的点坐标进行缩放,直接坐标乘以缩放比例即可。最后值得注意的一点是,json标注文件中的 ['imageData'] 字段也要改成resize之后的图片哦,不然使用labelme 打开后的图片还是原来没有resize前的图,polygons 的位置跟大小是不对的。

import cv2
import os
import glob
import json
import collections
import numpy as np
from labelme import utils


if __name__ == "__main__":
    src_dir = './srcDir'
    dst_dir = './dstDir'
    
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    # 先收集一下文件夹中图片的格式列表,例如 ['.jpg', '.JPG']
    exts = dict()
    filesnames = os.listdir(src_dir)
    for filename in filesnames:
        name, ext = filename.split('.')
        if ext != 'json':
            if exts.__contains__(ext):
                exts[ext] += 1
            else:
                exts[ext] = 1

    anno = collections.OrderedDict()  # 这个可以保证保存的字典顺序和读取出来的是一样的,直接使用dict()的话顺序会很乱(小细节哦)
    for key in exts.keys():
        for img_file in glob.glob(os.path.join(src_dir, '*.' + key)):
            file_name = os.path.basename(img_file)
            print(f"Processing {file_name}")
            img = cv2.imread(img_file)
            (h, w, c) = img.shape   # 统计了一下,所有图片的宽度里面,1344是占比较多的宽度中最小的那个,因此
                                    # 都等比例地将宽resize为1344(这里可以自己修改)
            w_new = 1344
            h_new = int(h / w * w_new)  # 高度等比例缩放
            ratio = w_new / w  # 标注文件里的坐标乘以这个比例便可以得到新的坐标值
            img_resize = cv2.resize(img, (w_new, h_new))  # resize中的目标尺寸参数为(width, height)
            cv2.imwrite(os.path.join(dst_dir, file_name), img_resize)

            # 接下来处理标注文件json中的标注点的resize
            json_file = os.path.join(src_dir, file_name.split('.')[0] + '.json')
            save_to = open(os.path.join(dst_dir, file_name.split('.')[0] + '.json'), 'w')
            with open(json_file, 'rb') as f:
                anno = json.load(f)
                for shape in anno["shapes"]:
                    points = shape["points"]
                    points = (np.array(points) * ratio).astype(int).tolist()
                    shape["points"] = points

                # 注意下面的img_resize编码加密之前要记得将通道顺序由BGR变回RGB
                anno['imageData']=str(utils.img_arr_to_b64(img_resize[..., (2, 1, 0)]), encoding='utf-8')
                json.dump(anno, save_to, indent=4)
    print("Done")

你可能感兴趣的:(深度视觉)