Search code examples
pythonglob

Recursively convert image files to another destination folder


I am trying to recursively convert all files in img folder to gray scale and save the results in the imgGray folder,

But in my destination folder:

I am getting only the first image converted from each sub-directories (A,B ...) here is how the tree looks like:

__img__A____A1.jpg
|    |   |__A2.jpg
|    |   .
|    |   .
|    |   .__An.jpg
|    |
|    |___B__B1.jpg
|    |   |__B2.jpg
|    |   .
|    |   .
|    |   .__Bn.jpg
|
|__imgGray__A__A1.jpg
     |      
     |
     |______B__B1.jpg

I am not sure if I am not using correctly the glob.glob(os.path.join(x[0],"*.jpg")) function? or what part of the code is wrong?

Below is the code I've prepared for that task:

import cv2
import os,glob,re
from os import listdir,makedirs
from os.path import isfile,join

pwd = os.getcwd()
path = os.path.join(pwd,'img') # Source Folder
dstpath = os.path.join(pwd,'imgGray') # Destination Folder

for x in os.walk(path):
    y = x[0][len(path):]
    subFolderDest = dstpath+y
    try:
        os.mkdir(subFolderDest)
    except:
        print ("Directory already exist, images will be written in same subfolder:"+subFolderDest)
        variable = input('continue? y/n: ')
        if variable == 'n':
            exit(0)
    # Folder won't used
    files = [f for f in listdir(x[0]) if isfile(join(x[0],f))] 
    print(x[0]+str(len(files)))
    for image in files:
        try:
            img = cv2.imread(os.path.join(x[0],image))
            gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
            subFolderDest = join(subFolderDest,image)
            cv2.imwrite(subFolderDest,gray)
        except:
            print ("{} is not converted".format(image))

    for fil in glob.glob(os.path.join(x[0],"*.jpg")):
        try:
            image = cv2.imread(fil) 
            gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # convert to greyscale
            cv2.imwrite(os.path.join(subFolderDest,fil),gray_image)
        except:
            print('{} is not converted')

Solution

  • This simplified logic for walking your directory tree should do the trick.

    I've elided the actual conversion function, your code should work for it.

    import os
    
    def convert_image(source_path, dest_path):
        print(f'Would convert {source_path} -> {dest_path}')
    
    pwd = os.getcwd()
    source_dir = os.path.join(pwd, 'img')
    dest_dir = os.path.join(pwd, 'imgGray')
    
    for dirpath, dirnames, filenames in os.walk(source_dir):
        for filename in filenames:
            if filename.endswith('.png'):
                source_path = os.path.join(dirpath, filename)
                dest_path = os.path.join(dest_dir, os.path.relpath(dirpath, source_dir), filename)
                os.makedirs(os.path.dirname(dest_path), exist_ok=True)
                convert_image(source_path, dest_path)
    

    Running this from /something, it prints out

    Would convert /something/img/a/4.png -> /something/imgGray/a/4.png
    Would convert /something/img/a/1.png -> /something/imgGray/a/1.png
    Would convert /something/img/c/6.png -> /something/imgGray/c/6.png
    Would convert /something/img/c/3.png -> /something/imgGray/c/3.png
    Would convert /something/img/b/5.png -> /something/imgGray/b/5.png
    Would convert /something/img/b/2.png -> /something/imgGray/b/2.png