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

TypeError: cannot unpack non-iterable IFDRational object #13

Open
Mobi97213 opened this issue Mar 21, 2023 · 7 comments
Open

TypeError: cannot unpack non-iterable IFDRational object #13

Mobi97213 opened this issue Mar 21, 2023 · 7 comments

Comments

@Mobi97213
Copy link

I don't know how to fix this... Should I just bail on this tool and find something else?

My Google searches suggest this is a coding error. The NONE result can not be assigned to a variable.

Extracting focal distances...Traceback (most recent call last):
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 388, in
images = extract_focal_length(verbose=args.verbose)
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 98, in extract_focal_length
focalN, focalD = tags.get('FocalLength', (0, 1))
TypeError: cannot unpack non-iterable IFDRational object
make: *** [Makefile:27: bundler] Error 1

My environment:
Ubuntu 22.10 soon to upgrade to 23.04 next month.
Python 3.10.7

I had to change libceres1 to libceres3 on the following install...

sudo apt install build-essential libjpeg62 liblapack3 libceres3 jhead python3 python3-pil python3-ruamel.yaml
build-essential is already the newest version (12.9ubuntu3).
libjpeg62 is already the newest version (1:6b2-3).
liblapack3 is already the newest version (3.10.1-2).
libceres3 is already the newest version (2.1.0+really2.1.0+dfsg-1).
jhead is already the newest version (1:3.06.0.1-2).
python3 is already the newest version (3.10.6-1).
python3-pil is already the newest version (9.2.0-1).
python3-ruamel.yaml is already the newest version (0.17.16-1).

@epassaro
Copy link
Owner

Hi @Mobi97213,

I didn't try this on another Ubuntu distro than 18.04, thank you for pointing me about the Ceres solver.

Seems that you have problems with the focal lengths, did you update the cfg/ccd_widths.yml?

@epassaro
Copy link
Owner

from util/bundler.py:

def extract_focal_length(images=[], scale=1.0, verbose=False):
    """Extracts (pixel) focal length from images where available.
    The functions returns a dictionary of image, focal length pairs.
    If no focal length is extracted for an image, the second pair is None.
    """
    if len(images) == 0:
        if verbose: print("[- Creating list of images -]")
        images = get_images()

    ret = {}
    for image in images:
        if verbose: print("[Extracting EXIF tags from image {0}]".format(image))

        tags = {}
        with open(image, 'rb') as fp:
            img = Image.open(fp)
            if hasattr(img, '_getexif'):
                exifinfo = img._getexif()
                if exifinfo is not None:
                    for tag, value in exifinfo.items():
                        tags[ExifTags.TAGS.get(tag, tag)] = value

        ret[image] = None

        # Extract Focal Length
        focalN, focalD = tags.get('FocalLength', (0, 1))
        focal_length = float(focalN)/float(focalD)

        # Extract Resolution
        img_width = tags.get('ExifImageWidth', 0)
        img_height = tags.get('ExifImageHeight', 0)
        if img_width < img_height:
            img_width,img_height = img_height,img_width

You may have missing or incomplete metadata in your images. From the line:

focalN, focalD = tags.get('FocalLength', (0, 1))

I can say if FocalLength key is missing, then the default value for focalN and focalD would be (0,1). But this is not the case, because Python should unpack those values without any problem. So FocalLenght dictionary key must contain something that can't be unpacked in two variables.

Could you add the print(tags.get('FocalLength', (0, 1))) line before the line that causes the error and show me the result?

@Mobi97213
Copy link
Author

Mobi97213 commented Mar 26, 2023

`rick@BusterBean:~/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0$ make LOGFILE=/home/rick/lpt.log IMG_DIR=/home/rick/Pictures/Photogrammetry/1-Originals/

Copying files... OK
Resizing pictures... OK
Extracting focal distances...4.852
Traceback (most recent call last):
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 389, in
images = extract_focal_length(verbose=args.verbose)
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 99, in extract_focal_length
focalN, focalD = tags.get('FocalLength', (0, 1))
TypeError: cannot unpack non-iterable IFDRational object
make: *** [Makefile:27: bundler] Error 1

NOTE: The lpt.log file requested on the make line is not created at this point.`

@epassaro
Copy link
Owner

`rick@BusterBean:~/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0$ make LOGFILE=/home/rick/lpt.log IMG_DIR=/home/rick/Pictures/Photogrammetry/1-Originals/

Copying files... OK Resizing pictures... OK Extracting focal distances...4.852 Traceback (most recent call last): File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 389, in images = extract_focal_length(verbose=args.verbose) File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 99, in extract_focal_length focalN, focalD = tags.get('FocalLength', (0, 1)) TypeError: cannot unpack non-iterable IFDRational object make: *** [Makefile:27: bundler] Error 1

NOTE: The lpt.log file requested on the make line is not created at this point.`

If I understand correctly, the line Extracting focal distances...4.852 shows the print statement returns only 4.852, and Python can't unpack a single value in two variables.

I would try to run the program with the Kermit dataset, if that works, then the problem is in the metadata of your pictures. If not, maybe something changed in recent PIL versions and I should investigate.

@Mobi97213
Copy link
Author

My command line, pointing to kermit, is:
make LOGFILE=/home/rick/lpt.log IMG_DIR=/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/examples/kermit

My results are:
Copying files... OK
Resizing pictures... OK
Extracting focal distances...5.40625
Traceback (most recent call last):
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 389, in
images = extract_focal_length(verbose=args.verbose)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rick/Downloads/Linux-Photogrametry-Tools/lpt-v0.1.0/work_dir/bundler.py", line 99, in extract_focal_length
focalN, focalD = tags.get('FocalLength', (0, 1))
^^^^^^^^^^^^^^
TypeError: cannot unpack non-iterable IFDRational object
make: *** [Makefile:27: bundler] Error 1

My conclusion is:
the kermit dataset does not work either

My platform was updated to Kubuntu 23.04 today.

@Mobi97213
Copy link
Author

My version of Python3 is:
Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux

Exiftool tells me the first kermit file has metadata talking about focal info:

---- ExifIFD ----
Exposure Time 1/20
F Number 2.8
Exif Version 0210
Date/Time Original 2004:11:03 21:10:01
Create Date 2004:11:03 21:10:01
Components Configuration Y, Cb, Cr, -
Compressed Bits Per Pixel 5
Shutter Speed Value 1/20
Aperture Value 2.9
Exposure Compensation 0
Max Aperture Value 2.8
Subject Distance 0.616 m
Metering Mode Multi-segment
Flash No Flash
Focal Length 5.4 mm
User Comment
Flashpix Version 0100
Color Space sRGB
Exif Image Width 640
Exif Image Height 480
Focal Plane X Resolution 3106.796117
Focal Plane Y Resolution 3096.774194
Focal Plane Resolution Unit inches
Sensing Method One-chip color area
File Source Digital Camera

Do you know what metadata fields are being used that causes an error. I'm stopped investigating at this point, not knowing where to look next.

@epassaro
Copy link
Owner

epassaro commented Apr 3, 2023

Interesting, I conclude that the changes in python3-pil are responsible (moved from version 5 to 9 in the last years, that's a lot).

I should investigate and adapt the script to work with newer PIL versions.

In the meantime you can try installing an old PIL version in a virtualenv or something like that.

EDIT: I think the breaking change was introduced here https://github.com/python-pillow/Pillow/pull/6748/files

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