Uniform LBP(均匀LBP)
为解决二进制模式过多的问题,提高统计性,Ojala提出了采用一种“等价模式”(Uniform Pattern)来对LBP算子的模式种类进行降维。Ojala等认为,在实际图像中,绝大多数LBP模式最多只包含两次从1到0或从0到1的跳变。因此,Ojala将“等价模式”定义为:当某个LBP所对应的循环二进制数从0到1或从1到0最多有两次跳变时,该LBP所对应的二进制就称为一个等价模式类。如00000000(0次跳变),00000111(只含一次从0到1的跳变),10001111(先由1跳到0,再由0跳到1,共两次跳变)都是等价模式类。除等价模式类以外的模式都归为另一类,称为混合模式类,例如10010111(共四次跳变)。通过这样的改进,二进制模式的种类大大减少,而不会丢失任何信息。模式数量由原来的2P种减少为 P ( P-1)+2种,其中P表示邻域集内的采样点数。对于3×3邻域内8个采样点来说,二进制模式由原始的256种减少为58种,即:它把值分为59类,58个uniform pattern为一类,依次从大到小排序;其它的所有值为第59类。这样直方图从原来的256维变成59维。这使得特征向量的维数更少,并且可以减少高频噪声带来的影响。
Python代码:
import numpy as np
import cv2
import os
np.set_printoptions(threshold = 1e6)
def arry_58():
l = np.zeros(58, dtype=int)
m = []
a = -1
for i in range(256):
bit = '{:08b}'.format(i) # 二进制化
arry = [] # 二进制生成数组
count = 0 # 计数变化次数
# 把字符串变为数组方便统计变化次数
for x in range(len(bit)):
arry.append(int(bit[x]))
# print(arry)
first = arry[0] # 数组第一个为first,与之后的比较
for j in range(1, len(arry)):
if arry[j] != first: # 如果变化,计数单位加1
count += 1
first = arry[j] # 并且把变化的值重新赋值
# print(count)
if count <= 2: # 如果变化次数小于2,则依次排序
a += 1
# print(i)
l[a] = i
l = l.tolist()
return l
def uniform_LBP(img):
h, w = img.shape # 图像的长和宽
dst = np.zeros((h - 2, w - 2), dtype=img.dtype) # 新建一张图
# dst = np.zeros(img.shape, dtype=img.dtype) # 新建一张图
arry58 = arry_58()
for i in range(1, h - 1):
for j in range(1, w - 1):
center = img[i][j]
code = []
count = 0
code7 = img[i - 1][j - 1]
if code7 >= center:
code7 = 1
else:
code7 = 0
code.append(code7)
code6 = img[i - 1][j]
if code6 >= center:
code6 = 1
else:
code6 = 0
code.append(code6)
code5 = img[i - 1][j + 1]
if code5 >= center:
code5 = 1
else:
code5 = 0
code.append(code5)
code4 = img[i][j + 1]
if code4 >= center:
code4 = 1
else:
code4 = 0
code.append(code4)
code3 = img[i + 1][j + 1]
if code3 >= center:
code3 = 1
else:
code3 = 0
code.append(code3)
code2 = img[i + 1][j]
if code2 >= center:
code2 = 1
else:
code2 = 0
code.append(code2)
code1 = img[i + 1][j - 1]
if code1 >= center:
code1 = 1
else:
code1 = 0
code.append(code1)
code0 = img[i][j - 1]
if code0 >= center:
code0 = 1
else:
code0 = 0
code.append(code0)
LBP = code7*128 + code6*64 + code5*32 + code4*16 + code3*8 + code2*4 + code1*2 + code0*1
#print("LBP值为:",LBP)
#print("8位编码为:",code)
first = code[0] # 数组第一个为first,与之后的比较
for x in range(1, len(code)):
if code[x] != first: # 如果变化,计数单位加1
count += 1
first = code[x] # 并且把变化的值重新赋值
#print("跳变次数",count)
if count > 2: # 如果变化次数大于3,则归为59位
dst[i - 1][j - 1] = 58
else: # 否则,按原来的数计算
loca = arry58.index(LBP) # 获取位置
dst[i - 1][j - 1] = loca
return dst
if __name__ == '__main__':
gray = cv2.imread('./b.jpg', cv2.IMREAD_GRAYSCALE)
print(gray.shape)
a = uniform_LBP(gray)
cv2.imshow('uniform_lbp', a)
cv2.imwrite("./2.jpg", a)
cv2.waitKey(0)