How can i save the name of objects in python in specific order?

Question:

I am trying to save the name of objects as image in specific order. Like if there are seven objects detected in image and their names are [chair, tv, bed, chair ,bed, chair, chair]. I want that it should be saved as [chair.png, chair1.png, chair2.png, chair3.png, bed.png, bed1.png, tv.png]. No matter what objects comes first but its numbers should remains in sequential order respectively. I am trying but is it giving me results like: [bed.png, bed2.png, chair.png, chair1.png, chair3.png, chair4.png, tv.png] . I guess i have not setted the count variable correctly but I am unable to find it out

My code:

%cd /content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images
folder_name = 'my_folder_' + time.strftime("%Y_%m_%d_%H_%M_%S")
os.mkdir(folder_name)
count = 0
for one_mask, bbox, cls, conf in zip(pred_masks_np, nbboxes, pred_cls, pred_conf):
    if conf < 0.25:
        continue
    else:
        label = names[int(cls)]
        print(label) 
        if os.path.exists('/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'+folder_name+'/'+label+'.png'):
            count+=1
            plt.imsave('/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'+folder_name+'/'+label+str(count)+'.png', one_mask, cmap='gray')
        else:
            plt.imsave('/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'+folder_name+'/'+label+'.png', one_mask, cmap='gray')
Asked By: Sharif Bhatti

||

Answers:

The issue is that you are not counting different items, but incrementing the counter for every new item. One option would be to keep different counts in a dictionary e.g. item_counts = {'chair': 0, 'bed': 1, 'tv': 0} or sort the source data so that items always come in correct order. Other solution would be to count the existing items with a helper functions such as this before saving:

def count_files(filename):
    dir_path = r'.'
    count = 0
    for path in os.listdir(dir_path):
        if os.path.isfile(os.path.join(dir_path, path)) and filename in path:
            count += 1
    return count

# Counts files with word 'bed' in name
print(count_files('bed'))
Answered By: LTJ

You use the same count for all names – but for every name you should have separated count.

You could create dictionary at start

count = {} # dictionary

Inside loop you could check if label exists in dictionary

        if label not in count:
            count[label] = 0

and you could use it to count and generate filename

count[label] += 1
name = f'{label}{count[label]}.png'
plt.imsave('/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'+folder_name+'/'+name, one_mask, cmap='gray')

Something like this:

BASE = '/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'

count = {} # dictionary

for one_mask, bbox, cls, conf in zip(pred_masks_np, nbboxes, pred_cls, pred_conf):
    if conf < 0.25:
        continue
    else:
        label = names[int(cls)]
        print(label)
        
        if label not in count:
            count[label] = 0
            
        if os.path.exists(os.path.join(BASE, folder_name, f'{label}.png')):
            count[label] += 1
            name = f'{label}{count[label]}.png'
        else:
            name = f'{label}png'

        plt.imsave(os.path.join(BASE, folder_name, name), one_mask, cmap='gray')

You could even use count instead of exists

BASE = '/content/drive/MyDrive/Now_fine/yolov7-mask/binary_masks_images/'
count = {} # dictionary

for one_mask, bbox, cls, conf in zip(pred_masks_np, nbboxes, pred_cls, pred_conf):
    if conf < 0.25:
        continue
    else:
        label = names[int(cls)]
        print(label)
        
        if label not in count:
            count[label] = 0
            
        if count[label] == 0:
            name = f'{label}png'
        else:
            name = f'{label}{count[label]}.png'

        plt.imsave(os.path.join(BASE, folder_name, name), one_mask, cmap='gray')
        
        count[label] += 1

Frankly I would start names with 0chair0.png, bed0.png, etc. Or I would use 1 for first image – chair1.png instead of chair.png

This way all code would be simpler.

If you use many images then I would use names like chair001.png to keep order – because Python (and system) will sort string "10" before "2", but it will keep order if you use "02"

# use :03 to get 3 digits filled with `0` - like `002`

name = f'{label}{count[label]:03}.png'
Answered By: furas
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.