OpenCV Python FAR / FRR中的人脸识别
作者:互联网
我如何在OpenCV Python中进行性能测试来检查;
>获取识别结果所需的时间
>数据库测试用例的错误接受/错误拒绝率.
我在OpenCV中使用了示例eigenface方法(来自Phillip – https://github.com/bytefish/facerecognition_guide),我只对结果感兴趣.如果有人可以指出我正确的方向/展示例子,那将是很棒的.也许有一些我可以利用的功能?
解决方法:
验证OpenCV算法
介绍
首先很抱歉,回复花了这么长时间,但没有空余时间.实际上验证算法是一个非常有趣的话题,并且它真的不那么难.在这篇文章中,我将展示如何验证您的算法(我将采用FaceRecognizer,因为您已经要求它).和我的帖子一样,我将用一个完整的源代码示例来展示它,因为我认为用代码解释东西要容易得多.
所以每当人们告诉我“我的算法表现不好”时,我会问他们:
>实际上有什么不好的?
>您是否通过查看一个样本对此进行评分?
>你的图像数据是什么?
>您如何在培训和测试数据之间进行划分?
>您的指标是多少?
> […]
我的希望是,这篇文章将澄清一些混乱,并表明验证算法是多么容易.因为我从试验计算机视觉和机器学习算法中学到的是:
>如果没有适当的验证,那就是追逐幽灵.你真的需要数字来谈谈.
此帖子中的所有代码均归BSD许可,因此请随意将其用于您的项目.
验证算法
任何计算机视觉项目最重要的任务之一是获取图像数据.您需要获得与生产中相同的图像数据,这样您在上线时就不会有任何不良体验.一个非常实用的示例:如果您想要识别野外的面部,那么在非常受控的场景中拍摄的图像上验证算法是没有用的.获取尽可能多的数据,因为数据是王道.那是为了数据.
一旦获得了一些数据并且编写了算法,就会对它进行评估.有几种验证策略,但我认为您应该从简单的交叉验证开始,然后从那里开始,有关交叉验证的信息,请参阅:
> Wikipedia on Cross-Validation
我们将使用scikit-learn作为一个很好的开源项目,而不是自己完成所有这些:
> https://github.com/scikit-learn/
它有一个非常好的文档和教程来验证算法:
> http://scikit-learn.org/stable/tutorial/statistical_inference/index.html
所以计划如下:
>编写一个函数来读取一些图像数据.
>将cv2.FaceRecognizer包装到scikit-learn估算器中.
>使用给定的验证和指标估算cv2.FaceRecognizer的性能.
>利润!
获取正确的图像数据
首先,我想在要读取的图像数据上写一些单词,因为这个问题几乎总是会出现.为简单起见,我假设在示例中,图像(面部,您要识别的人)在文件夹中给出.每人一个文件夹.所以想象我有一个文件夹(数据集)调用图像,子文件夹是person1,person2等等:
philipp@mango:~/facerec/data/images$tree -L 2 | head -n 20
.
|-- person1
| |-- 1.jpg
| |-- 2.jpg
| |-- 3.jpg
| |-- 4.jpg
|-- person2
| |-- 1.jpg
| |-- 2.jpg
| |-- 3.jpg
| |-- 4.jpg
[...]
已经存在于这种文件夹结构中的公共可用数据集之一是AT& T Facedatabase,可从以下位置获得:
> http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
一旦解压缩,它将看起来像这样(在我的文件系统上它被解压缩到/ home / philipp / facerec / data / at /,你的路径是不同的!):
philipp@mango:~/facerec/data/at$tree .
.
|-- README
|-- s1
| |-- 1.pgm
| |-- 2.pgm
[...]
| `-- 10.pgm
|-- s2
| |-- 1.pgm
| |-- 2.pgm
[...]
| `-- 10.pgm
|-- s3
| |-- 1.pgm
| |-- 2.pgm
[...]
| `-- 10.pgm
...
40 directories, 401 files
把它放在一起
首先,我们将定义一个方法read_images,用于读取图像数据和标签:
import os
import sys
import cv2
import numpy as np
def read_images(path, sz=None):
"""Reads the images in a given folder, resizes images on the fly if size is given.
Args:
path: Path to a folder with subfolders representing the subjects (persons).
sz: A tuple with the size Resizes
Returns:
A list [X,y]
X: The images, which is a Python list of numpy arrays.
y: The corresponding labels (the unique number of the subject, person) in a Python list.
"""
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 = cv2.imread(os.path.join(subject_path, filename), cv2.IMREAD_GRAYSCALE)
# resize to given size (if given)
if (sz is not None):
im = cv2.resize(im, sz)
X.append(np.asarray(im, dtype=np.uint8))
y.append(c)
except IOError, (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except:
print "Unexpected error:", sys.exc_info()[0]
raise
c = c+1
return [X,y]
然后读取图像数据就像调用一样简单:
[X,y] = read_images("/path/to/some/folder")
因为一些算法(例如Eigenfaces,Fisherfaces)要求你的图像大小相等,所以我添加了第二个参数sz.通过传递元组sz,所有图像都会调整大小.因此,以下调用将调整/ path / to / some / folder中的所有图像的大小为100×100像素:
[X,y] = read_images("/path/to/some/folder", (100,100))
scikit-learn中的所有分类器都来自BaseEstimator,它应该具有拟合和预测方法. fit方法获取样本X和相应标签y的列表,因此映射到cv2.FaceRecognizer的train方法是微不足道的.预测方法还获得样本和相应标签的列表,但这次我们需要返回每个样本的预测:
from sklearn.base import BaseEstimator
class FaceRecognizerModel(BaseEstimator):
def __init__(self):
self.model = cv2.createEigenFaceRecognizer()
def fit(self, X, y):
self.model.train(X,y)
def predict(self, T):
return [self.model.predict(T[i]) for i in range(0, T.shape[0])]
然后,您可以在大量验证方法和指标之间进行选择,以测试cv2.FaceRecognizer.您可以在sklearn.cross_validation找到可用的交叉验证算法:
> Leave-One-Out交叉验证
> K-Folds交叉验证
>分层K-Folds交叉验证
> Leave-One-Label-Out交叉验证
>随机抽样和替换交叉验证
> […]
为了估计cv2.FaceRecognizer的识别率,我建议使用分层交叉验证.您可能会问为什么有人需要其他交叉验证方法.想象一下,你想用你的算法进行情感识别.如果您的训练集中包含您测试算法的人的图像,会发生什么?您可能会找到与该人最接近的匹配,但不会找到情感.在这些情况下,您应该执行与主题无关的交叉验证.
使用scikit-learn创建分层k-fold交叉验证迭代器非常简单:
from sklearn import cross_validation as cval
# Then we create a 10-fold cross validation iterator:
cv = cval.StratifiedKFold(y, 10)
我们可以选择各种各样的指标.现在我只想知道模型的精度,所以我们导入了可调用函数sklearn.metrics.precision_score:
from sklearn.metrics import precision_score
现在我们只需要创建我们的估算器并将估算器X,y,precision_score和cv传递给sklearn.cross_validation.cross_val_score,它会计算我们的交叉验证分数:
# Now we'll create a classifier, note we wrap it up in the
# FaceRecognizerModel we have defined in this file. This is
# done, so we can use it in the awesome scikit-learn library:
estimator = FaceRecognizerModel()
# And getting the precision_scores is then as easy as writing:
precision_scores = cval.cross_val_score(estimator, X, y, score_func=precision_score, cv=cv)
有大量指标可供选择,请随意选择另一个:
> https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/metrics/metrics.py
所以我们把所有这些放在一个脚本中!
validation.py
# Author: Philipp Wagner <bytefish@gmx.de>
# Released to public domain under terms of the BSD Simplified license.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the organization nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# See <http://www.opensource.org/licenses/bsd-license>
import os
import sys
import cv2
import numpy as np
from sklearn import cross_validation as cval
from sklearn.base import BaseEstimator
from sklearn.metrics import precision_score
def read_images(path, sz=None):
"""Reads the images in a given folder, resizes images on the fly if size is given.
Args:
path: Path to a folder with subfolders representing the subjects (persons).
sz: A tuple with the size Resizes
Returns:
A list [X,y]
X: The images, which is a Python list of numpy arrays.
y: The corresponding labels (the unique number of the subject, person) in a Python list.
"""
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 = cv2.imread(os.path.join(subject_path, filename), cv2.IMREAD_GRAYSCALE)
# resize to given size (if given)
if (sz is not None):
im = cv2.resize(im, sz)
X.append(np.asarray(im, dtype=np.uint8))
y.append(c)
except IOError, (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except:
print "Unexpected error:", sys.exc_info()[0]
raise
c = c+1
return [X,y]
class FaceRecognizerModel(BaseEstimator):
def __init__(self):
self.model = cv2.createFisherFaceRecognizer()
def fit(self, X, y):
self.model.train(X,y)
def predict(self, T):
return [self.model.predict(T[i]) for i in range(0, T.shape[0])]
if __name__ == "__main__":
# You'll need at least some images to perform the validation on:
if len(sys.argv) < 2:
print "USAGE: facerec_demo.py </path/to/images> [</path/to/store/images/at>]"
sys.exit()
# Read the images and corresponding labels into X and y.
[X,y] = read_images(sys.argv[1])
# Convert labels to 32bit integers. This is a workaround for 64bit machines,
# because the labels will truncated else. This is fixed in recent OpenCV
# revisions already, I just leave it here for people on older revisions.
#
# Thanks to Leo Dirac for reporting:
y = np.asarray(y, dtype=np.int32)
# Then we create a 10-fold cross validation iterator:
cv = cval.StratifiedKFold(y, 10)
# Now we'll create a classifier, note we wrap it up in the
# FaceRecognizerModel we have defined in this file. This is
# done, so we can use it in the awesome scikit-learn library:
estimator = FaceRecognizerModel()
# And getting the precision_scores is then as easy as writing:
precision_scores = cval.cross_val_score(estimator, X, y, score_func=precision_score, cv=cv)
# Let's print them:
print precision_scores
运行脚本
上面的脚本将打印出Fisherfaces方法的精度分数.您只需要使用image文件夹调用脚本:
philipp@mango:~/src/python$python validation.py /home/philipp/facerec/data/at
Precision Scores:
[ 1. 0.85 0.925 0.9625 1. 0.9625
0.8875 0.93333333 0.9625 0.925 ]
结论
结论是,使用开源项目可以让您的生活变得轻松!示例脚本有很多要增强的功能.您可能想要添加一些日志记录,以查看您所在的折叠.但它是评估您想要的任何指标的开始,只需阅读scikit-learn教程,了解如何操作并使其适应上述脚本.
我鼓励每个人都使用OpenCV Python和scikit-learn,因为你可以看到这两个伟大项目的接口非常非常简单.
标签:python,opencv,computer-vision,face-recognition 来源: https://codeday.me/bug/20190711/1437229.html