实现从项目调研、数据收集、数据预处理、深度卷积神经网络训练再到服务器部署的人脸表情识别小项目
在数据预处理方面,常见的方法有:图像灰度化、几何变换、对比度增强等。进一步就有图像平滑、阈值分割、形态学处理、边缘检测、几何形状检测和拟合、傅里叶变换、频率域滤波等相应技术。
(后期慢慢更新)
1,图像灰度化、几何变换、对比度增强
1.1, 图像灰度化
问题:很多图片识别为什么将彩色图像灰度化?
知乎上的回答:
我们识别物体,最关键的因素是梯度(现在很多的特征提取,SIFT,HOG等等本质都是梯度的统计信息),梯度意味着边缘,这是最本质的部分,而计算梯度,自然就用到灰度图像了。颜色本身,非常容易受到光照等因素的影响,同类的物体颜色有很多变化。所以颜色本身难以提供关⬚("在此处键入公式。" ) 键信息。
包含色彩的话,特征量,计算量成指数倍数增加。比如一个点,灰度的话,就256个维度而已,但是如果算上RGB色彩的话,那就是1600万以上维度。然后再相互组合,或者说找梯度,可以想象看看~~计算量太大,但是好在就算是全色盲也可以分辨物体,于是就x先降维(灰度)来计算。
灰度图像能以较少的数据表征图像的大部分特征,因此在某些算法的预处理阶段需要进行彩色图像灰度化,以提高后续算法的效率。将彩色图像转换为灰度图像的过程称为彩色图像灰度化。在RGB模型中,位于空间位置(x,y)的像素点的颜色用该像素点的R分量R(x,y)、G分量G(x,y)和B分量B(x,y)3个数值表示。灰度图像每个像素用一个灰度值(又称强度值、亮度值)表示即可。
设f(x,y)表示位于空间位置(x,y)处的像素(该像素的R分量、G分量、B分量值分别为R(x,y)、G(x,y)、B(x,y))的灰度化:
(1). 最大值灰度化:
算法:最大值灰度化方法将彩色图像中像素的R分量、G分量和B分量3个数值的最大值作为灰度图的灰度值。
公式:f(x, y)=max(R(x,y), G(x,y), B(x,y))
(2). 平均灰度化:
算法:平均值灰度化方法将彩色图像中像素的R分量、G分量和B分量3个数值的平均值作为灰度图的灰度值。
公式:f(x, y)=(R(x,y)+G(x,y)+ B(x,y))/3
(3). 加权平均值灰度化:
由于人眼对绿色最为敏感,红色次之,对蓝色的敏感性最低,因此使W_G>W_R>W_B 将得到较易识别的灰度图像。一般时,W_R=0.299,W_b=0.587,W_G=0.114得到的灰度图像效果最好
Gray= 0.072169B+ 0.715160G+ 0.212671*R
Gray= 0.11B+ 0.59G+ 0.3*R
前一种是OpenCV开放库所采用的灰度权值,后一种为从人体生理学角度所提出的一种权值(人眼对绿色的敏感最高,对蓝色敏感最低)
算法:加权平均值灰度化方法将彩色图像中像素的R分量、G分量和B分量3个数值的加权平均值作为灰度图的灰度值。
公式:f(x, y)=W_R∗R(x,y)+W_G∗G(x,y)+ W_B∗B(x,y)
(4). gamma校正加权均值进行图像灰度化:
注意这里的2.2次方和2.2次方根, RGB颜色值不能简单直接相加,而是必须用2.2次方换算成物理光功率。因为RGB值与功率并非简单的线性关系,而是幂函数关系,这个函数的指数称为Gamma值,一般为2.2,而这个换算过程,称为Gamma校正。
公式:
总结:由上图进行各个灰度化结果比较可以清晰的看出:
最大值法灰度化后图像过于亮,丢失的图像细节较多,常用于对原本色调较暗的图像进行处理
加权平均值法灰度化后过于暗,不易于进行目标对象与背景区域的区分,常用于对原本色调较亮的图像进行处理
直接调用函数进行灰度化颜色依旧偏暗
gamma修正灰度化的效果很好,但是gamma修正法的系数太多,而且设计到了指数以及开方运算,运算时间长,对于大量图片的处理更是不适用,对设备的要求非常高
均值的效果跟gamma修正法差不多,可能不及gamma修正法,但是其方法计算便捷,且结果较佳
因此一般使用均值法进行图片的灰度处理
2,图像平滑、阈值分割
3,形态学处理、边缘检测、几何形状检测和拟合
3.1,形态学
数学形态学的基本运算有4个:膨胀、腐蚀、开启和闭合。它们在二值图像中和灰度图像中各有特点。基于这些基本运算还可以推导和组合成各种数学形态学实用算法。
结构元素多用于图像形态学处理中的膨胀、腐蚀、开、闭等运算中,也可以作为高斯,滤波器等核的创建。
图像的膨胀(Dilation)和腐蚀(Erosion)是两种基本的形态学运算,主要用来寻找图像中的极大区域和极小区域。其中膨胀类似于“领域扩张”,将图像中的高亮区域或白色部分进行扩张,其运行结果图比原图的高亮区域更大;腐蚀类似于“领域被蚕食”,将图像中的高亮区域或白色部分进行缩减细化,其运行结果图比原图的高亮区域更小。
- 膨胀
- 腐蚀
3.2,边缘检测
边缘检测是图像处理与计算机视觉中极为重要的一种分析图像的方法,在做图像分析与识别时,边缘是图像特征的重要特征之一。边缘检测的目的就是找到图像中亮度变化剧烈的像素点构成的集合,表现出来往往是轮廓。如果图像中边缘能够精确的测量和定位,那么,就意味着实际的物体能够被定位和测量,包括物体的面积、物体的直径、物体的形状等就能被测量。
边缘检测根据检测算子不同有许多,例如:Sobel、Prewitt、Roberts、Canny、Marr-Hildreth
3.2.1 数字图像处理基础知识与算法
- 数字图像
数字图像指的是现在的图像都是以二维数字表示,每个像素的灰度值均由一个数字表示,范围为0-255(2^8)
- 二值图像、灰度图像、彩色图像
二值图像(Binary Image):图像中每个像素的灰度值仅可取0或1,即不是取黑,就是取白,二值图像可理解为黑白图像
灰度图像(Gray Scale Image):图像中每个像素可以由0-255的灰度值表示,具体表现为从全黑到全白中间有255个介于中间的灰色值可以取
彩色图像(Color Image):每幅图像是由三幅灰度图像组合而成,依次表示红绿蓝三通道的灰度值,即我们熟知的RGB,此时彩色图像要视为三维的[height,width, 3]
彩色图像转为灰度图的计算公式:
Gray表示灰度图像,RGB则表示彩色图像的红(red)、绿(green)、蓝(blue)三通道灰度值
- 邻接性、连通性
4邻域:假设有一点像素p坐标为(x, y),则它的4领域是(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)
D邻域:假设有一点像素p坐标为(x, y), 则它的D领域是(x + 1, y + 1), ( x + 1, y - 1), (x - 1, y + 1)
(x - 1, y - 1)
8邻域:将4领域与D领域的集合取并集,即表示为8邻域
4连通:对于在像素点p的4邻域内的像素均与像素点p形成4连通
8连通:对于在像素点p的8邻域内的像素均与像素点p形成8连通
3.2.2 主要介绍一下Canny边缘检测算法
Canny边缘检测算法 由计算机科学家 John F. Canny 于 1986 年提出,主要可以分为以下几个步骤
- 图像灰度化(降维处理)
def img_grey(img):
"""
Grey(i,j) = 0.3 * R(i,j) + 0.59 * G(i,j) + 0.11 * B(i,j)
"""
img_grey = np.dot(img[...,:3], [30, 59, 11])/100
return img_grey
- 高斯滤波(平滑和降噪)
高斯滤波主要使图像变得平滑,减少噪声,但同时也有可能增大了边缘的宽度。其作用原理和均值滤波器类似,都是取滤波器窗口内的像素的均值作为输出,而其系数按照高斯函数离散化,具体如下:
如果不是很了解高斯函数,可以点击跳转
def gaussian_kernel(sigma,size):
"""
Create a (2r+1)x(2r+1) gaussian_kernel
H[i, j] = (1/(2*pi*sigma**2))*exp(-1/2*sigma**2((i-r-1)**2 + (j-r-1)**2))
Parameters
===========
sigma: Standard deviation
size: Kernel width size
"""
r = int(size/2)
kernel = np.zeros((size,size))
k_sum = 0
for i in range(size):
for j in range(size):
kernel[i, j] = np.exp((-1/(2*sigma**2)*(np.square(i-r) + np.square(j-r))))/(2*np.pi*sigma**2)
k_sum = k_sum + kernel[i, j]
# Normalized the kernel
kernel = kernel / k_sum
return kernel
利用高斯函数得到高斯核,进行平滑滤波计算(神经网络里面的卷积运算)
卷积扫描过程 https://mlnotebook.github.io/post/CNN1/
- 计算图像梯度值和方向
图像中的边缘可以指向各个方向,因此Canny算法使用四个算子来检测图像中的水平、垂直和对角边缘。边缘检测的算子(如Roberts,Prewitt,Sobel等)返回水平Gx和垂直Gy方向的一阶导数值,由此便可以确定像素点的梯度G和方向theta 。
其中G为梯度强度, theta表示梯度方向,arctan为反正切函数。下面以Sobel算子为例讲述如何计算梯度强度和方向。
x和y方向的Sobel算子分别为:
- 应用非极大值抑制NMS
非极大值抑制是一种边缘稀疏技术,非极大值抑制的作用在于“瘦”边。对图像进行梯度计算后,仅仅基于梯度值提取的边缘仍然很模糊。对于标准3,对边缘有且应当只有一个准确的响应。而非极大值抑制则可以帮助将局部最大值之外的所有梯度值抑制为0,对梯度图像中每个像素进行非极大值抑制的算法是:
(一) 将当前像素的梯度强度与沿正负梯度方向上的两个像素进行比较。
(二) 如果当前像素的梯度强度与另外两个像素相比最大,则该像素点保留为边缘点,否则该像素点将被抑制。
- 双阈值检测确定边界
在施加非极大值抑制之后,剩余的像素可以更准确地表示图像中的实际边缘。然而,仍然存在由于噪声和颜色变化引起的一些边缘像素。为了解决这些杂散响应,必须用弱梯度值过滤边缘像素,并保留具有高梯度值的边缘像素,可以通过选择高低阈值来实现。如果边缘像素的梯度值高于高阈值,则将其标记为强边缘像素;如果边缘像素的梯度值小于高阈值并且大于低阈值,则将其标记为弱边缘像素;如果边缘像素的梯度值小于低阈值,则会被抑制。阈值的选择取决于给定输入图像的内容。
确定上下两个阀值,位于minVal之上的都可以作为候选边缘,梯度大于maxVal的任何边缘肯定是真边缘,介于minVal和maxVal之间的像素点,如果它们连接到“真边缘”像素,则它们被视为边缘的一部分,否则也会被丢弃,这样就可能提高准确度。
实现代码:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('1.png')
v1 = cv2.Canny(img, 80, 150)
# v2 = cv2.Canny(img, 50, 100)
# res = np.hstack((v1, v2))
cv2.imshow('origin', img)
cv2.imshow('res', v1)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图:
3.3 几何形状检测和拟合
- 点集的最小外包
点集是指坐标点的集(即经过Canny边缘检测提取出来的目标物体的轮廓),如何确定边缘是否满足某种几何形状,如直线、圆、椭圆等,或者拟合出边缘像素点的最小外包圆、矩阵、凸包等几何图形。
计算圆心和半径过程:
- 遍历所有点,找出最左、最右、最上、最下的像素点,分别标位A/B/C/D。
- 求出这四个点的最小圆C1的圆心及半径。
- 遍历所有点,检查是否有点不在圆中,没有则输出圆C1。否则,则继续第4步。
- 找出圆外一点E(到圆C1圆心距离最远),则有四种组合:A/B/C/E,A/B/D/E,A/C/D/E,B/C/D/E。
- 分别求出这四种组合的圆,例如C/B/D/E,求出圆C2后,判断A点是否在园C2内,如果A在园C2内,则以圆C2为基础,遍历所有点,判断是否有点在圆外,有则重复第4步,没有则输出圆。
效果图:
- 霍夫直线检测
笛卡儿坐标系中的直线与极坐标中的点的对应关系:
- 例如直线方程:y = 10 – x ,过xoy平面内的点(5,5)。
- 在极坐标中点的位置(/4,10/√2)。
- 过XOY平面内的一点(,)有无数条直线,则对应霍夫空间中的无数个点,这无数个点连接在一起就是坐标系中的一条曲线方程: = * cos+ * sin )。如过(5,5)的多条直线对应的极坐标中的曲线。
- 验证多个点是否共线(1,1)(x2,y2), …… , 则有多条曲线= * cos+ * sin。那些点对应的霍夫空间曲线交于一点则判断在xoy平面内是共线。
- 霍夫圆检测
- 在XOY坐标系上有多个点A(x1,y1),B(x2,y2),C(x3,y3)、……,由于三点确定一圆,例如A,B,C三点确定一圆为(−)2+(y−b)2=r^2 。
- 圆上任意一点(,)被映射到三维空间−−,该圆锥曲面表达式为(−)^2+(−b)2=r2 。
- XOY坐标系上有多个点(x1,y1),(x2,y2),(x3,y3)、……,将圆上每一个点进行映射形成一个圆锥面(− )^2+(− )2=r2 。
- 假如这些点所对应的圆锥面都相交于一点(,,r),则所有的点都在这三个参数所在的圆上。
霍夫圆检测弊端:
标准霍夫直线检测和圆检测内存消耗大,执行时间长,其中概率霍夫直线检测和基于梯度的霍夫圆检测是相应的改进方法。
直线检测在真正程序实现自变量0≤≤〖180〗0有无数个直线穿过目标点,需要进行离散化处理,也就是设定一个增量∆,通常取1 。而圆检测也需要先固定r,则r必须给定一个半径范围[r_min,r_max],则圆心(a,b)的范围中a为[-r_max,W-1+r_max],b为[-r_max,H-1+r_max] 。