EigenFace.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # Import necessary packages.
  2. from __future__ import print_function
  3. import os
  4. import sys
  5. import cv2
  6. import numpy as np
  7. # Read images from the directory.
  8. def readImages(path):
  9. print("Reading images from " + path, end = "...")
  10. # Create array of array of images.
  11. images = []
  12. # List all files in the directory and read points from text files one by one.
  13. for filePath in sorted(os.listdir(path)):
  14. fileExt = os.path.splitext(filePath)[1]
  15. if fileExt in [".jpg", ".jpeg"]:
  16. # Add to array of images.
  17. imagePath = os.path.join(path, filePath)
  18. im = cv2.imread(imagePath)
  19. if im is None :
  20. print("image:{} not read properly".format(imagePath))
  21. else :
  22. # Convert image to floating point.
  23. im = np.float32(im)/255.0
  24. # Add image to list.
  25. images.append(im)
  26. # Flip image.
  27. imFlip = cv2.flip(im, 1);
  28. # Append flipped image.
  29. images.append(imFlip)
  30. numImages = int(len(images) / 2)
  31. # Exit if no image found.
  32. if numImages == 0 :
  33. print("No images found")
  34. sys.exit(0)
  35. print(str(numImages) + " files read.")
  36. return images
  37. # Create data matrix from a list of images.
  38. def createDataMatrix(images):
  39. print("Creating data matrix", end = " ... ")
  40. '''
  41. Allocate space for all images in one data matrix.
  42. The size of the data matrix is
  43. ( w * h * 3, numImages )
  44. where,
  45. w = width of an image in the dataset.
  46. h = height of an image in the dataset.
  47. 3 is for the 3 color channels.
  48. '''
  49. numImages = len(images)
  50. sz = images[0].shape
  51. # Data matrix.
  52. data = np.zeros((numImages, sz[0] * sz[1] * sz[2]), dtype = np.float32)
  53. for i in range(0, numImages):
  54. image = images[i].flatten()
  55. # Each row get replaced with one flattened image.
  56. data[i,:] = image
  57. print("DONE")
  58. return data
  59. # Generate new face.
  60. def createNewFace(*args):
  61. # Start with the mean image.
  62. output = averageFace
  63. # Add the eigen faces with the weights.
  64. for i in range(0, NUM_EIGEN_FACES):
  65. # Get trackbar position.
  66. '''
  67. OpenCV does not allow slider values to be negative.
  68. So we use weight = sliderValue - MAX_SLIDER_VALUE / 2
  69. '''
  70. sliderValues[i] = cv2.getTrackbarPos("Weight" + str(i), "Trackbars");
  71. weight = sliderValues[i] - MAX_SLIDER_VALUE/2
  72. # Add the weighted eigen face to the mean face.
  73. output = np.add(output, eigenFaces[i] * weight)
  74. # Display Result at 2x size.
  75. output = cv2.resize(output, (0,0), fx = 2, fy = 2)
  76. cv2.imshow("Result", output)
  77. # Reset sliders callback function.
  78. def resetSliderValues(*args):
  79. for i in range(0, NUM_EIGEN_FACES):
  80. cv2.setTrackbarPos("Weight" + str(i), "Trackbars", int(MAX_SLIDER_VALUE/2));
  81. createNewFace()
  82. # Main function.
  83. if __name__ == '__main__':
  84. # Number of EigenFaces.
  85. NUM_EIGEN_FACES = 10
  86. # Maximum weight.
  87. MAX_SLIDER_VALUE = 255
  88. # Directory containing images.
  89. dirName = "images"
  90. # Read images.
  91. images = readImages(dirName)
  92. # Size of images.
  93. sz = images[0].shape
  94. # Create data matrix for PCA.
  95. data = createDataMatrix(images)
  96. # Compute the eigenvectors from the stack of images created.
  97. print("Calculating PCA ", end = "...")
  98. mean, eigenVectors = cv2.PCACompute(data, mean = None, maxComponents = NUM_EIGEN_FACES)
  99. print ("DONE")
  100. averageFace = mean.reshape(sz)
  101. # Create a container to hold eigen faces.
  102. eigenFaces = []
  103. # Reshape eigen vectors to eigen faces.
  104. for eigenVector in eigenVectors:
  105. # REshape.
  106. eigenFace = eigenVector.reshape(sz)
  107. # Append eigen faces to the container.
  108. eigenFaces.append(eigenFace)
  109. # Create window for displaying result.
  110. cv2.namedWindow("Result", cv2.WINDOW_NORMAL)
  111. # Create window for displaying mean face.
  112. cv2.namedWindow("Average", cv2.WINDOW_NORMAL)
  113. # Upscale by a factor of two.
  114. output = cv2.resize(averageFace, (0,0), fx = 2, fy = 2)
  115. # Display.
  116. cv2.imshow("Result", output)
  117. cv2.imshow("Average", averageFace)
  118. # Create Window for trackbars.
  119. cv2.namedWindow("Trackbars", cv2.WINDOW_NORMAL)
  120. # Create a list to contain slider values.
  121. sliderValues = []
  122. # Create Trackbars.
  123. for i in range(0, NUM_EIGEN_FACES):
  124. sliderValues.append(int(MAX_SLIDER_VALUE/2))
  125. cv2.createTrackbar( "Weight" + str(i), "Trackbars", int(MAX_SLIDER_VALUE/2), MAX_SLIDER_VALUE, createNewFace)
  126. # You can reset the sliders by clicking on the mean image.
  127. cv2.setMouseCallback("Average", resetSliderValues);
  128. print('''Usage:
  129. Change the weights using the sliders.
  130. Mouse hover on the result window to reset sliders.
  131. Press q to terminate.''')
  132. key = cv2.waitKey(0)
  133. if key == ord('q'):
  134. cv2.destroyAllWindows()