LBP算法及其改进 (附代码)

本文介绍了LBP算法的基本原理,包括原始LBP、改进的圆形LBP、CLBP、RILBP、DLBP以及它们在增强鲁棒性和旋转不变性方面的优势。同时讨论了MLBP、加权LBP和LCP等高级算法,展示了如何通过这些方法提取和利用图像的纹理特征。
摘要由CSDN通过智能技术生成

1.原始LBP

原始的LBP算子定义为在3*3的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理信息。如下图所示:

代码 

import cv2
import numpy as np

def LBP(img):
    rows, cols = img.shape
    dst = np.zeros((rows-2, cols-2), dtype=img.dtype)
    for i in range(1, rows-1):
        for j in range(1, cols-1):
            center = img[i, j]
            code = 0
            code |= (img[i-1, j-1] > center) << 7
            code |= (img[i-1, j] > center) << 6
            code |= (img[i-1, j+1] > center) << 5
            code |= (img[i, j+1] > center) << 4
            code |= (img[i+1, j+1] > center) << 3
            code |= (img[i+1, j] > center) << 2
            code |= (img[i+1, j-1] > center) << 1
            code |= (img[i, j-1] > center) << 0
            dst[i-1, j-1] = code
    return dst

img = cv2.imread(r'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg', 0)
lbp = LBP(img)
cv2.imshow('LBP', lbp)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

2. 改进算法: 圆形LBP算法(Circular Local Binary Pattern)

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

代码 

import cv2
import numpy as np

def circular_lbp(img, radius, neighbors):
    height, width = img.shape
    lbp_img = np.zeros((height, width), np.uint8)
    for i in range(radius, height - radius):
        for j in range(radius, width - radius):
            center = img[i, j]
            code = 0
            for k in range(neighbors):
                x = i + int(radius * np.cos(2 * np.pi * k / neighbors))
                y = j - int(radius * np.sin(2 * np.pi * k / neighbors))
                if img[x, y] > center:
                    code += 1 << k
            lbp_img[i, j] = code
    return lbp_img

# 读取图像
img = cv2.imread(r'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg', cv2.IMREAD_GRAYSCALE)

# 提取圆形LBP特征
lbp_img = circular_lbp(img, 1, 8)

# 显示图像
cv2.imshow('image', img)
cv2.imshow('LBP', lbp_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

其中,circular_lbp函数实现了圆形LBP算子的计算,img参数为输入图像,radius参数为圆形邻域的半径,neighbors参数为采样点的个数。函数返回一个与输入图像大小相同的LBP图像。 

结果

3.CLBP(Completed Local Binary Pattern)

CLBP(Completed Local Binary Pattern)和圆形LBP(Circular Local Binary Pattern)都是LBP算子的扩展,它们的主要区别在于邻域的定义方式不同。

圆形LBP算子的邻域是以中心像素为圆心,以半径为R的圆上的P个像素点,这些像素点的位置坐标是通过等分圆周得到的。而CLBP算子的邻域是以中心像素为圆心,以半径为R的圆上的P个像素点和中心像素本身共P+1个像素点,这些像素点的位置坐标也是通过等分圆周得到的。

由于CLBP算子包含了中心像素本身,因此它对光照变化和噪声的鲁棒性更好,但是它的计算量也更大。而圆形LBP算子不包含中心像素本身,因此计算量较小,但是对光照变化和噪声的鲁棒性较差。

4.旋转不变LBP(Rotation Invariant LBP,RILBP)

RILBP是一种改进的局部二值模式(LBP)算法,它在LBP的基础上增加了旋转不变性。在LBP中,对于同一纹理,不同的旋转角度会导致不同的LBP特征,这会影响到纹理识别的准确性。而RILBP通过对LBP特征进行旋转不变处理,使得同一纹理在不同旋转角度下的LBP特征保持一致,从而提高了纹理识别的准确性。

代码

import cv2
import numpy as np

def rotation_invariant_lbp(img, P=8, R=1):
    h, w = img.shape
    lbp = np.zeros((h-2*R, w-2*R), dtype=np.uint8)
    for i in range(R, h-R):
        for j in range(R, w-R):
            center = img[i, j]
            values = []
            for n in range(P):
                x = i + int(R * np.cos(2 * np.pi * n / P))
                y = j - int(R * np.sin(2 * np.pi * n / P))
                values.append(img[x, y])
            values = np.array(values)
            values = values - center
            values = np.where(values >= 0, 1, 0)
            lbp[i-R, j-R] = np.sum(values * (2 ** np.arange(P)))
    return lbp
# 其中,img为输入的灰度图像,P为采样点数,R为采样半径。
# 函数rotation_invariant_lbp返回的是旋转不变LBP特征图像。
# 读取图像
img = cv2.imread(r'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg', cv2.IMREAD_GRAYSCALE)

# 计算旋转不变LBP特征
lbp = rotation_invariant_lbp(img)

# 显示结果
cv2.imshow('LBP', lbp)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.方向性LBP(Directional LBP,DLBP) 

DLBP是一种改进的LBP算法,它是基于LBP算法的基础上,引入了梯度信息,从而提高了LBP算法的鲁棒性和判别能力。DLBP算法的主要思想是将图像分成若干个小块,对每个小块进行LBP特征提取,并计算该小块内像素的梯度信息,将LBP特征和梯度信息进行融合,得到该小块的DLBP特征。DLBP算法的优点是可以有效地提高LBP算法的鲁棒性和判别能力,对于光照变化不均匀、噪声等情况下的图像处理具有较好的效果。

以下是DLBP算法的实现步骤:
1. 将图像分成若干个小块,对每个小块进行LBP特征提取。
2. 计算该小块内像素的梯度信息。
3. 将LBP特征和梯度信息进行融合,得到该小块的DLBP特征。
4. 将所有小块的DLBP特征进行拼接,得到整幅图像的DLBP特征。

代码

import cv2
import numpy as np

def DLBP(img, radius=1, neighbors=8):
    h, w = img.shape
    dst = np.zeros((h-2*radius, w-2*radius), dtype=np.uint8)
    for i in range(radius, h-radius):
        for j in range(radius, w-radius):
            center = img[i, j]
            value = 0
            for k in range(neighbors):
                x = i + int(radius * np.cos(2 * np.pi * k / neighbors))
                y = j - int(radius * np.sin(2 * np.pi * k / neighbors))
                if img[x, y] > center:
                    value += 2 ** k
            dst[i-radius, j-radius] = value
    return dst

def get_gradient(img):
    grad_x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
    grad_y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
    gradx = cv2.convertScaleAbs(grad_x)
    grady = cv2.convertScaleAbs(grad_y)
    grad = cv2.addWeighted(gradx, 0.5, grady, 0.5, 0)
    return grad

def get_DLBP(img, radius=1, neighbors=8):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    grad = get_gradient(gray)
    lbp = DLBP(gray, radius, neighbors)
    dlbp = cv2.addWeighted(lbp, 0.5, grad, 0.5, 0)
    return dlbp

# 读取图像
img = cv2.imread(r'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg')
# 提取DLBP特征
dlbp = get_DLBP(img)
# 显示结果
cv2.imshow('DLBP', dlbp)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.多尺度LBP(Multiscale LBP,MLBP)

MLBP是一种基于LBP的改进算法,它是由多个LBP特征组合而成的。相比于传统的LBP算法,MLBP可以更好地描述图像的纹理特征。下面是MLBP的实现步骤:

1.将图像分成若干个小块,对于每个小块,都计算出一个LBP特征。

2.将每个小块的LBP特征串联起来,得到一个长向量。

3.将所有小块的向量组合成一个矩阵,每行代表一个小块的向量。

4.对矩阵进行主成分分析(PCA),得到一个降维后的矩阵。

5.将降维后的矩阵中的每个元素都归一化到[0,1]的范围内。

6.将归一化后的矩阵中的每个元素都乘以一个权重系数,得到最终的MLBP特征。

代码

import cv2
import numpy as np

def mlbp(img, P, R, num_blocks):
    # 将图像分成num_blocks x num_blocks个小块
    h, w = img.shape[:2]
    block_size = (w // num_blocks, h // num_blocks)
    blocks = [img[i*block_size[1]:(i+1)*block_size[1], j*block_size[0]:(j+1)*block_size[0]] for i in range(num_blocks) for j in range(num_blocks)]

    # 计算每个小块的LBP特征
    lbp_blocks = [cv2.spatial_histogram(block, P, R, normalize=True) for block in blocks]

    # 将所有小块的LBP特征串联起来
    lbp_vector = np.concatenate(lbp_blocks)

    # 将所有小块的LBP特征组成一个矩阵
    lbp_matrix = np.reshape(lbp_vector, (num_blocks*num_blocks, -1))

    # 对矩阵进行PCA降维
    pca = cv2.PCA(n_components=0.95)
    pca.fit(lbp_matrix)
    lbp_matrix_pca = pca.transform(lbp_matrix)

    # 归一化
    lbp_matrix_norm = cv2.normalize(lbp_matrix_pca, None, 0, 1, cv2.NORM_MINMAX)

    # 计算权重系数
    weights = np.arange(num_blocks*num_blocks)
    weights = np.exp(-weights)

    # 计算MLBP特征
    mlbp_feature = np.multiply(lbp_matrix_norm, weights.reshape(-1, 1))
    mlbp_feature = np.sum(mlbp_feature, axis=0)

    return mlbp_feature

# 读取图像
img = cv2.imread('test.jpg', cv2.IMREAD_GRAYSCALE)

# 计算MLBP特征
P = 8
R = 1
num_blocks = 4
mlbp_feature = mlbp(img, P, R, num_blocks)

# 输出MLBP特征
print(mlbp_feature)

7.加权LBP(Weighted LBP,W-LBP)

加权LBP(Local Binary Pattern)是一种用于图像处理的特征提取算法,它可以用于纹理分类、人脸识别等领域。加权LBP与传统的LBP相比,它引入了权重因子,可以更好地描述图像的纹理特征。下面是使用Python实现加权LBP的步骤:

1.将图像转换为灰度图像。

2.对于每个像素,计算其8个邻域像素与中心像素的差值,并将差值转换为二进制数。

3.根据二进制数计算加权值,加权值的计算公式为:$w_i=2^i$,其中$i$表示二进制数中1的个数。

4.将所有像素的加权值相加,得到该像素的加权LBP值。

5.将所有像素的加权LBP值组成一个向量,作为该图像的特征向量。

代码

import cv2
import numpy as np

# 定义计算加权LBP值的函数
def calc_weighted_lbp(img):
    rows, cols = img.shape
    dst = np.zeros((rows-2, cols-2), dtype=np.uint8)
    for i in range(1, rows-1):
        for j in range(1, cols-1):
            binary = ''
            center = img[i, j]
            for m in [-1, 0, 1]:
                for n in [-1, 0, 1]:
                    if m == 0 and n == 0:
                        continue
                    diff = img[i+m, j+n] - center
                    if diff >= 0:
                        binary += '1'
                    else:
                        binary += '0'
            weight = 0
            for k in range(len(binary)):
                if binary[k] == '1':
                    weight += 2**k
            dst[i-1, j-1] = weight
    return dst

# 读取图像并转换为灰度图像
img = cv2.imread('test.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 计算加权LBP特征向量
lbp = calc_weighted_lbp(gray)

# 输出特征向量
print(lbp)

8.局部对比度模式LBP(Local Contrast Pattern,LCP)

LBP改进算法LCP是一种用于纹理特征提取的算法,它是LBP算法的改进版本。LBP算法是一种用于图像纹理特征提取的算法,它通过比较像素点与周围像素点的灰度值大小关系,将每个像素点转换为二进制数,从而提取图像的纹理特征。LCP算法在LBP算法的基础上,引入了旋转不变性和灰度不变性,使得算法更加稳健和准确。

LCP算法的具体步骤如下:

  1. 将图像分成若干个小区域,对每个小区域进行处理。
  2. 对于每个像素点,计算其与周围像素点的灰度值大小关系,并将结果转换为二进制数。
  3. 对于每个小区域,将其中的所有像素点的二进制数进行拼接,得到一个二进制数序列。
  4. 对于每个二进制数序列,将其进行旋转不变性处理,即将其按照字典序排序后,选择最小的一个作为该序列的代表。
  5. 对于每个小区域,将其代表序列的二进制数转换为十进制数,作为该小区域的纹理特征。

代码 

import cv2
import numpy as np

def LCP(img):
    # 将图像分成16个小区域
    h, w = img.shape[:2]
    h_step, w_step = h // 4, w // 4
    features = []
    for i in range(4):
        for j in range(4):
            # 对每个小区域进行处理
            sub_img = img[i*h_step:(i+1)*h_step, j*w_step:(j+1)*w_step]
            sub_feature = []
            # 对每个像素点进行处理
            for m in range(1, h_step-1):
                for n in range(1, w_step-1):
                    center = sub_img[m, n]
                    binary = ''
                    for k in [(m-1, n-1), (m-1, n), (m-1, n+1), (m, n+1), (m+1, n+1), (m+1, n), (m+1, n-1), (m, n-1)]:
                        if sub_img[k] >= center:
                            binary += '1'
                        else:
                            binary += '0'
                    # 将二进制数转换为十进制数
                    sub_feature.append(int(binary, 2))
            # 对代表序列进行旋转不变性处理
            sub_feature.sort()
            sub_feature = np.array(sub_feature)
            min_feature = sub_feature
            for k in range(1, 8):
                sub_feature = np.roll(sub_feature, 1)
                if (sub_feature < min_feature).all():
                    min_feature = sub_feature
            # 将代表序列转换为十进制数,作为该小区域的纹理特征
            features.append(min_feature.dot(2 ** np.arange(min_feature.size)[::-1]))
    return features

# 读取图像
img = cv2.imread('test.jpg', 0)
# 提取纹理特征
features = LCP(img)
print(features)

从 skimage.feature导入

from skimage.feature import local_binary_pattern
import numpy as np
import cv2

# 读取图像
img = cv2.imread(r'D:\papercode\experiment\2\deep-learning-for-image-processing-master\deep-learning-for-image-processing-master\amusement_0037.jpg', 0)

# 计算LCP特征
radius = 3
n_points = 8 * radius
lcp = local_binary_pattern(img, n_points, radius)

# 将LCP特征转换为灰度图像
lcp = np.uint8((lcp / lcp.max()) * 255)

# 显示图像
cv2.imshow('LCP', lcp)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果: 

参考:

LBP算法及其改进算法

LBP(Local Binary Pattern,局部二值模式)

浅谈LBP原理和代码(基于Python)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值