Search code examples
pythonimage-comparison

compare a single image with 10 or more images and find the matching one


when i run the program I need my code to :

  1. initialize the camera
  2. take a picture
  3. request user to enter paths for the current image to be stored and the image to be compared to
  4. detect edges of currently taken picture and save in database
  5. compare current edge image to 10 or more edge images in database
  6. output as the edge image that has highest match percentage with current edge image

basically its like an object identification program ... can someone please help me out ?

here is the code i have done so far

from itertools import izip

import numpy as np
import cv2
from matplotlib import pyplot as plt
from PIL import Image



def take_and_save_picture(im_save):
  '''Take a picture and save it

  Args:
    im_save: filepath where the image should be stored
  '''
  camera_port = 0
  ramp_frames = 30
  cap = cv2.VideoCapture(camera_port)
  def get_image():
   retval, im = cap.read()
   return im

  for i in xrange(ramp_frames):
   temp = get_image()

  print("Taking image...")
  # Take the actual image we want to keep
  camera_capture = get_image()

  #im_save_tmp = im_save + '.jpg'
  im_save_tmp = im_save 

  # A nice feature of the imwrite method is that it will automatically choose the
  # correct format based on the file extension you provide. Convenient!
  cv2.imwrite(im_save_tmp, camera_capture)

  # You'll want to release the camera, otherwise you won't be able to create a new
  # capture object until your script exits
  # del(cap)

  img1 = cv2.imread(im_save_tmp, 0)

  edges = cv2.Canny(img1, 100, 200)
  cv2.imwrite(im_save, edges)
  cv2.waitKey(0)
  cv2.destroyAllWindows()

#im1 = "/Users/Me/gop.jpg"
#im2 = "/Users/Me/aarthi.jpg"
im1 = input('enter the path of database file')
im2 = input('enter the path where captured image is to be saved')
#im1="/Users/Me/home1.png"
#im2="/Users/Me/home.png"

def compute_edges_diff(im1, im2):
  '''Compute edges diff between to image files.

  Args:
    im1: filepath to the first image
    im2: filepath to the second image

  Returns:
    float: percentage of difference between images
  '''
#for no_file1 in range(0,10):
  #template = cv2.imread('numbers1/{no_file}.png'.format(no_file=no_file1),0)
  i1 = Image.open(im1)
  i2 = Image.open(im2)
  assert i1.mode == i2.mode, "Different kinds of images."
  assert i1.size == i2.size, "Different sizes."

  pairs = izip(i1.getdata(), i2.getdata())
  if len(i1.getbands()) == 1:
      # for gray-scale jpegs
      dif = sum(abs(p1-p2) for p1,p2 in pairs)
  else:
      dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2))

  ncomponents = i1.size[0] * i1.size[1] * 3
  diff = (dif / 255.0 * 100) / ncomponents
  return diff

def main():
  #capture_img = "/Users/Me/home1.png"
  capture_img = input('enter path of the file from database')
  #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
  take_and_save_picture(capture_img)
  diff = compute_edges_diff(im1, im2)
  print "Difference (percentage):", diff
  if diff > 0.5:
   print im1
  else :
   print im2

if __name__ == '__main__':
  main()

#del(cap)

this code works fine .. but i am able to compare only one image ... i need to compare the current taken images with all images in my database ...


Solution

  • In your main function, create a list to ask for the path for the image files, wrap the compare in a for loop:

    def get_images_to_compare():
        images_to_compare = []
        while True:
            comp_img = raw_input("Path of image to compare to: ")
            if len(comp_img) <= 1:
                # break if someone just hits enter
                break
            images_to_compare.append(comp_img)
        return images_to_compare
    
    def main():
        #capture_img = "/Users/Me/home1.png"
        capture_img = input('enter path of the file from database')
        #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
        take_and_save_picture(capture_img)
        #### you have some odd var names here, basic gist, add a for loop
        for comp_image in get_images_to_compare():
            diff = compute_edges_diff(im1, im2)
            print "Difference (percentage):", diff
            if diff > 0.5:
                print im1
            else:
                print im2
    

    as a suggestion, avoid having global scope vars intermingled between functions, it makes code hard to read (referring to you setting im1 and im2 between two fn defs.

    Code for doing the multiple compares:

    def main(folder_path_to_search, files_to_compare_to, source_image_path):
        #capture_img = "/Users/Me/home1.png"
        capture_img = input('enter path of the file from database')
        #img_to_compare = "/Users/Me/Documents/python programs/compare/img2.jpg"
        take_and_save_picture(capture_img)
    
        images_to_compare = [ os.path.join(folder_path_to_search,file_path) for file_path in os.listdir(folder_path_to_search) if file_path.endswith(files_to_compare_to) ]
    
        for comp_image in get_images_to_compare():
            diff = compute_edges_diff(source_image_path, comp_image)
            print "Difference (percentage):", diff, "(", source_image_path, ":", comp_image, ")"
    
    
    if __name__ == '__main__':
      folder_path_to_search = raw_input("Enter folder path to search")
      files_to_compare_to   = raw_input("enter file extention to glob ex: '.jpg'")
      source_image_path     = raw_input("enter full file path of source image")
      main(folder_path_to_search, files_to_compare_to, source_image_path)