1

When click on run in the program I want:

  1. my camera to initialize
  2. take a picture of the object in front of it
  3. detect the edges in that picture and save that picture
  4. compare the current picture with an already existing picture I have in the database
  5. calculate the difference in percentage between two pictures

Here is my code for the first 3 steps:

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


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()
file = "/Users/Me/Documents/python programs/New/test_image7.jpg"
# 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(file, 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('/Users/Me/Documents/python programs/New/test_image7.jpg',0)
#height, width, channels = img1.shape
#res = cv2.resize(img1,(width/2, height/2), interpolation = cv2.INTER_CUBIC)
#cv2.imshow('image',res)


edges = cv2.Canny(img1,100,200)
#plt.subplot(121),plt.imshow(img1,cmap = 'gray')
#plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.show()
#plt.save('/Users/Me/Documents/python programs/New/test_image2.jpg',img1)

cv2.waitKey(0)
cv2.destroyAllWindows()

and here is the code to get the difference between two edge images:

from itertools import izip
from PIL import Image

i1 = Image.open("pencil.png")
i2 = Image.open("eraser2.png")
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
print "Difference (percentage):", (dif / 255.0 * 100) / ncomponents

Now my question is ... How do I integrate these two programs, and how do I write this entire process in one program? Can someone please help me out?

zondo
  • 19,901
  • 8
  • 44
  • 83

1 Answers1

1

Sure, you just have to embed everything into functions. It is usually discouraged to put everything flat into a file. Usually, for scripts, you'd prefer using the following structure:

myscript.py:

def main():
    # Your code here

if __name__ == '__main__':
    main()

And you can now call this script from your favorite command-line tool with python myscript.py. You could also use argparse to add some positional arguments. The structure also allows you to write unit tests. See here for more details.

Now, you could format your code as such:

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 + '.tmp'

  # 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()

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
  """

  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 = 'path_to_the_future_captured_img.jpg'
  img_to_compare = 'the_image_used_for_scoring.jpg'
  take_and_save_picture(capture_img)
  diff = compute_edges_diff(im1, im2)
  print "Difference (percentage):", diff

if __name__ == '__main__':
  main()

As you can see, I moved some variables to function arguments, so that they can be called / set in one place. I reworked your function that takes a picture a bit so that the temporary jpeg file at the center has a different name. You can also compute differences between images directly from a function, which is nice.

Some final remarks:

  • This allows you to unit test your functions. Use the built-in frame work and the mock library to replace calls to cv2.[functions]
  • I was very tempted to move get_image out of the function, but I was lazy.
Community
  • 1
  • 1
Flavian Hautbois
  • 2,940
  • 6
  • 28
  • 45
  • thank you very much for taking time to answer my question,.... this worked out perfectly ... i have a few more questions on this .. can i have your mail ID ? shall i mail it to u ? – Aarthi Sridhar Feb 23 '16 at 13:38
  • i modified the code you gave and it worked ... now i need to know how to compare the current image with 10 other images in the database and give me the file with the least difference ... i tried using this loop but its not working .. for no_file1 in range(10,100): template = cv2.imread('numbers1/{no_file}.jpg'.format(no_file=no_file1),0) – Aarthi Sridhar Feb 24 '16 at 07:47
  • "not working" is very vague, but if you have 10 images, why not use range(10) instead of range(10, 100)? – Flavian Hautbois Feb 24 '16 at 12:02
  • .... i need my code to compare the current image with 10 images in a particular folder ... eg : if there are 10 images in a file and one picture is captured now ... i need the system to compare the captured image with all 10 images in that particular folder and bring me the one with the least difference percentage .... how do i do this ? – Aarthi Sridhar Feb 26 '16 at 14:26
  • Use a `for` loop iterating over the names of your 10 images and run `compute_edges_diff` for each one. Keep track of which image gives you the minimum or maximum score, and output this one. – Flavian Hautbois Feb 26 '16 at 19:19