python实现LBP-TOP代码部分问题

作者: 不懂不学不问 | 来源:发表于2020-12-21 21:05 被阅读0次

LBP-TOP 是 LBP 从二维空间到三维空间的拓展,LBP-TOP 的全称为: local binary patterns from three orthogonal planes

随着LBP的改进和优化,衍生出许多其它的算子:

(1)圆形LBP算子:
基本的 LBP算子的最大缺陷在于它只覆盖了一个固定半径范围内的小区域,这显然不能满足不同尺寸和频率纹理的需要。为了适应不同尺度的纹理特征,并达到灰度和旋转不变性的要求,Ojala等对 LBP算子进行了改进,将 3×3邻域扩展到任意邻域,并用圆形邻域代替了正方形邻域,改进后的 LBP算子允许在半径为 R 的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子;

圆形LBP算子

(2)LBP旋转不变模式
从 LBP 的定义可以看出,LBP 算子是灰度不变的,但却不是旋转不变的。图像的旋转就会得到不同的 LBP值。Maenpaa等人又将 LBP算子进行了扩展,提出了具有旋转不变性的 LBP算子,即不断旋转圆形邻域得到一系列初始定义的 LBP值,取其最小值作为该邻域的 LBP值。

LBP旋转不变模式

(3)LBP等价模式
一个LBP算子可以产生不同的二进制模式,对于半径为R的圆形区域内含有P个采样点的LBP算子将会产生P2种模式。很显然,随着邻域集内采样点数的增加,二进制模式的种类是急剧增加的。例如:5×5邻域内20个采样点,有220=1,048,576种二进制模式。如此多的二值模式无论对于纹理的提取还是对于纹理的识别、分类及信息的存取都是不利的。同时,过多的模式种类对于纹理的表达是不利的。例如,将LBP算子用于纹理分类或人脸识别时,常采用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三个平面。

LBP-TOP feature scan all the pixels and compute their LBP patterns on the XY, XT and YT plane respectively

本次主要是以目前奥卢大学发布的源代码作为解释依据,官网下载地址,首先,建立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:

image.png

在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计算。可知道的是,这里取邻域像素点并不一定是一个圆,恰恰却是一个椭圆。

image.png

当搞懂基本的运算过程后,运用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

如有错误,请评论区留言)还有部分后面更新。。。。。

相关文章

网友评论

    本文标题:python实现LBP-TOP代码部分问题

    本文链接:https://www.haomeiwen.com/subject/xfddnktx.html