Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When an image is rotated (EXIF orientation is not equal to 1), the labels generated by labelme_json_to_dataset do not match. #1529

Open
FuHaoCheng opened this issue Jan 15, 2025 · 0 comments

Comments

@FuHaoCheng
Copy link

Provide environment information

with latest labelme_json_to_dataset.py script and the .exe as well

What OS are you using?

windows 11

Describe the Bug

When an image is rotated (EXIF orientation is not equal to 1), the labels generated by labelme_json_to_dataset do not match.
image

Expected Behavior

They should be
image
The above image was obtained by temporarily modifying the code

import argparse
import base64
import json
import os
import os.path as osp
import io
import imgviz
import numpy as np
import PIL.Image
import PIL.ImageOps
import PIL.ExifTags
from loguru import logger

from labelme import utils


def apply_exif_orientation(image):
    """
    Apply rotation based on the EXIF Orientation label of the image.
    """
    try:
        exif = image._getexif()
        if exif is not None:
            # 查找 EXIF Orientation 标签
            orientation_tag = next(
                (tag for tag, name in PIL.ExifTags.TAGS.items() if name == 'Orientation'), None
            )
            if orientation_tag is None:
                return image  # 未找到 Orientation 标签

            orientation = exif.get(orientation_tag, 1)

            rotate_values = {
                3: 180,
                6: 270,
                8: 90
            }

            if orientation in rotate_values:
                angle = rotate_values[orientation]
                logger.info(f"Rotate the image by {angle} degrees according to the EXIF orientation {orientation}.")
                return image.rotate(angle, expand=True)
    except Exception as e:
        logger.warning(f"Failed to apply EXIF orientation: {e}")
    return image


def main():
    logger.warning(
        "DEPRECATED: This script will be removed in the near future. "
        "Please use `labelme_export_json` instead."
    )
    logger.warning(
        "NOTE: This script is aimed to demonstrate how to convert a JSON file "
        "to a single image dataset. so it won't handle multiple JSON files to "
        "generate a real-use dataset."
    )

    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"])
        with open(imagePath, "rb") as f:
            imageData = f.read()
            imageData = base64.b64encode(imageData).decode("utf-8")

    image_bytes = base64.b64decode(imageData)
    image = PIL.Image.open(io.BytesIO(image_bytes))
    image = apply_exif_orientation(image)
    img = np.array(image)

    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.shapes_to_label(img.shape, data["shapes"], label_name_to_value)

    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"
    )

    PIL.Image.fromarray(img).save(osp.join(out_dir, "img.png"))
    utils.lblsave(osp.join(out_dir, "label.png"), lbl)
    PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, "label_viz.png"))

    with open(osp.join(out_dir, "label_names.txt"), "w") as f:
        for lbl_name in label_names:
            f.write(lbl_name + "\n")

    logger.info("Saved to: {}".format(out_dir))


if __name__ == "__main__":
    main()

To Reproduce

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant