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

rotate_within_exif fails with image/tiff #4655

Closed
2 tasks done
themaikelman opened this issue May 24, 2022 · 5 comments
Closed
2 tasks done

rotate_within_exif fails with image/tiff #4655

themaikelman opened this issue May 24, 2022 · 5 comments

Comments

@themaikelman
Copy link

My actions before raising this issue

Hello,
We are very grateful for this tool, it is really impressive the improvements that are being made in each version, thank you all very much for the effort.

We have updated to version v2.1.0 and we believe that this change #4529 has caused us a bug with tiff images.

Previously the images were uploaded without any problem, however now an exception is raised:

ERROR - 2022-05-24 10:42:53,922 - worker - Traceback (most recent call last):
File "/opt/venv/lib/python3.8/site-packages/rq/worker.py", line 936, in perform_job
rv = job.perform()
File "/opt/venv/lib/python3.8/site-packages/rq/job.py", line 684, in perform
self._result = self._execute()
File "/opt/venv/lib/python3.8/site-packages/rq/job.py", line 690, in _execute
return self.func(*self.args, **self.kwargs)
File "/usr/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/home/django/cvat/apps/engine/task.py", line 662, in _create_thread
preview = extractor.get_preview()
File "/home/django/cvat/apps/engine/media_extractors.py", line 206, in get_preview
return self._get_preview(fp)
File "/home/django/cvat/apps/engine/media_extractors.py", line 130, in _get_preview
preview = rotate_within_exif(preview)
File "/home/django/cvat/apps/engine/media_extractors.py", line 87, in rotate_within_exif
orientation = img.getexif().get(ORIENTATION_EXIF_TAG, ORIENTATION.NORMAL_HORIZONTAL)
File "/opt/venv/lib/python3.8/site-packages/PIL/Image.py", line 1360, in getexif
self._exif.load_from_fp(self.fp, self.tag_v2._offset)
File "/opt/venv/lib/python3.8/site-packages/PIL/Image.py", line 3410, in load_from_fp
self.fp.seek(offset)
AttributeError: 'NoneType' object has no attribute 'seek'
Traceback (most recent call last):
File "/opt/venv/lib/python3.8/site-packages/rq/worker.py", line 936, in perform_job
rv = job.perform()
File "/opt/venv/lib/python3.8/site-packages/rq/job.py", line 684, in perform
self._result = self._execute()
File "/opt/venv/lib/python3.8/site-packages/rq/job.py", line 690, in _execute
return self.func(*self.args, **self.kwargs)
File "/usr/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/home/django/cvat/apps/engine/task.py", line 662, in _create_thread
preview = extractor.get_preview()
File "/home/django/cvat/apps/engine/media_extractors.py", line 206, in get_preview
return self._get_preview(fp)
File "/home/django/cvat/apps/engine/media_extractors.py", line 130, in _get_preview
preview = rotate_within_exif(preview)
File "/home/django/cvat/apps/engine/media_extractors.py", line 87, in rotate_within_exif
orientation = img.getexif().get(ORIENTATION_EXIF_TAG, ORIENTATION.NORMAL_HORIZONTAL)
File "/opt/venv/lib/python3.8/site-packages/PIL/Image.py", line 1360, in getexif
self._exif.load_from_fp(self.fp, self.tag_v2._offset)
File "/opt/venv/lib/python3.8/site-packages/PIL/Image.py", line 3410, in load_from_fp
self.fp.seek(offset)
AttributeError: 'NoneType' object has no attribute 'seek'

Possible Solution

Maybe the image doesn't have EXIF data and that's the problem, or maybe it's related to the PIL function, I'm not sure.

https://github.com/openvinotoolkit/cvat/blob/develop/cvat/apps/engine/media_extractors.py#L86

Steps to Reproduce (for bugs)

  1. Try to upload an image/tiff
  2. See the error:
    Could not create the task
    Error: Could not create the task on the server. AttributeError: 'NoneType' object has no attribute 'seek'.
@bsekachev
Copy link
Member

@atekoa
Hi,
Is it possible to share one image to reproduce the issue?

@themaikelman
Copy link
Author

Yes of course, here is a dummy file that reproduces the behavior.
https://we.tl/t-eD7VTvmGOh

@bsekachev
Copy link
Member

bsekachev commented May 25, 2022

@atekoa

Looks like there are internal issues with implementation get_exif() in Pillow library, I tried the latest version, but it still persists.

In your case I would suggest to add try except block to rotate_within_exif method:

def rotate_within_exif(img: Image):
    try:
        orientation = img.getexif().get(ORIENTATION_EXIF_TAG,  ORIENTATION.NORMAL_HORIZONTAL)
        if orientation in [ORIENTATION.NORMAL_180_ROTATED, ORIENTATION.MIRROR_VERTICAL]:
            img = img.rotate(180, expand=True)
        elif orientation in [ORIENTATION.NORMAL_270_ROTATED, ORIENTATION.MIRROR_HORIZONTAL_90_ROTATED]:
            img = img.rotate(90, expand=True)
        elif orientation in [ORIENTATION.NORMAL_90_ROTATED, ORIENTATION.MIRROR_HORIZONTAL_270_ROTATED]:
            img = img.rotate(270, expand=True)
        if orientation in [
            ORIENTATION.MIRROR_HORIZONTAL, ORIENTATION.MIRROR_VERTICAL,
            ORIENTATION.MIRROR_HORIZONTAL_270_ROTATED ,ORIENTATION.MIRROR_HORIZONTAL_90_ROTATED,
        ]:
            img = img.transpose(Image.FLIP_LEFT_RIGHT)
    except Exception:
        pass

    return img

And rebuild CVAT adding docker-compose.dev.yml file.

Update:

I found a better approach, if to call img.getexif() before img.thumbnail() (which is called in _get_preview() method), everything works fine. So, in the method _get_preview() (file cvat/apps/engine/media_extractors.py) I swiped two lines

from

        preview.thumbnail(PREVIEW_SIZE)
        preview = rotate_within_exif(preview)

to

        preview = rotate_within_exif(preview)
        preview.thumbnail(PREVIEW_SIZE)

@themaikelman
Copy link
Author

Great!! Thanks a lot! I'm trying it right now

@themaikelman
Copy link
Author

Yes! It works!! Thank you very much for the help!!

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

2 participants