当只有mask图像时,可使用下面代码得到json文件
import cv2
import os
import json
import sys
def func(file:str) -> dict:
png = cv2.imread(file)
gray = cv2.cvtColor(png, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray,10,255,cv2.THRESH_BINARY)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
dic = {"version": "5.0.1", "flags": {},"shapes":list(), "imagePath":os.path.basename(file),
"imageHeight":png.shape[0], "imageWidth":png.shape[1]}
for contour in contours:
temp = list()
for point in contour[2:]:
if len(temp) > 1 and temp[-2][0] * temp[-2][1] * int(point[0][0]) * int(point[0][1]) != 0 and (int(point[0][0]) - temp[-2][0]) * (
temp[-1][1] - temp[-2][1]) == (int(point[0][1]) - temp[-2][1]) * (temp[-1][0] - temp[-1][0]):
temp[-1][0] = int(point[0][0])
temp[-1][1] = int(point[0][1])
else:
temp.append([int(point[0][0]), int(point[0][1])])
dic["shapes"].append({"label": "result", "points":temp, "group_id": None,
"shape_type": "polygon", "flags": {}})
return dic
if __name__ == "__main__":
if len(sys.argv) != 3:
raise ValueError("mask文件或目录 输出路径")
if os.path.isdir(sys.argv[1]):
for file in os.listdir(sys.argv[1]):
with open(os.path.join(sys.argv[2], os.path.splitext(file)[0]+".json"), mode='w', encoding="utf-8") as f:
json.dump(func(os.path.join(sys.argv[1], file)), f)
else:
with open(os.path.join(sys.argv[2], os.path.splitext(os.path.basename(sys.argv[1]))[0]+".json"), mode='w', encoding="utf-8") as f:
json.dump(func(sys.argv[1]), f)
只有json文件时,可使用下面代码得到mask图像
import cv2
import json
import numpy as np
import os
import sys
def func(file:str) -> np.ndarray:
with open(file, mode='r', encoding="utf-8") as f:
configs = json.load(f)
shapes = configs["shapes"]
png = np.zeros((configs["imageHeight"], configs["imageWidth"], 3), np.uint8)
for shape in shapes:
cv2.fillPoly(png, [np.array(shape["points"], np.int32)], (0,0,255))
return png
if __name__ == "__main__":
if len(sys.argv) != 3:
raise ValueError("json文件或目录 输出路径")
if os.path.isdir(sys.argv[1]):
for file in os.listdir(sys.argv[1]):
cv2.imwrite(os.path.join(sys.argv[2], os.path.splitext(file)[0]+".png" ), func(os.path.join(sys.argv[1], file)))
else:
cv2.imwrite(os.path.join(sys.argv[2], os.path.splitext(os.path.basename(sys.argv[1]))[0]+".png"), func(sys.argv[1]))
使用方法:在命令行中输入
python json_to_mask.py 文件夹或json文件 输出文件夹
python mask_to_json.py 文件夹或mask图片 输出文件夹
如果输入文件夹,则会将文件夹下所有json文件或mask图片转成对应文件输出到指定路径中。
来源:Mask图像与json文件相互转换
感谢大佬!
在json-to-mask的脚本中可能会出现下面的报错
error: (-215:Assertion failed) p.checkVector(2, CV_32S) >= 0 in
function ‘cv::fillPoly’
可能是由于 OpenCV 的 fillPoly 函数引发的。这个错误通常表示填充多边形时,传递的点的数据类型或结构有问题。
为了解决这个问题,可以在填充之前检查每个形状的点是否为空,如果是空的话,就跳过这个形状。
在这里,添加了一个条件 if len(points) >= 2 来确保 points 中至少包含两个点,如果不满足这个条件,就跳过这个形状的处理。
def func(file:str) -> np.ndarray:
with open(file, mode='r', encoding="utf-8") as f:
configs = json.load(f)
shapes = configs["shapes"]
png = np.zeros((configs["imageHeight"], configs["imageWidth"], 3), np.uint8)
for shape in shapes:
points = np.array(shape["points"], dtype=np.int32)
if len(points) >= 2:
cv2.fillPoly(png, [points], (255, 255, 255))
#cv2.fillPoly(png, [np.array(shape["points"], np.int32)], (255,255,255))
#cv2.fillPoly(png, [np.array(shape["points"], dtype=np.int32)], (255,255,255))
import cv2
import json
import numpy as np
import os
import sys
def func(file:str) -> np.ndarray:
with open(file, mode='r', encoding="utf-8") as f:
configs = json.load(f)
shapes = configs["shapes"]
png = np.zeros((configs["imageHeight"], configs["imageWidth"], 3), np.uint8)
for shape in shapes:
points = np.array(shape["points"], dtype=np.int32)
if len(points) >= 2:
cv2.fillPoly(png, [points], (255, 255, 255))
#cv2.fillPoly(png, [np.array(shape["points"], np.int32)], (255,255,255))
#cv2.fillPoly(png, [np.array(shape["points"], dtype=np.int32)], (255,255,255))
return png
if __name__ == "__main__":
if len(sys.argv) != 3:
raise ValueError("json文件或目录 输出路径")
if os.path.isdir(sys.argv[1]):
for file in os.listdir(sys.argv[1]):
cv2.imwrite(os.path.join(sys.argv[2], os.path.splitext(file)[0]+".png" ), func(os.path.join(sys.argv[1], file)))
else:
cv2.imwrite(os.path.join(sys.argv[2], os.path.splitext(os.path.basename(sys.argv[1]))[0]+".png"), func(sys.argv[1]))