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))