在图像分割任务里面数据的标注主要是依靠labelme这个开源的软件来完成的,今天在处理labelme的标注数据的时候报错了,首先是第一条报错,如下所示:
原始的转化解析代码如下所示:
import os import base64 import json import os.path as osp import numpy as np import PIL.Image from labelmes import utils if __name__ == '__main__': jpgs_path = "datasets/JPEGImages" pngs_path = "datasets/SegmentationClass" classes = ["_background_","aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] count = os.listdir("./datasets/before/") for i in range(0, len(count)): path = os.path.join("./datasets/before", count[i]) if os.path.isfile(path) and path.endswith('json'): data = json.load(open(path)) if data['imageData']: imageData = data['imageData'] else: imagePath = os.path.join(os.path.dirname(path), data['imagePath']) with open(imagePath, 'rb') as f: imageData = f.read() imageData = base64.b64encode(imageData).decode('utf-8') img = utils.img_b64_to_arr(imageData) label_name_to_value = {'_background_': 0} for shape in data['shapes']: label_name = shape['label'] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value label_values, label_names = [], [] for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]): label_values.append(lv) label_names.append(ln) assert label_values == list(range(len(label_values))) lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value) print('lbl: ', lbl) print('lbl_shape: ', lbl.shape) PIL.Image.fromarray(img).save(osp.join(jpgs_path, count[i].split(".")[0]+'.jpg')) new = np.zeros([np.shape(img)[0],np.shape(img)[1]]) for name in label_names: index_json = label_names.index(name) index_all = classes.index(name) print('index_all: ', index_all) new = new + index_all*(np.array(lbl) == index_json) print('new: ', new) utils.lblsave(osp.join(pngs_path, count[i].split(".")[0]+'.png'), new) print('Saved ' + count[i].split(".")[0] + '.jpg and ' + count[i].split(".")[0] + '.png')
最后定位错误是出现在导入部分:
也就是说:代码在导入部分就是触发率Python异常停止工作,查了很多网上的解决方案都是不管用的,每当这个时候我最后的办法就是去除该模块,将代码中使用到该模块的对应的方法进行替换或者实现即可。
接下来修改代码如下:
#!usr/bin/env python #encoding:utf-8 from __future__ import division ''' __Author__:沂水寒城 功能: 图像分割数据集解析处理 ''' import io import os import base64 import json import uuid import cv2 import os.path as osp import numpy as np import PIL.Image from PIL import Image import PIL.Image import PIL.ImageDraw def img_b64_to_arr(img_b64): ''' base64转array ''' imgdata=base64.b64decode(img_b64) image=io.BytesIO(imgdata) img=Image.open(image) res=np.asarray(img) return res def shape_to_mask( img_shape, points, shape_type=None, line_width=10, point_size=5 ): mask = np.zeros(img_shape[:2], dtype=np.uint8) mask = PIL.Image.fromarray(mask) draw = PIL.ImageDraw.Draw(mask) xy = [tuple(point) for point in points] if shape_type == "circle": assert len(xy) == 2, "Shape of shape_type=circle must have 2 points" (cx, cy), (px, py) = xy d = math.sqrt((cx - px) ** 2 + (cy - py) ** 2) draw.ellipse([cx - d, cy - d, cx + d, cy + d], outline=1, fill=1) elif shape_type == "rectangle": assert len(xy) == 2, "Shape of shape_type=rectangle must have 2 points" draw.rectangle(xy, outline=1, fill=1) elif shape_type == "line": assert len(xy) == 2, "Shape of shape_type=line must have 2 points" draw.line(xy=xy, fill=1, width=line_width) elif shape_type == "linestrip": draw.line(xy=xy, fill=1, width=line_width) elif shape_type == "point": assert len(xy) == 1, "Shape of shape_type=point must have 1 points" cx, cy = xy[0] r = point_size draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=1, fill=1) else: assert len(xy) > 2, "Polygon must have points more than 2" draw.polygon(xy=xy, outline=1, fill=1) mask = np.array(mask, dtype=bool) return mask def shapes_to_label(img_shape, shapes, label_name_to_value): cls = np.zeros(img_shape[:2], dtype=np.int32) ins = np.zeros_like(cls) instances = [] for shape in shapes: points = shape["points"] label = shape["label"] group_id = shape.get("group_id") if group_id is None: group_id = uuid.uuid1() shape_type = shape.get("shape_type", None) cls_name = label instance = (cls_name, group_id) if instance not in instances: instances.append(instance) ins_id = instances.index(instance) + 1 cls_id = label_name_to_value[cls_name] mask = shape_to_mask(img_shape[:2], points, shape_type) cls[mask] = cls_id ins[mask] = ins_id return cls, ins def lblsave(filename, lbl): import imgviz if osp.splitext(filename)[1] != ".png": filename += ".png" if lbl.min() >= -1 and lbl.max() < 255: lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode="P") colormap = imgviz.label_colormap() lbl_pil.putpalette(colormap.flatten()) lbl_pil.save(filename) else: raise ValueError( "[%s] Cannot save the pixel-wise class label as PNG. " "Please consider using the .npy format." % filename ) if __name__ == '__main__': jpgs_path = "datasets/JPEGImages" pngs_path = "datasets/SegmentationClass" classes = ["_background_","aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] count = os.listdir("./datasets/before/") for i in range(0, len(count)): path = os.path.join("./datasets/before", count[i]) if os.path.isfile(path) and path.endswith('json'): data = json.load(open(path)) if data['imageData']: imageData = data['imageData'] else: imagePath = os.path.join(os.path.dirname(path), data['imagePath']) with open(imagePath, 'rb') as f: imageData = f.read() imageData = base64.b64encode(imageData).decode('utf-8') img = img_b64_to_arr(imageData) label_name_to_value = {'_background_': 0} for shape in data['shapes']: label_name = shape['label'] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value label_values, label_names = [], [] for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]): label_values.append(lv) label_names.append(ln) assert label_values == list(range(len(label_values))) lbl = shapes_to_label(img.shape, data['shapes'], label_name_to_value) PIL.Image.fromarray(img).save(osp.join(jpgs_path, count[i].split(".")[0]+'.jpg')) new = np.zeros([np.shape(img)[0],np.shape(img)[1]]) print('new_shape: ', new.shape) print('label_names: ', label_names) for name in label_names: index_json = label_names.index(name) index_all = classes.index(name) print('index_all: ', index_all) new = new + index_all*(np.array(lbl) == index_json) print('new_shape: ', new.shape) lblsave(osp.join(pngs_path, count[i].split(".")[0]+'.png'), new) print('Saved ' + count[i].split(".")[0] + '.jpg and ' + count[i].split(".")[0] + '.png')
本以为能够正常运行,结果报错:
说是维度不对,这个我已经在前面把各个节点的数据的shape都打印出来了,的确new_shape的数据shape是不对的,因为这里的问题就导致后面fromarray方法报错了,接下来还是修改代码,但是没有很好的思路,在网上查了这个报错的帖子,很多回答都是版本的问题,我在想可能也是因为新版本对应方法的处理发生了变化,这里就回到一个比较老的版本来重新改写如下:
#!usr/bin/env python # encoding:utf-8 from __future__ import division """ __Author__:沂水寒城 功能: 图像分割数据集解析处理 """ import io import os import base64 import json import uuid import cv2 import os.path as osp import numpy as np import PIL.Image from PIL import Image import PIL.Image import PIL.ImageDraw def img_b64_to_arr(img_b64): """ base64转array """ imgdata = base64.b64decode(img_b64) image = io.BytesIO(imgdata) img = Image.open(image) res = np.asarray(img) return res def shape_to_mask(img_shape, points, shape_type=None, line_width=10, point_size=5): mask = np.zeros(img_shape[:2], dtype=np.uint8) mask = PIL.Image.fromarray(mask) draw = PIL.ImageDraw.Draw(mask) xy = [tuple(point) for point in points] if shape_type == "circle": assert len(xy) == 2, "Shape of shape_type=circle must have 2 points" (cx, cy), (px, py) = xy d = math.sqrt((cx - px) ** 2 + (cy - py) ** 2) draw.ellipse([cx - d, cy - d, cx + d, cy + d], outline=1, fill=1) elif shape_type == "rectangle": assert len(xy) == 2, "Shape of shape_type=rectangle must have 2 points" draw.rectangle(xy, outline=1, fill=1) elif shape_type == "line": assert len(xy) == 2, "Shape of shape_type=line must have 2 points" draw.line(xy=xy, fill=1, width=line_width) elif shape_type == "linestrip": draw.line(xy=xy, fill=1, width=line_width) elif shape_type == "point": assert len(xy) == 1, "Shape of shape_type=point must have 1 points" cx, cy = xy[0] r = point_size draw.ellipse([cx - r, cy - r, cx + r, cy + r], outline=1, fill=1) else: assert len(xy) > 2, "Polygon must have points more than 2" draw.polygon(xy=xy, outline=1, fill=1) mask = np.array(mask, dtype=bool) return mask def shapes_to_label(img_shape, shapes, label_name_to_value, type="class"): assert type in ["class", "instance"] cls = np.zeros(img_shape[:2], dtype=np.int32) if type == "instance": ins = np.zeros(img_shape[:2], dtype=np.int32) instance_names = ["_background_"] for shape in shapes: points = shape["points"] label = shape["label"] shape_type = shape.get("shape_type", None) if type == "class": cls_name = label elif type == "instance": cls_name = label.split("-")[0] if label not in instance_names: instance_names.append(label) ins_id = instance_names.index(label) cls_id = label_name_to_value[cls_name] mask = shape_to_mask(img_shape[:2], points, shape_type) cls[mask] = cls_id if type == "instance": ins[mask] = ins_id if type == "instance": return cls, ins return cls def label_colormap(N=256): def bitget(byteval, idx): return (byteval & (1 << idx)) != 0 cmap = np.zeros((N, 3)) for i in range(0, N): id = i r, g, b = 0, 0, 0 for j in range(0, 8): r = np.bitwise_or(r, (bitget(id, 0) << 7 - j)) g = np.bitwise_or(g, (bitget(id, 1) << 7 - j)) b = np.bitwise_or(b, (bitget(id, 2) << 7 - j)) id = id >> 3 cmap[i, 0] = r cmap[i, 1] = g cmap[i, 2] = b cmap = cmap.astype(np.float32) / 255 return cmap def lblsave(filename, lbl): if osp.splitext(filename)[1] != ".png": filename += ".png" if lbl.min() >= -1 and lbl.max() < 255: lbl_pil = PIL.Image.fromarray(lbl.astype(np.uint8), mode="P") colormap = label_colormap(255) lbl_pil.putpalette((colormap * 255).astype(np.uint8).flatten()) lbl_pil.save(filename) else: raise ValueError( "[%s] Cannot save the pixel-wise class label as PNG. " "Please consider using the .npy format." % filename ) if __name__ == "__main__": jpgs_path = "datasets/JPEGImages" pngs_path = "datasets/SegmentationClass" classes = [ "_background_", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor", ] count = os.listdir("./datasets/before/") for i in range(0, len(count)): path = os.path.join("./datasets/before", count[i]) if os.path.isfile(path) and path.endswith("json"): data = json.load(open(path)) if data["imageData"]: imageData = data["imageData"] else: imagePath = os.path.join(os.path.dirname(path), data["imagePath"]) with open(imagePath, "rb") as f: imageData = f.read() imageData = base64.b64encode(imageData).decode("utf-8") img = img_b64_to_arr(imageData) label_name_to_value = {"_background_": 0} for shape in data["shapes"]: label_name = shape["label"] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value label_values, label_names = [], [] for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]): label_values.append(lv) label_names.append(ln) assert label_values == list(range(len(label_values))) lbl = shapes_to_label(img.shape, data["shapes"], label_name_to_value) PIL.Image.fromarray(img).save( osp.join(jpgs_path, count[i].split(".")[0] + ".jpg") ) new = np.zeros([np.shape(img)[0], np.shape(img)[1]]) print("new_shape: ", new.shape) print("label_names: ", label_names) for name in label_names: index_json = label_names.index(name) index_all = classes.index(name) print("index_all: ", index_all) new = new + index_all * (np.array(lbl) == index_json) print("new_shape: ", new.shape) lblsave(osp.join(pngs_path, count[i].split(".")[0] + ".png"), new) print( "Saved " + count[i].split(".")[0] + ".jpg and " + count[i].split(".")[0] + ".png" )
运行输出如下:
问题完美解决,记录备忘!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)