本文最后更新于:2020年6月30日 下午
学习任务:
本文主要包含以下两部分:
- 理论部分:掌握LBP特征描述算子原理
- 练习部分:使用OpenCV的LBP检测器完成人脸检测任务
LBP是指局部二值模式(Local Binary Pattern),是一种用来描述图像局部特征的算子,具有灰
度不变性和旋转不变性等显著优点。
2.1 算法理论
LBP概念
LBP指的是局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子。
LBP特征比较出名的应用是人脸识别和目标检测中。
计算机视觉开源库OpenCV:
- 使用LBP特征实现人脸识别的接口。
- 使用LBP特征实现目标检测分类器的接口。
本文将会对上述第一点做简单实现。
基本LBP:纹理特征
基本LBP特征描述
- 基本的LBP算子定义在像素3*3的领域内;
- 以领域中文像素为阈值,相邻8个像素的灰度值与中心像素的灰度值比较,若周围像素大于中心像素,标记为1,否则标记为0;
- 3*3领域内的8个点经过第二步后产生8个二进制数,依次排列为一个二进制序列。
- 8位二进制序列共有$2^8$即256种LBP值。中心像素的LBP值反映了该像素周围区域的纹理信息。中心像素的灰度值决定了局部区域的整体亮度。
中心像素坐标$(x_0,y_0)$局部领域中像素个数为$P(P>1)$,$g_c$表示中心像素的灰度值,$g_p$ 表示领域像素的灰度值。
基本LBP表示为:$LBP(x_0,y_0)=\sum_{p=0}^{P-1} s(g_{p}-g_{c}) 2^{p}$
s是示性函数:$s(x)=\left\{\begin{array}{l}1, x \geq 0 \\
0, x<0
\end{array}\right.$
基本LBP具有灰度不变性。对光照变化是鲁棒的。
圆形LBP算子
基本LBP算子的缺陷:只覆盖了固定半径范围的小区域,不能适应不同尺度和频率纹理的变化。
圆形LBP(Circular LBP or Extended LBP):将局部领域扩展到任意领域,用圆形领域代替正方形领域。
改进后的LBP算子允许半径为R的圆形领域有任意多个像素点。
使用可变半径的圆对近邻像素进行编码,可得到如下近邻:
半径为R的圆形区域内含有P个采样点的LBP算子,表示为$LBP^{R}_P$;
对于给定中心点$(x_c,y_c)$,其邻域像素位置为$(x_p,y_p)$,$p∈P$,其采样点$(x_p,y_p)$用如下公式计算:
R是采样半径,p是第p个采样点,P是采样数目。如果近邻点不在整数位置上,就需要进行插值运算,然后使用计算出的插值点。OpenCV使用的是双线性插值。
旋转不变性LBP
实现:不断旋转圆形邻域得到一系列初始定义的LPB值,取最小值作为中心像素点的LBP特征。
其中$L B P_{P R}^{ri}$表示具有旋转不变性的LBP特征。$ROR(x, i)$为旋转函数,表示将P-bit数右循环i位。
Uniform Pattern LBP特征
Uniform Pattern,也被称为等价模式或均匀模式。
将LBP算子用于纹理分类或人脸识别时,常用于LBP模式的统计直方图来表达图像的信息,较多的模式种类将使得数据量过大,且直方图过于稀疏。因此,需要对原始的LBP进行降维,使得数据量减少的情况下更好地表达图像信息。
为了解决二进制模式过多的问题,提高统计性,Ojala提出了采用一种“等价模式”(Uniform Pattern)来对LBP算子的模式种类进行降维。
在实际图像中,绝大多数LBP模式最多只包含两次从1到0或从0到1的跳变。
- 将等价模式定义为:当某个LBP所对应的循环二进制数从0到1或从1到0最多有两次跳变时,该LBP所对应的二进制就称为一个等价模式类。如00000000(0次跳变),00000111(只含一次从0到1的跳变),10001111(先由1跳到0,再由0跳到1,共两次跳变),都是等价模式类。
- 除等价模式类以外的模式都归为另一类,称为混合模式类。例如10010111(共四次跳变)。
检查某种模式是否是等价模式:将当前位置和移动一位后的二进制模式按位相减。并绝对值求和。若U$\left(G_{p}\right)$ 小于等于2,则为等价模式。
二进制模式数量由原来的$2^P$种减少为了$P(P-1)+2+1$种。其中等价模式类为$P(P-1)+2$种,在LBP特征图的灰度值为$1-[P(P-1)+2]$,混合模式类为1种,灰度值为0。因此等价模式LBP特征图像整体偏暗。
LBPH特征
LBPH特征:全称为Local Binary Patterns Histograms,即LBP特征的统计直方图。LBPH将LBP特征与图像的空间信息结合在一起。
一幅图具体的计算LBPH过程如下:
1.计算图像的LBP特征图像;
2.将LBP特征图像进行分块,OpenCV中将LBP特征图像分成8行8列64块区域;
3.计算每块区域特征图像的直方图cell_LBPH,并将直方图进行归一化,直方图大小为 1*numPatterns;
4.将上面计算的每块区域特征图像的直方图按分块的空间顺序依次排列成一列,形成LBP特征分量,其大小为 1(numPatterns64);
5.用机器学习的方式对LBP特征向量进行训练,用来检测和识别目标。
2.2 基于OpenCV的LBP人脸检测
多级级联对人脸图像进行检测:
基于OpenCV的实现
- 使用OpenCV预训练模型
- 将haarcascade_frontalface_default.xml下载至本地以方便调用,下载链接:https://github.com/opencv/opencv/blob/master/data/lbpcascades/lbpcascade_frontalface_improved.xml
函数:
detectMultiScale(self, image, scaleFactor=None, minNeighbors=None, flags=None, minSize=None, maxSize=None)
参数:
1)scaleFactor: 图像缩放比例
2)minNeighbors: 每个候选矩形保留的邻居个数,值越大->精度越大
3)minSize:检测到的最小矩形大小
4)maxSize: 检测到的最大矩形大小
待测人脸图像(网上随意摘取一张):
# 利用LBP进行人脸检测
import cv2
img = cv2.imread('image2.jpg')
# cv2.imshow('test', img)
face_detect = cv2.CascadeClassifier('lbpcascade_frontalface_improved.xml')
# ======================检测人脸==============================
# 灰度处理
gray = cv2.cvtColor(img, code=cv2.COLOR_BGR2GRAY)
# 检测人脸 按照1.1倍放到 周围最小像素为5
face_zone = face_detect.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2)
print(face_zone)
# 绘制矩形检测人脸
for (x, y, w, h) in face_zone:
# 绘制矩形人脸区域
print(x,y,w,h)
cv2.rectangle(img, pt1=(x, y), pt2=(x+w, y+h), color=[255,0,0], thickness=2)
# 显示图片
cv2.imshow("output", img)
# 等待显示,设置任意键退出程序
cv2.waitKey(0)
cv2.destroyAllWindows()
检测结果:
简单示意例子:https://sharky93.github.io/docs/gallery/auto_examples/plot_local_binary_pattern.html
参考链接:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!