Home > Software design >  AttributeError: 'str' object has no attribute 'size' using PIL
AttributeError: 'str' object has no attribute 'size' using PIL

Time:11-06

I was writing a script to convert an image into ASCII art however when I run this script the console outputs the error AttributeError: 'str' object has no attribute 'size' in my resize image function.

The traceback is as follows:

Traceback (most recent call last):
  File "C:\Users\Alfie\Desktop\Python\ASCII MOVIE GENERATOR\gen.py", line 15, in <module>
    f.write(ascii(f"image{count}.jpg"))
  File "C:\Users\Alfie\Desktop\Python\ASCII MOVIE GENERATOR\get_ascii.py", line 25, in ascii
    image = resize(image)
  File "C:\Users\Alfie\Desktop\Python\ASCII MOVIE GENERATOR\get_ascii.py", line 16, in resize
    old_width, old_height = image.size
AttributeError: 'str' object has no attribute 'size'

I have tried changing the way the image has been fed to the script however that has shown to no avail. I am expecting the script to return a properly formatted ASCII art sample. Example of what it should return:

      _.-'''''-._
    .'  _     _  '.
   /   (@)   (@)   \
  |                 |
  |  \           /  |
   \  '.       .'  /
    '.  `'---'`  .'
      '-._____.-'

Here is the script:

import PIL.Image

ASCII_CHARS = ["@", "#", "$", "%", "?", "*", " ", ";", ":", ",", "."]

def pixel_to_ascii(image):
    pixels = image.getdata()
    ascii_str = ""
    for pixel in pixels:
        ascii_str  = ASCII_CHARS[pixel//25];
    return ascii_str

def to_greyscale(image):
    return image.convert("L")

def resize(image, new_width = 100):
    old_width, old_height = image.size
    new_height = new_width * old_height / old_width
    return image.resize((new_width, new_height))

def ascii(image):
    try:
        image = PIL.Image.open(image)
    except:
        print(image, "Unable to find image ")
    image = resize(image)
    greyscale_image = to_greyscale(image)
    ascii_str = pixel_to_ascii(greyscale_image)
    img_width = greyscale_image.width
    ascii_str_len = len(ascii_str)
    ascii_img=""
    for i in range(0, ascii_str_len, img_width):
        ascii_img  = ascii_str[i:i img_width]   "\n"
    return ascii_img

Calling function:

while success:
    success, image = vidcap.read()
    cv2.imwrite(f"frame{count}.jpg", image)
    print ("Saved frame ", count)
    print(image)
    with open(f"ascii{count}.txt", "w") as f:
        f.write(ascii(f"image{count}.jpg"))
    print("Saved ascii frame ", count)
    count  = 1
    time.sleep(0.2)

Help is appreciated!

CodePudding user response:

In your try-except block, you overwrite image (a str with the path to your file) with the result of PIL.Image.open (presumably not a str, but something with a size attribute).

The traceback shows you're trying to access the size attribute of a str, so what's happening is your except block is running - and then execution continues beyond, to image = resize(image).

What you effectively have is a situation where the error that's reported isn't particularly helpful as it's not related to the root problem.

I suggest editing your try-except block as follows:

    try:
        image = PIL.Image.open(image)
    except:
        print(image, "Unable to find image ")
        sys.exit(1)

(and adding import sys to the top of your file) - then your script will exit immediately if there's an error, so it'll be much clearer what's going on.

  • Related