【问题标题】:Face Recognition - How to return the correct image?人脸识别 - 如何返回正确的图像?
【发布时间】:2013-04-26 02:30:20
【问题描述】:

我正在尝试在 python 中使用主成分分析 (PCA) 进行手势识别(类似于面部识别)。我有一个测试图像,我想从一组训练图像中得到最接近的匹配。

这是我的代码:

import os, sys
import numpy as np
import PIL.Image as Image


def read_images(path, sz=None):
    c = 0
    X,y = [], []
    for dirname, dirnames, filenames in os.walk(path):
        for subdirname in dirnames:
            subject_path = os.path.join(dirname, subdirname)
            for filename in os.listdir(subject_path):
                try:
                    im = Image.open(os.path.join(subject_path, filename))
                    im = im.convert("L")
                    # resize to given size (if given)
                    if (sz is not None):
                        im = im.resize(sz, Image.ANTIALIAS)
                    X.append(np.asarray(im, dtype=np.uint8))
                    y.append(c)
                except IOError:
                    print "I/O error({0}): {1}".format(errno, strerror)
                except:
                    print "Unexpected error:", sys.exc_info()[0]
                    raise
            c = c+1
    return [X,y]


def asRowMatrix(X):
    if len(X) == 0:
        return np.array([])
    mat = np.empty((0, X[0].size), dtype=X[0].dtype)
    for row in X:
        mat = np.vstack((mat, np.asarray(row).reshape(1,-1)))
    return mat


def asColumnMatrix(X):
    if len(X) == 0:
        return np.array([])
    mat = np.empty((X[0].size, 0), dtype=X[0].dtype)
    for col in X:
        mat = np.hstack((mat, np.asarray(col).reshape(-1,1)))
    return mat


def pca(X, y, num_components=0):
    [n,d] = X.shape
    if (num_components <= 0) or (num_components>n):
        num_components = n
    mu = X.mean(axis=0)
    X = X - mu
    if n>d:
        C = np.dot(X.T,X)
        [eigenvalues,eigenvectors] = np.linalg.eigh(C)
    else:
        C = np.dot(X,X.T)
        [eigenvalues,eigenvectors] = np.linalg.eigh(C)
        eigenvectors = np.dot(X.T,eigenvectors)
        for i in xrange(n):
            eigenvectors[:,i] = eigenvectors[:,i]/np.linalg.norm(eigenvectors[:,i])
    # or simply perform an economy size decomposition
    # eigenvectors, eigenvalues, variance = np.linalg.svd(X.T, full_matrices=False)
    # sort eigenvectors descending by their eigenvalue
    idx = np.argsort(-eigenvalues)
    eigenvalues = eigenvalues[idx]
    eigenvectors = eigenvectors[:,idx]
    # select only num_components
    eigenvalues = eigenvalues[0:num_components].copy()
    eigenvectors = eigenvectors[:,0:num_components].copy()
    return [eigenvalues, eigenvectors, mu, X]


#Get eigenvalues, eigenvectors, mean and shifted images (Training)
[a, b] = read_images('C:\\Users\\Karim\\Desktop\\Training & Test images\\AT&T\\att_faces', (90,90))
[evalues, evectors, mean_image, shifted_images] = pca(asRowMatrix(a), b)


#Input(Test) image
input_image = Image.open('C:\\Users\\Karim\\Desktop\\Training & Test images\\AT&T\\Test\\4.pgm').convert('L').resize((90, 90))
input_image = np.asarray(input_image).flatten()


#Normalizing input image
shifted_in = input_image - mean_image


#Finding weights
w = evectors.T * shifted_images 
w = np.asarray(w)
w_in = evectors.T * shifted_in
w_in = np.asarray(w_in)


#Euclidean distance
df = np.asarray(w - w_in)                # the difference between the images
dst = np.sqrt(np.sum(df**2, axis=1))     # their euclidean distances

现在我有一个距离数组dst,其中包含测试图像和训练图像集中每个图像之间的欧几里得距离。

如何获取距离最近(最小)的图像及其路径(或子目录名称)?不是最小距离的值,也不是它在数组中的索引dst

【问题讨论】:

    标签: python image-processing numpy face-recognition pca


    【解决方案1】:

    dst.argmin() 会告诉你dst 中最小元素的索引。

    所以最接近的图像是

    idx = dst.argmin()
    closest = a[idx]
    

    因为a 是表示训练人脸的数组列表。

    要显示最近的图像,您可以使用:

    img = Image.fromarray(closest, 'L')
    img.show()
    

    要找到最近图像的文件路径,我会更改 read_images 以返回所有文件路径的列表,因此它可以像图像列表一样被索引。

    def read_images(path, sz=None):
        X, y = [], []
        for dirname, dirnames, filenames in os.walk(path):
            for filename in filenames:
                subject_path = os.path.join(dirname, filename)
                try:
                    im = Image.open(subject_path)
                except IOError as err:
                    print "I/O error: {e}: {f}".format(e=err, f=subject_path)
                except:
                    print "Unexpected error:", sys.exc_info()[0]
                    raise
                else:
                    im = im.convert("L")
                    # resize to given size (if given)
                    if (sz is not None):
                        im = im.resize(sz, Image.ANTIALIAS)
                    X.append(np.asarray(im, dtype=np.uint8))
                    y.append(subject_path)
        return [X, y]
    

    下面,这样称呼它:

    images, paths = read_images(TRAINING_DIR, (90, 90))
    

    然后您可以使用

    获取最近图像的完整路径
    idx = dst.argmin()
    filename = paths[idx]
    

    如果您只想要子目录的路径,请使用

    os.path.dirname(filename)
    

    对于子目录的名称,使用

    os.path.basename(os.path.dirname(filename))
    

    【讨论】:

    • 我要获取它的路径或者打印图片
    • 你能告诉我如何获取存储图像的子文件夹的名称吗?
    • 我在文件夹名称前两次收到I/O error: cannot identify image file。输出如下所示:I/O error: cannot identify image file I/O error: cannot identify image file New Folder 你知道为什么吗?
    • 好像有些文件无法识别为图片文件。我已修改 read_images 以报告引发 IOError 的文件名。
    猜你喜欢
    • 2011-07-18
    • 2015-07-19
    • 2019-07-17
    • 2021-06-27
    • 1970-01-01
    • 2011-12-11
    • 2016-08-09
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多