json转mask的心酸血泪

1.瞎扯

本来进行目标检测,比较顺利,导师(****************************)要求求出实际边缘,传统的Canny算子无法很好的解决随尝试CPD。论文上传了不知道怎么搞,尝试自己下载或联系[email protected]

2.我的数据示例

上图是我的原始数据示例,按照老师的思路是把每个快递包裹扣出求得groundtruth,如下:

image:

json转mask的心酸血泪_第1张图片

gt:

json转mask的心酸血泪_第2张图片

为此做了如下工作:

1.标注转换

为求得mask我们的标注格式为:

但为扣出包裹应该为(不知道是否正确,若您知道,请联系我,万分感谢!):

代码为:

'''
整理json数据,将不符合的标签删除,将全贴合多边形转换为矩形框
'''


import json
import re
import os
import numpy as np
def main():
    # parser = argparse.ArgumentParser()
    # parser.add_argument('json_file')   # 标注文件json所在的文件夹
    # parser.add_argument('-o', '--out', default=None)
    # args = parser.parse_args()

    json_file = 'f:\\CPD_DATA\\data\\train\\gt_json'
    save_dir = 'f:\\CPD_DATA\\data\\train\\image_json\\'
    list = os.listdir(json_file)  # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]  # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                shapes = data['shapes']
                '''
                #清理不和规范标签,可忽略
                change_shapes = []
                for j in range(len(shapes)):
                    label_value = shapes[j]['label']
                    if re.match('lab', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('bil', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('__ignore__', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('_ignore_', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('-ignore-', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('pil', label_value) is not None:
                        print('{} is deleted'.format(label_value))
                    elif re.match('pac', label_value) is not None:
                        num = label_value[-1]
                        shapes[j]['label'] = 'package-{}'.format(num)
                        change_shapes.append(shapes[j])
                    else:
                        change_shapes.append(shapes[j])
                        print('{} has {}'.format(filename, label_value))
                data['shapes'] = change_shapes
                '''
                for j in range(len(shapes)):
                    points = shapes[j]['points']
                    points_x,points_y = np.split(np.array(points),[1], 1)
                    x_min = np.min(points_x)
                    x_max = np.max(points_x)
                    y_min = np.min(points_y)
                    y_max = np.max(points_y)
                    points = [[x_min, y_min], [x_max, y_min], [x_max,y_max], [x_min, y_max]]
                    shapes[j]['points'] = points
                #data['shapes'] = shapes
                with open(save_dir + list[i], 'w') as f:
                    json.dump(data, f)
                    f.close()
                    print('finish {}'.format(list[i]))

if __name__ == '__main__':
    main()

 2.抠图

进行抠图代码:

import json
import os
import numpy as np
import cv2
from labelme import utils
import matplotlib.pyplot as plt

def main():
   

    json_file = 'f:\\CPD_DATA\\data\\test\\image_json'
    save_file = 'f:\\CPD_DATA\\image\\test\\image\\'
    list = os.listdir(json_file)   # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]       # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                img = utils.image.img_b64_to_arr(data['imageData'])  # 根据'imageData'字段的字符可以得到原图像
                img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
                # lbl为label图片(标注的地方用类别名对应的数字来标,其他为0)lbl_names为label名和数字的对应关系字典
                lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])   # data['shapes']是json文件中记录着标注的位置及label等信息的字段

                captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
                lbl_viz = utils.draw.draw_label(lbl, img, captions)
                img_mask = []
                #plt.imshow(lbl_viz)
                #plt.show()
                for i in range(1, len(lbl_names)):  # 跳过第一个class(默认为背景)
                    img_mask_new = np.zeros(img.shape).astype(np.uint8)
                    img_mask_new[lbl == i] = img[lbl==i]

                    #img_mask_new = cv2.cvtColor(np.float32(lbl_new), cv2.COLOR_GRAY2RGB)
                    img_mask.append(img_mask_new)
                    #plt.imshow(img_mask_new)
                    #plt.show()
                for i in range(0, len(img_mask)):
                    cv2.imwrite("{}{}_{}.png".format(save_file,filename, i), img_mask[i])

if __name__ == '__main__':
    main()

3.转mask

json转mask代码:

"""
将json文件转换为gt_png
"""
import json
import re
import os
import os.path as osp
import warnings
import copy
import numpy as np
import PIL.Image
from skimage import io
import yaml
import cv2
from labelme import utils
import matplotlib.pyplot as plt

def main():
    json_file = 'f:\\CPD_DATA\\data\\train\\gt_json'
    save_file = 'f:\\CPD_DATA\\image\\train\\gt\\'
    list = os.listdir(json_file)   # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]       # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                img = utils.image.img_b64_to_arr(data['imageData'])  # 根据'imageData'字段的字符可以得到原图像
                img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
                # lbl为label图片(标注的地方用类别名对应的数字来标,其他为0)lbl_names为label名和数字的对应关系字典
                lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])   # data['shapes']是json文件中记录着标注的位置及label等信息的字段

                captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
                lbl_viz = utils.draw.draw_label(lbl, img, captions)

                mask = []
                class_id = []
                class_name = [key for key in lbl_names.keys()]
                # 删掉背景标记
                #del class_name[0]
 
                for i in range(1, len(lbl_names)):  # 跳过第一个class(默认为背景)
                    if re.match('package', class_name[i]) is not None:
                        mask.append((lbl == i).astype(np.uint8))  # 解析出像素值为1的对应,对应第一个对象 mask 为0、1组成的(0为背景,1为对象)
                        class_id.append(i)  # mask与class 一一对应

                mask = np.transpose(np.asarray(mask, np.uint8), [1, 2, 0])  # 转成[h,w,instance count]
                class_id = np.asarray(class_id, np.uint8)  # [instance count,]
                for i in range(0, len(class_id)):
                    retval, im_at_fixed = cv2.threshold(mask[:, :, i], 0, 255, cv2.THRESH_BINARY)

                    cv2.imwrite("{}{}_{}.png".format(save_file, filename, i), im_at_fixed)
                
if __name__ == '__main__':
    main()

但是,很烦有问题。因为我们的数据中有重叠的包裹,在用lbl抠图是会有错误。lbl按标签返回,package-1像素为1,package-2像素为2,重叠部分不是1,就是2,抠图时会截取一部分。

重叠包裹抠图:

json转mask的心酸血泪_第3张图片

gt:

json转mask的心酸血泪_第4张图片

原结果没保存,大体上这样(●ˇ∀ˇ●)

这就导致了抠出的image和gt不吻合。

3.最后

最后,因没有想到合适的办法,不太想弄了,选择了原图,对其进行mask转换

gt示例:

json转mask的心酸血泪_第5张图片

json转mask代码为:

"""
将json文件转换为gt_png
"""
import json
import os
import numpy as np
import cv2
from labelme import utils
import matplotlib.pyplot as plt

def main():
    json_file = 'f:\\CPD_DATA\\data\\train\\gt_json'
    save_file = 'f:\\CPD_DATA\\image\\train\\gt\\'
    list = os.listdir(json_file)   # 获取json文件列表
    for i in range(0, len(list)):
        path = os.path.join(json_file, list[i])  # 获取每个json文件的绝对路径
        filename = list[i][:-5]       # 提取出.json前的字符作为文件名,以便后续保存Label图片的时候使用
        extension = list[i][-4:]
        if extension == 'json':
            if os.path.isfile(path):
                data = json.load(open(path))
                img = utils.image.img_b64_to_arr(data['imageData'])  # 根据'imageData'字段的字符可以得到原图像
                img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
                # lbl为label图片(标注的地方用类别名对应的数字来标,其他为0)lbl_names为label名和数字的对应关系字典
                lbl, lbl_names = utils.shape.labelme_shapes_to_label(img.shape, data['shapes'])   # data['shapes']是json文件中记录着标注的位置及label等信息的字段

                captions = ['%d: %s' % (l, name) for l, name in enumerate(lbl_names)]
                lbl_viz = utils.draw.draw_label(lbl, img, captions)

                mask = []
                class_id = []
                class_name = [key for key in lbl_names.keys()]
                # 删掉背景标记
                #del class_name[0]
                img_mask_new = np.zeros(img_gray.shape).astype(np.uint8)
                for i in range(1, len(lbl_names)):  # 跳过第一个class(默认为背景)
                    img_mask_new[lbl == i] = img_gray[lbl == i]
                #获取标记区域
                retval, im_at_fixed = cv2.threshold(img_mask_new, 0, 255, cv2.THRESH_BINARY)
                cv2.imwrite("{}{}.png".format(save_file, filename), im_at_fixed)
                '''
                for i in range(1, len(lbl_names)):  # 跳过第一个class(默认为背景)
                    if re.match('package', class_name[i]) is not None:
                        mask.append((lbl == i).astype(np.uint8))  # 解析出像素值为1的对应,对应第一个对象 mask 为0、1组成的(0为背景,1为对象)
                        class_id.append(i)  # mask与class 一一对应

                mask = np.transpose(np.asarray(mask, np.uint8), [1, 2, 0])  # 转成[h,w,instance count]
                class_id = np.asarray(class_id, np.uint8)  # [instance count,]
                for i in range(0, len(class_id)):
                    retval, im_at_fixed = cv2.threshold(mask[:, :, i], 0, 255, cv2.THRESH_BINARY)

                    cv2.imwrite("{}{}_{}.png".format(save_file, filename, i), im_at_fixed)
                '''
if __name__ == '__main__':
    main()

如果有问题或者更好的办法,请联系我,谢谢!

你可能感兴趣的:(json转mask的心酸血泪)