您的当前位置:首页正文

LBP特征

2024-11-08 来源:个人技术集锦
  • https:///q123456789098/article/details/52748918
  • https:///zouxy09/article/details/7929531

LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度不变性等显著的优点。

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

3、对LBP特征向量进行提取的步骤

(1)首先将检测窗口划分为16×16的小区域(cell);

(2)对于每个cell中的一个像素,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经比较可产生8位二进制数,即得到该窗口中心像素点的LBP值;

(3)然后计算每个cell的直方图,即每个数字(假定是十进制数LBP值)出现的频率;然后对该直方图进行归一化处理。

(4)最后将得到的每个cell的统计直方图进行连接成为一个特征向量,也就是整幅图的LBP纹理特征向量;

然后便可利用SVM或者其他机器学习算法进行分类了。

代码实现

# @Time: 2021/6/10 11:29 
# @Author: wucong
# @File: computer_lbp.py 
# @Software: PyCharm
# @Version: win10 Python 3.7.6
# @Version: torch 1.8.1+cu111 torchvision 0.9.1+cu111
# @Version: tensorflow 2.4.1+cu111  keras 2.4.3
# @Describe:
"""
- https:///q123456789098/article/details/52748918
- https:///zouxy09/article/details/7929531

LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;
它具有旋转不变性和灰度不变性等显著的优点。
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import normalize
from numba import jit
from scipy import signal
import time

# from skimage.feature import local_binary_pattern as lbp

def get_lbp_value(str1:str,rotation:bool):
    if rotation:
        tmp=[]
        for i in range(8):
            tmp.append(int(str1, 2))
            str1 = str1[1:]+str1[0]
        return min(tmp)
    else:
        return int(str1,2) # 转成10进制

def get_lbp_img(img:np.array,ksize=3,h=64,w=64,rotation=True):
    img = np.pad(img,[[1,1],[1,1]],'constant',constant_values=0)
    new_img = img.copy()
    for i in range(1,h+1):
        for j in range(1,w+1):
            lbp_list = []
            p = ksize//2
            v = img[i,j]
            lbp_list.append(str((img[i-p,j-p]>v).astype(int)))
            lbp_list.append(str((img[i-p,j]>v).astype(int)))
            lbp_list.append(str((img[i-p,j+p]>v).astype(int)))
            lbp_list.append(str((img[i,j+p]>v).astype(int)))
            lbp_list.append(str((img[i+p,j+p]>v).astype(int)))
            lbp_list.append(str((img[i+p,j]>v).astype(int)))
            lbp_list.append(str((img[i+p,j-p]>v).astype(int)))
            lbp_list.append(str((img[i,j-p]>v).astype(int)))

            # 加入旋转不变性 取最小值
            lbp_str = "".join(lbp_list)

            new_img[i,j] = get_lbp_value(lbp_str,rotation)

    return new_img[1:-1,1:-1]


def lbp(img:np.array,cell_size,stride=0,bins=64,h=64,w=64,rotation=True):
    """

    Args:
        img: 默认是 BGR格式
        cell_size:
        stride: >=cell_size时 每个cell间不重叠 ;否则重叠
        bins: 0 表示不做统计;否则 做统计 [0,256] 推荐使用 统计
        h: resize 后的 高
        w:  resize 后的 宽

    Returns: lbp特征

    """

    # 1.灰度化
    if img.ndim > 2: img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.resize(img, (w, h))
    img = get_lbp_img(img,3,h,w,rotation)

    if stride == 0: stride=cell_size
    feature = []
    for i in range(0,h-cell_size,stride):
        for j in range(0,w-cell_size,stride):
            timg = img[i:i+cell_size,j:j+cell_size] # 1个cell
            if bins == 0: # 不做统计
                # feature.append(timg)
                feature.append(normalize(np.array(timg.flatten())[None])[0])
            else:
                interval = 256/bins
                hist = [0]*bins
                for px in timg.flatten():
                    hist[int(px//interval)] += 1

                # 归一化
                hist = normalize(np.array(hist)[None])[0]
                feature.append(hist)

    return np.stack(feature).reshape(-1)

if __name__=="__main__":
    start = time.time()
    img = cv2.imread('./6_36_1.jpg')
    feature = lbp(img,cell_size=10,stride=3,bins=0)
    end = time.time()
    print(feature.shape,'cost time:%.5f'%(end-start))
显示全文