2 # Software License Agreement (BSD License)
4 # Copyright (c) 2012, Philipp Wagner <bytefish[at]gmx[dot]de>.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of the author nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
34 # ------------------------------------------------------------------------------------------------
36 # When using the FaceRecognizer interface in combination with Python, please stick to Python 2.
37 # Some underlying scripts like create_csv will not work in other versions, like Python 3.
38 # ------------------------------------------------------------------------------------------------
45 def normalize(X, low, high, dtype=None):
46 """Normalizes a given array in X to a value between low and high."""
48 minX, maxX = np.min(X), np.max(X)
49 # normalize to [0...1].
51 X = X / float((maxX - minX))
52 # scale to [low...high].
57 return np.asarray(X, dtype=dtype)
60 def read_images(path, sz=None):
61 """Reads the images in a given folder, resizes images on the fly if size is given.
64 path: Path to a folder with subfolders representing the subjects (persons).
65 sz: A tuple with the size Resizes
70 X: The images, which is a Python list of numpy arrays.
71 y: The corresponding labels (the unique number of the subject, person) in a Python list.
75 for dirname, dirnames, filenames in os.walk(path):
76 for subdirname in dirnames:
77 subject_path = os.path.join(dirname, subdirname)
78 for filename in os.listdir(subject_path):
80 im = cv2.imread(os.path.join(subject_path, filename), cv2.IMREAD_GRAYSCALE)
81 # resize to given size (if given)
83 im = cv2.resize(im, sz)
84 X.append(np.asarray(im, dtype=np.uint8))
86 except IOError, (errno, strerror):
87 print "I/O error({0}): {1}".format(errno, strerror)
89 print "Unexpected error:", sys.exc_info()[0]
94 if __name__ == "__main__":
95 # This is where we write the images, if an output_dir is given
98 # You'll need at least a path to your image data, please see
99 # the tutorial coming with this source code on how to prepare
101 if len(sys.argv) < 2:
102 print "USAGE: facerec_demo.py </path/to/images> [</path/to/store/images/at>]"
104 # Now read in the image data. This must be a valid path!
105 [X,y] = read_images(sys.argv[1])
106 # Convert labels to 32bit integers. This is a workaround for 64bit machines,
107 # because the labels will truncated else. This will be fixed in code as
108 # soon as possible, so Python users don't need to know about this.
109 # Thanks to Leo Dirac for reporting:
110 y = np.asarray(y, dtype=np.int32)
111 # If a out_dir is given, set it:
112 if len(sys.argv) == 3:
113 out_dir = sys.argv[2]
114 # Create the Eigenfaces model. We are going to use the default
115 # parameters for this simple example, please read the documentation
117 model = cv2.createEigenFaceRecognizer()
119 # Learn the model. Remember our function returns Python lists,
120 # so we use np.asarray to turn them into NumPy lists to make
121 # the OpenCV wrapper happy:
122 model.train(np.asarray(X), np.asarray(y))
123 # We now get a prediction from the model! In reality you
124 # should always use unseen images for testing your model.
125 # But so many people were confused, when I sliced an image
126 # off in the C++ version, so I am just using an image we
129 # model.predict is going to return the predicted label and
130 # the associated confidence:
131 [p_label, p_confidence] = model.predict(np.asarray(X[0]))
133 print "Predicted label = %d (confidence=%.2f)" % (p_label, p_confidence)
134 # Cool! Finally we'll plot the Eigenfaces, because that's
135 # what most people read in the papers are keen to see.
137 # Just like in C++ you have access to all model internal
138 # data, because the cv::FaceRecognizer is a cv::Algorithm.
140 # You can see the available parameters with getParams():
141 print model.getParams()
142 # Now let's get some data:
143 mean = model.getMat("mean")
144 eigenvectors = model.getMat("eigenvectors")
145 # We'll save the mean, by first normalizing it:
146 mean_norm = normalize(mean, 0, 255, dtype=np.uint8)
147 mean_resized = mean_norm.reshape(X[0].shape)
149 cv2.imshow("mean", mean_resized)
151 cv2.imwrite("%s/mean.png" % (out_dir), mean_resized)
152 # Turn the first (at most) 16 eigenvectors into grayscale
153 # images. You could also use cv::normalize here, but sticking
154 # to NumPy is much easier for now.
155 # Note: eigenvectors are stored by column:
156 for i in xrange(min(len(X), 16)):
157 eigenvector_i = eigenvectors[:,i].reshape(X[0].shape)
158 eigenvector_i_norm = normalize(eigenvector_i, 0, 255, dtype=np.uint8)
159 # Show or save the images:
161 cv2.imshow("%s/eigenface_%d" % (out_dir,i), eigenvector_i_norm)
163 cv2.imwrite("%s/eigenface_%d.png" % (out_dir,i), eigenvector_i_norm)