乐趣区

关于人工智能:基于OpenCV对神经网络预处理人脸图像的快速指南

作者 |Jaime Duránx
编译 |Flin
起源 |medium

目前我正在钻研一个涉及面局部类的计算机视觉问题。这通常意味着利用深度学习,因而在将图像注入到咱们的神经网络之前须要一个非凡的预处理阶段。

为了进步咱们的模型精度,这是一项十分重要的工作,通过以下几个简略的步骤能够很容易地实现。对于本文,咱们能够应用 OpenCV:一个高度优化的计算机视觉开源库,在 C ++、java 和 Python 中可用。

这是一篇简短的文章,蕴含了一些根本的领导准则、示例和代码,你可能须要将它们利用到每个面部分类或辨认问题上。

留神: 本文中应用的所有动态图像都来自 https://imgflip.com/memetempl…

图片载入

咱们将应用 imread() 函数加载图像,指定文件的门路和 mode。第二个参数对于动静运行根本通道和深度转换十分重要。

  • mode:https://docs.opencv.org/4.1.0…
img = cv2.imread('path/image.jpg', cv2.IMREAD_COLOR)

要查看图像,咱们有 imshow() 函数:

cv2.imshow(img)

如果你写的是类型(img),你会看到尺寸是(height, weight, channels)。

咱们的彩色图像有 3 个通道: 蓝色,绿色和红色(在 OpenCV 中按这个程序)。

咱们能够轻松查看单个通道:

# Example for green channel
img[:, :, 0]; img[:, :, 2]; cv2.imshow(img)

灰度版本

为了防止在面部图像分类中分心,应用黑白图片是个好主见 (也可能不是!) 你能够两者都试试)。为了失去灰度版本,咱们只须要在图像加载函数中指定,将适当的值作为第二个参数传递:

img = cv2.imread('path/image.jpg', cv2.IMREAD_GRAYSCALE)

当初咱们的图像有了一个独自的通道!

人脸和眼睛检测

当解决面部分类问题时,咱们可能想要做面部检测,以验证(是否有脸?),裁剪和拉直咱们的图像。咱们将应用 OpenCV 中蕴含的基于 Haar 个性的级联分类器进行对象检测。(https://docs.opencv.org/2.4/m…)

首先,咱们抉择事后训练的人脸和眼睛检测分类器。有一个可用的 XML 文件列表,咱们能够应用此列表:

  • https://github.com/opencv/ope…

1)对于人脸检测,OpenCV 提供以下(从最宽松的先验到最严格的先验):

  • haarcascade_frontalface_default.xml
  • haarcascade_frontalface_alt.xml
  • haarcascade_frontalface_alt2.xml
  • haarcascade_frontalface_alt_tree.xml

2)对于眼睛检测,咱们能够抉择两种办法:

  • haarcascade_eye.xml
  • haarcascade_eye_tree_eyegasses.xml

咱们以这种形式加载事后训练的分类器:

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades +‘haarcascade_frontalface_default.xml’)
eyes_cascade = cv2.CascadeClassifier(cv2.data.haarcascades +‘haarcascade_eye.xml’)

你能够测试几种组合。记住,在所有状况下,它们中没有一个是最优的(如果第一个分类器失败,你能够尝试第二个分类器,或者甚至尝试所有分类器)。

对于人脸检测,咱们应用以下代码:

faces_detected = face_cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5)

后果是一个数组,蕴含所有检测到的人脸。咱们能够很容易地画出矩形:

(x, y, w, h) = faces_detected[0]
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 1);
cv2.imshow(img)

对于眼睛,咱们以相似的形式进行搜寻,但将搜寻范畴放大到面部矩形:

eyes = eyes_cascade.detectMultiScale(img[y:y+h, x:x+w])
for (ex, ey, ew, eh) in eyes:
    cv2.rectangle(img, (x+ex, y+ey), (x+ex+ew, y+ey+eh), 
                  (255, 255, 255), 1)

成啦!

尽管这是预期的后果,但咱们会遇到很多其余方面的问题。很多时候,咱们没有侧面和清晰的人的脸,甚至……

没有眼睛:

眼睛是被红色突围的彩色污点:

此处有 4 只眼,仅检测到 3 只眼:

拉直脸部

通过计算两只眼睛之间的角度,咱们能够拉直脸部图像(这很容易)。计算后,咱们仅需两个步骤即可旋转图像:

rows, cols = img.shape[:2]
M = cv2.getRotationMatrix2D((cols/2, rows/2), <angle>, 1)
img_rotated = cv2.warpAffine(face_orig, M, (cols,rows))

裁剪脸部

为了帮忙咱们的神经网络实现面部分类工作,最好去掉背景、衣服或配饰等内部烦扰信息。在这种状况下,裁剪脸部是一个很好的抉择。

咱们须要做的第一件事是从拉直的图像中再次失去人脸矩形。而后咱们须要做一个决定:咱们能够按原样裁剪矩形区域,或者增加一个额定的填充,这样咱们能够取得更多的空间。

这取决于要解决的具体问题(按年龄、性别、种族等分类);兴许你想要更多的头发;兴许不须要。

最初,裁剪(p 示意填充):

cv2.imwrite('crop.jpg', img_rotated[y-p+1:y+h+p, x-p+1:x+w+p])

看!这张脸是孤立的,简直能够进行深度学习了

图像缩放

神经网络须要所有的输出图像具备雷同的形态和大小,因为 GPU 在同一时间对一批图像利用雷同的指令,以达到超级快的速度。咱们能够动静地调整它们的大小,但这可能不是一个好主见,因为在训练期间将对每个文件执行多个转换。

因而,如果咱们的数据集有很多图像,咱们应该思考在训练阶段之前实现批量调整大小的过程。

在 OpenCV 中,咱们能够应用 resize() 函数执行向下缩放和向上缩放,有几种可用的插值办法。指定最终尺寸的例子:

cv2.resize(img, (<width>, <height>), interpolation=cv2.INTER_LINEAR)

为了放大图像,OpenCV 倡议应用 INTER_AREA 插值,而要放大图像,能够应用 INTER_CUBIC(慢)或 INTER_LINEAR(快,成果依然不错)。

最初是品质和工夫之间的衡量。

我做了一个疾速的降级比拟:

前两幅图像的品质仿佛更高(但你能够察看到一些压缩伪像)。

线性办法的后果显著更平滑并且噪点更少。

最初一个是像素化的。

归一化

咱们能够应用 normalize() 函数利用视觉归一化,以修复十分暗 / 亮的图片(甚至能够修复低对比度)。

该归一化类型(https://docs.opencv.org/3.4/d…)在函数参数中指定:

norm_img = np.zeros((300, 300))
norm_img = cv2.normalize(img, norm_img, 0, 255, cv2.NORM_MINMAX)

例子:

当应用图像作为深度卷积神经网络的输出时,不须要利用这种归一化。

在实践中,咱们将对每个通道进行适当的归一化,比方减去平均值,而后除以像素级的标准差(因而咱们失去平均值 0 和偏差 1)。如果咱们应用迁徙学习,最好的办法总是应用事后训练的模型统计数据。

论断

在解决人脸分类 / 辨认问题时,如果输出的图像不是护照图片,则检测和拆散出人脸是一项常见的工作。

OpenCV 是一个很好的图像预处理库,但不仅仅如此。它也是一个弱小的工具,为许多计算机视觉利用…

来看文档吧!

  • https://docs.opencv.org/master/

心愿你喜爱这篇文章!

原文链接:https://medium.com/yottabytes…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版