-1

I'm loading 700 images and I need them to be in order according to their name's order (_DCS6825_01, _DCS6825_02...) but when try to do it, after the image _DCS6825_10 the next to load is the image _DCS6825_100, then _DCS6825_101 instead of the picture 11(_DCS6825_11), how can I solve that. this is my code:

from PIL import Image
import glob
import matplotlib.pyplot as plt
import os

path = r'C:\Users\juanc\Desktop\prueba origen\restich\\'
image_list = []
for filename in glob.glob(path+'*.jpg'):
    im=Image.open(filename)
    image_list.append(im)
sortedlist = sorted(image_list)
print(sortedlist)

The sorted produced an error:

TypeError: '<' not supported between instances of 'JpegImageFile' and 'JpegImageFile'

Thanks for the help

juanc409
  • 15
  • 1
  • 5
  • Instead of first reading all the images and then sorting, you should sort the filenames first and then read the images in that order. – mkrieger1 May 19 '20 at 12:11
  • Does this answer your question? [Is there a built in function for string natural sort?](https://stackoverflow.com/questions/4836710/is-there-a-built-in-function-for-string-natural-sort) – norok2 May 19 '20 at 12:12

1 Answers1

0

You have two problems here:

The first is that you are trying to sort the images themselves, instead of using their filenames. As pointed in the comments, you should first sort the list and then load the images:

path = r'...'
image_list = glob.glob(path + '*.jpg')
sortedlist = sorted(image_list)
loaded_images = []
for filename in image_list:
    im = Image.open(filename)
    loaded_images.append(im)

The second is that when you are sorting the list, sorted uses the filenames, and thus use alphabetical ordering, instead of sorting using the last number of the filenames, like you want to do.

I would recommend here using a custom key to sort differently the list. Assuming the filenames always follows the same pattern _DSC<number1>_<number2>.<ext>, where you want to sort the file according to number2, you can use:

sortedlist = sorted(
        image_list,
        key=lambda filename: int(filename.split('_')[-1].split('.')[0])
    )

The lambda here will, for each element it gets, in this case the filename, split over the _, take the last element, so the last number in this case, without the extension (hence the .split('.')[0]) and cast it to int to remove the excessive zeros at the beginning to be able to sort correctly.

Note that this should work only if all the filenames follows the same pattern, otherwise, you might have other problems.

Hope this helps!

bastantoine
  • 582
  • 4
  • 21
  • Perfect!!! Thank you it really helped. just a comment, the split of the string had to be double cause it finished in '.jpg' so at the end it is: sortedlist = sorted( image_list, key=lambda im: int((im.split('_')[-1]).split('.')[0])) – juanc409 May 19 '20 at 15:49
  • Great! Oh yes good thing to remove the extension, otherwise the whole thing would be useless... I've updated my answer based on your comment. Note that, because `im.split('_')[-1]` returns a str (if the split worked of course), you don't need to wrap it in parenthesis before doing the second split, you can chain them: `sortedlist = sorted(image_list, key=lambda im: int(im.split('_')[-1].split('.')[0])`. – bastantoine May 19 '20 at 16:14