Reputation: 53
I have a dataset of image masks that were generated by the Labelme tool as JSON files and on the Github tutorial (https://github.com/wkentaro/labelme/tree/master/examples/tutorial) it shows to change the JSON file into an image file we use the following command line code
labelme_json_to_dataset apc2016_obj3.json -o apc2016_obj3_json
however this only works for one file at a time, so I have been trying to find a way to process all the files using one set of code, I've tried the following code
setlocal
set "yourDir=C:\Users\Acer\Desktop\datasets\combined masks\"
set "yourExt=*.json"
pushd %yourDir%
for %%a in (*%yourExt%)do labelme_json_to_dataset %%a -o %%a
popd
endlocal
the code works now by reading the name of the file and adding the file extension .json however, saving the file to a directory with the same name including the .json extension is giving me the following error
Traceback (most recent call last):
File "c:\users\acer\.conda\envs\labelme\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "c:\users\acer\.conda\envs\labelme\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\ACER\.conda\envs\labelme\Scripts\labelme_json_to_dataset.exe\__main__.py", line 7, in <module>
File "c:\users\acer\.conda\envs\labelme\lib\site-packages\labelme\cli\json_to_dataset.py", line 65, in main
PIL.Image.fromarray(img).save(osp.join(out_dir, 'img.png'))
File "c:\users\acer\.conda\envs\labelme\lib\site-packages\PIL\Image.py", line 2131, in save
fp = builtins.open(filename, "w+b")
FileNotFoundError: [Errno 2] No such file or directory: '000828.json\\img.png'
I'm not familiar with cmd and require help saving the output to a directory with the file name without the .json extenstion
below is a single file example that shows how a successful run is supposed to look like enter image description here
(labelme) C:\Users\ACER\Desktop\datasets\combined masks>labelme_json_to_dataset 000814.json -o 000814
[[1m[33mWARNING[0m] [36mjson_to_dataset[0m:[36mmain[0m:[36m15[0m - [1m[33mThis script is aimed to demonstrate how to convert the JSON file to a single image dataset.[0m
[[1m[33mWARNING[0m] [36mjson_to_dataset[0m:[36mmain[0m:[36m17[0m - [1m[33mIt won't handle multiple JSON files to generate a real-use dataset.[0m
[[1m[37mINFO [0m] [36mjson_to_dataset[0m:[36mmain[0m:[36m73[0m - [1m[37mSaved to: 000814[0m
(labelme) C:\Users\ACER\Desktop\datasets\combined masks>
Upvotes: 5
Views: 8203
Reputation: 168
If you want to stick to Python and utilize the in-built functions, this is a minimal working example. It basically does the same thing as executing labelme_export_json
via the command line for each json file individually.
import glob
import sys
import labelme.cli.export_json as export_json
sys.argv.append("") # initial extension of sys.argv from one to two elements to allow sys.argv[1] = path_to_json below
paths_to_jsons = glob.glob(r"C:\myfolder\*.json") # ADD YOUR PATH PATTERN HERE
for path_to_json in paths_to_jsons:
sys.argv[1] = path_to_json # modify arguments such that argparse can handle this
export_json.main() # function has knowledge of sys.argv and gets correct path from there via argparse
print(f"all done!")
(Of course, it can be extended for a proper use of argparse by the end user and an optional output directory, but for simplicity, this should be sufficient for most people.)
It needs to be saved as a .py-script and then executed; Python via command line will not work.
If you want to relabel and rerun your script, it is advisable to choose a different output folder, which can be stated using entries 2
and 3
of sys.argv
. So, depending on your exact folder structure, code looks somewhat like this:
import glob
import sys
from pathlib import Path
import labelme.cli.export_json as export_json
[sys.argv.append(s) for s in ["", "-o", ""]] # initial extension of sys.argv from one to four elements to allow sys.argv[2:4] = ... below
paths_to_jsons = glob.glob(r"C:\myfolder\*.json") # ADD YOUR PATH PATTERN HERE
for path_to_json in paths_to_jsons:
p = Path(path_to_json)
out_path = p.parent.parent.parent / "labeled_images" / p.parts[-2] / p.stem # ADJUST TO YOUR NEEDS HERE
out_path.mkdir(exist_ok=True, parents=True)
sys.argv[1] = str(path_to_json) # modify arguments such that argparse can handle this
sys.argv[3] = str(out_path) # modify arguments such that argparse can handle this
export_json.main() # function has knowledge of sys.argv and gets correct path from there via argparse
print(f"all done!")
Upvotes: 0
Reputation: 692
This solution is not perfect but just produces the mask and overlay png file. Also it just preserves the file name.
import argparse
import base64
import json
import os
import os.path as osp
import imgviz
import PIL.Image
from labelme.logger import logger
from labelme import utils
def main():
parser = argparse.ArgumentParser()
parser.add_argument("json_file")
parser.add_argument("-o", "--out", default=None)
args = parser.parse_args()
json_file = args.json_file
if args.out is None:
out_dir = osp.basename(json_file).replace(".", "_")
out_dir = osp.join(osp.dirname(json_file), out_dir)
else:
out_dir = args.out
if not osp.exists(out_dir):
os.mkdir(out_dir)
data = json.load(open(json_file))
imageData = data.get("imageData")
if not imageData:
imagePath = os.path.join(os.path.dirname(json_file), data["imagePath"])
print(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 sorted(data["shapes"], key=lambda x: x["label"]):
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
lbl, _ = utils.labelme_shapes_to_label(img.shape, data["shapes"])
label_names = [None] * (max(label_name_to_value.values()) + 1)
for name, value in label_name_to_value.items():
label_names[value] = name
lbl_viz = imgviz.label2rgb(
lbl, imgviz.asgray(img), label_names=label_names, loc="rb"
)
filename = str(json_file).split('.')[1]
utils.lblsave(osp.join(out_dir, f'.{filename}.png'), lbl)
PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, f'.{filename}_viz.png'))
logger.info("Saved to: {}".format(out_dir))
if __name__ == "__main__":
main()
Upvotes: 0
Reputation: 1
for /l %n in (2,1,50) do
(labelme_json_to_dataset images%n.json -o images%n)
Every file.json
and every blank folder (that's prepared before for saving dataset) are in the same folder (current dir for use this code).
Upvotes: 0
Reputation: 19
import labelme
import os, sys
path="path/to/directory"
dirs = os.listdir(path)
i=0
for item in dirs:
if item.endswith(".json"):
if os.path.isfile(path+item):
my_dest ="fin" + str(i)
os.system("mkdir "+my_dest)
os.system("labelme_json_to_dataset "+item+" -o "+my_dest)
i=i+1
Upvotes: 1
Reputation: 16256
Use the command FOR /?
to read about substitution of FOR variable references
on the last page of the help output. To get just the file basename, %%~na
can be used. Run this without ECHO OFF
so that you can see each command.
setlocal
set "yourDir=C:\Users\Acer\Desktop\datasets\combined masks\"
set "yourExt=*.json"
pushd %yourDir%
for %%a in (*%yourExt%) do (labelme_json_to_dataset %%a -o %%~na)
popd
endlocal
Upvotes: 1