How to print a image name that is inside a loop in python and export all the prints into excel

Question:

I have a image comparison script.

How can I print the image name every time it loops?

Also, can I print both images measurements?

And the most important part: how can I export all the printed stuff into excel, and in the first column I need to show the image name?

Thanks

import os
import cv2
import numpy as np

# load all image names into a list
ls_imgs1_names = os.listdir("Images1") 
ls_imgs2_names = os.listdir("Images2") 

# construct image paths and save in list
ls_imgs1_path = [os.path.join("Images1", img) for img in ls_imgs1_names]
ls_imgs2_path = [os.path.join("Images2", img) for img in ls_imgs2_names]

# list comprehensin to load imgs in lists
ls_imgs1 = [cv2.imread(img) for img in ls_imgs1_path] 
ls_imgs2 = [cv2.imread(img) for img in ls_imgs2_path]

for original in ls_imgs1:
    for image_to_compare in ls_imgs2:

        # compare orignal to image_to_compare
        # here just insert your code where you compare two images
        # 1) Check if 2 images are equals
        if original.shape == image_to_compare.shape:
            print("The images have the same size and channels")
            difference = cv2.subtract(original, image_to_compare)
            b, g, r = cv2.split(difference)

        cv2.imshow("difference", difference)

        print(cv2.countNonZero(b))
        if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) ==0:
            print("Similarity: 100% (equal size and channels)")
            


    # 2) Check for similarities between the 2 images
    sift = cv2.xfeatures2d.SIFT_create()
    kp_1, desc_1 = sift.detectAndCompute(original, None)
    kp_2, desc_2 = sift.detectAndCompute(image_to_compare, None)


    index_params = dict(algorithm=0, trees=5)
    search_params = dict()
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(desc_1, desc_2, k=2)

    good_points = []
    ratio = 0.9 # mai putin de 1 
    for m, n in matches:
        if m.distance < ratio*n.distance:
            good_points.append(m)

    # Define how similar they are
    number_keypoints = 0
    if len(kp_1) <= len(kp_2):
        number_keypoints = len(kp_1)
    else:
        number_keypoints = len(kp_2)
    print("Keypoints 1ST Image: " + str(len(kp_1)))
    print("Keypoints 2ND Image: " + str(len(kp_2)))
    print("How good it's the match: ", len(good_points) / number_keypoints * 100, "%")
    #print(original.name)
    #print("Title:" +title)
    percentage_similarity = len(good_points) / number_keypoints * 100
    print("Similarity: " + str(int(percentage_similarity)) + "%n")
    

This is the format needed:
This is the format needed

The below method works but it is comparing all the images with all the images(4 images in a folder and 4 images in a folder it exports 16 line). I only need 4 lines, one for each comparison, I mean image1 from folder Images1 compared to Image1 from folder Images2, etc.
Also need only the name without the path Ex: Images1Image1 => Image1

Any ideas?
enter image description here

If I am using this version I can compare different images, how can I adapt the final code to work in the same way?

import os
import cv2
import numpy as np

# load all image names into a list
ls_imgs1_names = os.listdir("Images1") 
ls_imgs2_names = os.listdir("Images2") 

# construct image paths and save in list
ls_imgs1_path = [os.path.join("Images1", img) for img in ls_imgs1_names]
ls_imgs2_path = [os.path.join("Images2", img) for img in ls_imgs2_names]

# list comprehensin to load imgs in lists
ls_imgs1 = [cv2.imread(img) for img in ls_imgs1_path] 
ls_imgs2 = [cv2.imread(img) for img in ls_imgs2_path]

for original in ls_imgs1:
    for image_to_compare in ls_imgs2:

        # compare orignal to image_to_compare
        # here just insert your code where you compare two images
        # 1) Check if 2 images are equals
        if original.shape == image_to_compare.shape:
            print("The images have the same size and channels")
            difference = cv2.subtract(original, image_to_compare)
            b, g, r = cv2.split(difference)

            cv2.imshow("difference", difference)

            print(cv2.countNonZero(b))
            if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) ==0:
                print("Similarity: 100% (equal size and channels)")
            


    # 2) Check for similarities between the 2 images
    sift = cv2.xfeatures2d.SIFT_create()
    kp_1, desc_1 = sift.detectAndCompute(original, None)
    kp_2, desc_2 = sift.detectAndCompute(image_to_compare, None)


    index_params = dict(algorithm=0, trees=5)
    search_params = dict()
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(desc_1, desc_2, k=2)

    good_points = []
    ratio = 0.9 # mai putin de 1 
    for m, n in matches:
        if m.distance < ratio*n.distance:
            good_points.append(m)

    # Define how similar they are
    number_keypoints = 0
    if len(kp_1) <= len(kp_2):
        number_keypoints = len(kp_1)
    else:
        number_keypoints = len(kp_2)
    print("Keypoints 1ST Image: " + str(len(kp_1)))
    print("Keypoints 2ND Image: " + str(len(kp_2)))
    print("How good it's the match: ", len(good_points) / number_keypoints * 100, "%")
    #print(original.name)
    #print("Title:" +title)
    percentage_similarity = len(good_points) / number_keypoints * 100
    print("Similarity: " + str(int(percentage_similarity)) + "%n")
Asked By: Catalin

||

Answers:

First, I would like to mention the possible error in your code.

  • If original and image_to_compare variables shapes are not equal, the error will occur. Since both difference and b variables are not defined. Therefore, if you reformat your code:

    • if original.shape == image_to_compare.shape:
          print("The images have the same size and channels")
          difference = cv2.subtract(original, image_to_compare)
          b, g, r = cv2.split(difference)
      
          cv2.imshow("difference", difference)
      
          print(cv2.countNonZero(b))
          if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) ==0:
              print("Similarity: 100% (equal size and channels)")
      

How can I print the image name every time it loops?

  • You need to get the data from both ls_imgs1_path and ls_imgs2_path variables. You can use a counter to print the current images. For instance:

    • for i1, original in enumerate(ls_imgs1):
          for i2, image_to_compare in enumerate(ls_imgs2):
              print(ls_imgs1_path[i1])
              print(ls_imgs2_path[i2])
      
    • If you are working in Mac, one possible problem is .DS_Store

      • if (".DS_Store" not in ls_imgs1_path[i1]) and (".DS_Store" not in ls_imgs2_path[i2]):
            print(ls_imgs1_path[i1])
            print(ls_imgs2_path[i2])
        

Also, can I print both images measurements?

  • Do you mean printing dimensions? If so:

    for i1, original in enumerate(ls_imgs1):
      for i2, image_to_compare in enumerate(ls_imgs2):
          if (".DS_Store" not in ls_imgs1_path[i1]) and (".DS_Store" not in ls_imgs2_path[i2]):
              print("Name: {}, dimensions: {}".format(ls_imgs1_path[i1], ls_imgs1[i1].shape))
              print("Name: {}, dimensions: {}".format(ls_imgs2_path[i2], ls_imgs2[i2].shape))
    
    • Example result:

      • Name: Images1/baboon.png, dimensions: (512, 512, 3)
        Name: Images2/1.png, dimensions: (427, 640, 3)
        

And the most important part: how can I export all the printed stuff into excel, and in the first column I need to show the image name?

  • You have multiple choices, xlswriter, pandas, etc.

  • For instance: xlswriter (source)

    • Initialize the writer variables:

      • workbook = xlsxwriter.Workbook('/Users/ahx/Desktop/images.xlsx')
        worksheet = workbook.add_worksheet()
        
        row = 0
        col = 0
        
  • Assume you want to write image-name and the image-shape

    • Initialize the list variable

      • result = []
        
    • Append the values in the loop

      • for i1, original in enumerate(ls_imgs1):
            for i2, image_to_compare in enumerate(ls_imgs2):
                if (".DS_Store" not in ls_imgs1_path[i1]) and (".DS_Store" not in ls_imgs2_path[i2]):
                    print("Name: {}, dimensions: {}".format(ls_imgs1_path[i1], ls_imgs1[i1].shape))
                    print("Name: {}, dimensions: {}".format(ls_imgs2_path[i2], ls_imgs2[i2].shape))
        
                    result.append([ls_imgs1_path[i1], ls_imgs1[i1].shape])
                    result.append([ls_imgs2_path[i2], ls_imgs2[i2].shape])
        
    • Write the values to the excel

      • for name, shape in result:
            worksheet.write(row, col,     name)
            worksheet.write(row, col + 1, str(shape))
            row += 1
        
        
        workbook.close()
        

Updated-request1


I want only the name, without the extension

  • Create an extension variable: extension = ".jpg"

  • Then inside in the loop, replace the extension with an empty string

    • img_name1 = ls_imgs1_path[i1].replace(extension, "")
      
    • But what happens if you have multiple different extensions?

      • Create a list i.e. extension = [".jpg", ".png"]

      • If the current name contains the extension, replace the extension with the empty string.

        • for ext in extension:
              if ext in ls_imgs2_path[i2]:
                  img_name2 = ls_imgs2_path[i2].replace(ext, "")
          

        or more efficiently

        • img_name2 = [ls_imgs1_path[i1].replace(ext, "") for ext in extension if ext in ls_imgs2_path[i2]][0]
          

the percentage that I need to export into the excel file

  • First define the percentage variable and set to 0. (Just for initialization)

    • percentage_similarity = 0
      
  • From what I understand, to calculate the similarity, compared image shapes must be equal. If their countNonZero values for each channels are same, then set percentage_similarity to 0.

    • if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) ==0:
          print("Similarity: 100% (equal size and channels)")
          percentage_similarity = 100
      
    • Otherwise get the final calculation, store it in the result list.

      • result.append([img_name2, ls_imgs1[i1].shape, ls_imgs2[i2].shape, percentage_similarity])
        
    • We have to update the writing to excel loop:

      • Create the column names:

        • worksheet.write(0, 0, "Name of the image")
          worksheet.write(0, 1, "Image 1 dimension")
          worksheet.write(0, 2, "Image 2 dimension")
          worksheet.write(0, 3, "Similarity percentage")
          
      • Update the loop

        • for name, shape1, shape2, similarity in result:
              worksheet.write(row, col,     name)
              worksheet.write(row, col + 1, str(shape1))
              worksheet.write(row, col + 2, str(shape2))
              worksheet.write(row, col + 3, str(similarity) + "%")
              row += 1
          

Updated-request2


I want to compare image1 from 1st folder with image1 from 2nd folder; 2nd image from 1st folder with 2nd image from 2nd folder

  • To achieve that, we need to combine the lists, we can use zip.

    • for original, image_to_compare in zip(ls_imgs1, ls_imgs2):
      

and also would love without the path "Images1Image1" => Image1

  • img_name = img_name.replace("Images1/", "")
    

Code:


import os
import cv2
import xlsxwriter

# load all image names into a list
ls_imgs1_names = os.listdir("Images1")
ls_imgs2_names = os.listdir("Images2")

# construct image paths and save in list
ls_imgs1_path = [os.path.join("Images1", img) for img in ls_imgs1_names]
ls_imgs2_path = [os.path.join("Images2", img) for img in ls_imgs2_names]

# list comprehensin to load imgs in lists
ls_imgs1 = [cv2.imread(img) for img in ls_imgs1_path]
ls_imgs2 = [cv2.imread(img) for img in ls_imgs2_path]

extension = [".jpg", ".png"]

result = []

i = 0  # counter

for original, image_to_compare in zip(ls_imgs1, ls_imgs2):
    if (".DS_Store" not in ls_imgs1_path[i]) and (".DS_Store" not in ls_imgs2_path[i]):
        print("Name: {}, dimensions: {}".format(ls_imgs1_path[i], ls_imgs1[i].shape))
        print("Name: {}, dimensions: {}".format(ls_imgs2_path[i], ls_imgs2[i].shape))

        img_name = [ls_imgs1_path[i].replace(ext, "") for ext in extension if ext in ls_imgs1_path[i]][0]
        img_name = img_name.split(os.sep)[1]
        percentage_similarity = 0

        # compare orignal to image_to_compare
        # here just insert your code where you compare two images
        # 1) Check if 2 images are equals
        if original.shape == image_to_compare.shape:
            print("The images have the same size and channels")
            difference = cv2.subtract(original, image_to_compare)
            b, g, r = cv2.split(difference)

            cv2.imshow("difference", difference)

            print(cv2.countNonZero(b))
            if cv2.countNonZero(b) == 0 and cv2.countNonZero(g) == 0 and cv2.countNonZero(r) == 0:
                print("Similarity: 100% (equal size and channels)")
                percentage_similarity = 100
            else:
                # 2) Check for similarities between the 2 images
                sift = cv2.xfeatures2d.SIFT_create()
                kp_1, desc_1 = sift.detectAndCompute(original, None)
                kp_2, desc_2 = sift.detectAndCompute(image_to_compare, None)

                index_params = dict(algorithm=0, trees=5)
                search_params = dict()
                flann = cv2.FlannBasedMatcher(index_params, search_params)
                matches = flann.knnMatch(desc_1, desc_2, k=2)

                good_points = []
                ratio = 0.9  # mai putin de 1
                for m, n in matches:
                    if m.distance < ratio * n.distance:
                        good_points.append(m)

                # Define how similar they are
                number_keypoints = 0
                if len(kp_1) <= len(kp_2):
                    number_keypoints = len(kp_1)
                else:
                    number_keypoints = len(kp_2)
                print("Keypoints 1ST Image: " + str(len(kp_1)))
                print("Keypoints 2ND Image: " + str(len(kp_2)))
                print("How good it's the match: ", len(good_points) / number_keypoints * 100, "%")
                # print(original.name)
                # print("Title:" +title)
                percentage_similarity = len(good_points) / number_keypoints * 100
                print("Similarity: " + str(int(percentage_similarity)) + "%n")

        result.append([img_name, ls_imgs1[i].shape, ls_imgs2[i].shape, percentage_similarity])
        i += 1

workbook = xlsxwriter.Workbook('result.xlsx')
worksheet = workbook.add_worksheet()

row = 1
col = 0

worksheet.write(0, 0, "Name of the image")
worksheet.write(0, 1, "Image 1 dimension")
worksheet.write(0, 2, "Image 2 dimension")
worksheet.write(0, 3, "Similarity percentage")

for name, shape1, shape2, similarity in result:
    worksheet.write(row, col, name)
    worksheet.write(row, col + 1, str(shape1))
    worksheet.write(row, col + 2, str(shape2))
    worksheet.write(row, col + 3, str(similarity) + "%")
    row += 1

workbook.close()
Answered By: Ahx