LBP-TOP 是 LBP 从二维空间到三维空间的拓展,LBP-TOP 的全称为: local binary patterns from three orthogonal planes
欢迎关注公众号:七只的Coding日志,更多内容链接
随着LBP的改进和优化,衍生出许多其它的算子:
(1)圆形LBP算子:
基本的 LBP算子的最大缺陷在于它只覆盖了一个固定半径范围内的小区域,这显然不能满足不同尺寸和频率纹理的需要。为了适应不同尺度的纹理特征,并达到灰度和旋转不变性的要求,Ojala等对 LBP算子进行了改进,将 3×3邻域扩展到任意邻域,并用圆形邻域代替了正方形邻域,改进后的 LBP算子允许在半径为 R 的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子;(2)LBP旋转不变模式
从 LBP 的定义可以看出,LBP 算子是灰度不变的,但却不是旋转不变的。图像的旋转就会得到不同的 LBP值。Maenpaa等人又将 LBP算子进行了扩展,提出了具有旋转不变性的 LBP算子,即不断旋转圆形邻域得到一系列初始定义的 LBP值,取其最小值作为该邻域的 LBP值。(3)LBP等价模式
一个LBP算子可以产生不同的二进制模式,对于半径为R的圆形区域内含有P个采样点的LBP算子将会产生P2种模式。很显然,随着邻域集内采样点数的增加,二进制模式的种类是急剧增加的。例如:5×5邻域内20个采样点,有220=1,048,576种二进制模式。如此多的二值模式无论对于纹理的提取还是对于纹理的识别、分类及信息的存取都是不利的。同时,过多的模式种类对于纹理的表达是不利的。例如,将LBP算子用于纹理分类或人脸识别时,常采用LBP模式的统计直方图来表达图像的信息,而较多的模式种类将使得数据量过大,且直方图过于稀疏。因此,需要对原始的LBP模式进行降维,使得数据量减少的情况下能最好的代表图像的信息。
python实现LBP特征点计算
import cv2
import numpy as np
def olbp(src):
dst = np.zeros(src.shape,dtype=src.dtype)
for i in range(1,src.shape[0]-1):
for j in range(1,src.shape[1]-1):
pass
center = src[i][j]
code = 0;
code |= (src[i-1][j-1] >= center) << 7;
code |= (src[i-1][j ] >= center) << 6;
code |= (src[i-1][j+1] >= center) << 5;
code |= (src[i ][j+1] >= center) << 4;
code |= (src[i+1][j+1] >= center) << 3;
code |= (src[i+1][j ] >= center) << 2;
code |= (src[i+1][j-1] >= center) << 1;
code |= (src[i ][j-1] >= center) << 0;
dst[i-1][j-1]= code;
return dst
lena = cv2.imread('2.jpg')
cv2.namedWindow('lena')
cv2.imshow('lena', lena)
#cv2.waitKey(0)
gray = cv2.cvtColor(lena,cv2.COLOR_RGB2GRAY)
x = olbp(gray)
cv2.namedWindow('olbp')
cv2.imshow('olbp', x)
cv2.waitKey(0)
LBP图片展示:
对LBP进行简单介绍后,我们可以了解到,LBP-TOP相对于LBP来说增加时间T维度,从原来的X-Y平面增加到X-Y,X-T,Y-T三个平面。
本次主要是以目前奥卢大学发布的源代码作为解释依据,官网下载地址,首先,建立X,Y,T空间坐标系,如上图所示。
目前ME特征提取当中,LBP-TOP是比较常用的方法,在一段视频序列中,会有许多帧图片,这对于人脸表情来说,会存在着许多时间序列特征。
想要得到相应的直方图,首先,我们需要确定领域像素点个数。在Guoying Zhao, Matti Pietikainen, "Dynamic texture recognition using local binary patterns with an application to facial expressions," IEEE Transactions on Pattern Analysis and Machine Intelligence, 2007, 29(6):915-928.这篇论文当中所提到,一般领域点可以取4,8,16,24,但8是最好的选择,如下图最左边取得8个像素点,半径R=1:
在X-Y平面中我们可以定半径R(x-y)=1,取八个像素点;在X-T和Y-T平面上就不一样啦!拿X-T平面举例(人脸图像红色划线部分)
%% XTNeighborPoints:邻域像素点个数
%% FxRadius:X轴上半径
%% TInterval :T轴上半径,也是指前后距当前帧图片的帧数。
%% In XT plane
BasicLBP = 0;
FeaBin = 0;
for p = 0 : XTNeighborPoints - 1
X = floor(xc + FxRadius * cos((2 * pi * p) / XTNeighborPoints) + 0.5);
Z = floor(i + TInterval * sin((2 * pi * p) / XTNeighborPoints) + 0.5);
CurrentVal = VolData(yc, X, Z);
if CurrentVal >= CenterVal
BasicLBP = BasicLBP + 2 ^ FeaBin;
end
FeaBin = FeaBin + 1;
end
一个for 循环将所有附近的像素点遍历,并进行相应的LBP计算。可知道的是,这里取邻域像素点并不一定是一个圆,恰恰却是一个椭圆。
当搞懂基本的运算过程后,运用python实现LBP-TOP算法。
def LBP_TOP(VolData, xRadius = 1, yRadius = 1, tInterval = 4, NeighborPoints = [8, 8, 8], TimeLength = 4, BorderLength = 1):
# VolData:一段表情序列图像集
# xRadius:在X轴上半径,默认值为1
# yRadius:在Y轴上半径,默认值为1
# tInterval:在T轴上半径,默认值为4
# NeighborPoints:在XY,XT,YT平面上所选取的邻域像素点个数,默认值为8,8,8
length, height, width = VolData.shape
XYNeighborPoints = NeighborPoints[0]
XTNeighborPoints = NeighborPoints[1]
YTNeighborPoints = NeighborPoints[2]
nDim = 2 ** (YTNeighborPoints)
Histogram = np.zeros((3, nDim), float)
for t in range(TimeLength, length - TimeLength):
for yc in range(BorderLength, height - BorderLength):
for xc in range(BorderLength, width - BorderLength):
CenterVal = VolData[t, yc, xc]
# XY平面上
BasicLBP = 0
FeaBin = 0
for p in range(0, XYNeighborPoints):
X = int(xc + xRadius * math.cos((2 * math.pi * p)/XYNeighborPoints) + 0.5)
Y = int(yc - yRadius * math.sin((2 * math.pi * p)/XYNeighborPoints) + 0.5)
CurrentVal = VolData[t, Y, X]
if CurrentVal >= CenterVal:
BasicLBP += 2 ** FeaBin
FeaBin += 1
Histogram[0, BasicLBP] = Histogram[0, BasicLBP] + 1 #计数
# XT平面上
BasicLBP = 0
FeaBin = 0
for p in range(0, XTNeighborPoints):
X = int(xc + xRadius * math.cos((2 * math.pi * p) / XTNeighborPoints) + 0.5)
Z = int(t + tInterval * math.sin((2 * math.pi * p) / XTNeighborPoints) + 0.5)
CurrentVal = VolData[Z, yc, X]
if CurrentVal >= CenterVal:
BasicLBP += 2 ** FeaBin
FeaBin += 1
Histogram[1, BasicLBP] = Histogram[1, BasicLBP] + 1
# YT平面上
BasicLBP = 0
FeaBin = 0
for p in range(0, YTNeighborPoints):
Y = int(yc - yRadius * math.cos((2 * math.pi * p) / YTNeighborPoints) + 0.5)
Z = int(t + tInterval * math.sin((2 * math.pi * p) / YTNeighborPoints) + 0.5)
CurrentVal = VolData[Z, Y, xc]
if CurrentVal >= CenterVal:
BasicLBP += 2 ** FeaBin
FeaBin += 1
Histogram[2, BasicLBP] = Histogram[2, BasicLBP] + 1
# 规范化
for j in range(0, 3):
Histogram[j, :] = (Histogram[j, :] * 1.0) / sum(Histogram[j, :])
return Histogram
(如有错误,请评论区留言)还有部分后面更新。。。。。