LBP的全称是Local Binary Pattern即局部二值模式,是局部信息提取中的一种方法,它具有旋转不变性和灰度不变性等显著的优点。在人脸识别领域有很多案例,此外,局部特征的算法还有 SIFT HOG等等。

LBP就是一种局部信息,它反应的内容是每个像素与周围像素的关系。举最基本的LBP为例,它反应了像素与周围8个点灰度值的关系,如下图所示:


  如上图所示,中间像素的灰度值为54,我们如下定义:当周围像素的灰度值大于等于中间像素值时,则LBP的一位值为1,否则为零。由这个九宫格,我们就得到了8位二进制数,顺时针取值,就得到了一个像素的LBP值,即11010011。那么我们如何表示这个二进值数呢,很简单,我们将它转化为十进制数即可,也就是211,即这一点的LBP值为211。就这样对整个图像进行LBP运算,就可以得到这幅图像的LBP特征。也就是说,我们把一张像素为256*256的图片进行LBP特征提取,我们就可以得到一个256*256的特征图(最外面的一圈进行补0后在进行运算),但每个特征图里的数值的范围是多少呢  0-256吗 不是的,特征图里的数值是由你定义的半径 和邻居数决定的 。比如上述的例子,他的半径是只选了周围一圈的8个,也就是 半径为1,邻居为 8 (一般来说,邻居数为半径的8倍) 。以此类推。 如果我们定义的是 半径为2 ,邻居为 2*8时 得到的特征图的数值的二进制数长度就翻了一番,所以范围是  0-65535 。

  但是得到这些特征有什么作用呢?提取图像特征的目标无非就是为了进行分类,我们把一幅灰度图像转化为了LBP特征图像,从理论上讲并没有实现降维,也无法进行分类。

  这时就引入了直方图统计,我们将LBP特征进行直方图统计,也就是统计LBP特征0~255各占的比例,这样就进行了数据的降维。之后就可以将一个向量输入分类器中进行分类。可是由于只有256维特征,所以分类的效果并不好。这时我们就引入了图像分块处理的方法,也就是说将图像分成若干的图像块,如,在人脸识别中,把脸分为7*7,5*5的区域,并对这49,25个小区域进行LBP处理,将每个小区域的直方图进行串联,就可以得到整个图像的LBP直方图。并对这个直方图进行分类处理,这样可以大大的增强分类的效果。但是分类数据维度也大大增加了,如果是7*7区域,数据维度为7*7*256=12544维。

可以看出数据的维度还是比较大,所以需要进一步进行降维,这里就涉及了另外一个概念:Uniform LBP,即均匀模式LBP。这种降维感觉是用了电路中的方法,也就是将原来的256维灰度数据重新分类,统计其位移后的跳变次数,当跳变次数小于2次时就定义为一个Uniform LBP,比如00000000左移一位还是00000000,没有跳变,即跳变次数为0;00001111左移一位为00011110,跳变次数为2;10100000左移一位为01000001跳变次数为3,它不是Uniform LBP。经过统计,Uniform LBP在整个的LBP特征中占85~90%,而Uniform LBP只有58个特征。所以我们将分类特征向量由256维降为58维。在实际应用中,其实是59维,因为加一维表示那些不是Uniform LBP的量。那么7*7的人脸区域在进行降维之后,有7*7*59=2891维。由此对LBP特征进行了降维。

所以,对LBP特征向量进行提取的步骤为:

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

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

3)然后计算每个cell的直方图,即每个数字出现的频率,然后对该直方图进行归一化处理

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

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

此外,LBP有许多的改进版本

1)圆形LBP算子

基本的LBP算子的最大缺陷就是只覆盖了一个固定半径范围内的小区域,这显然不能满足不同尺寸和频率纹理的需要,为了适应不同尺度的纹理特征,并达到灰度和旋转不变性的要求。改进后的LBP算子允许在半径为R的圆形领域内有任意多个像素点,从而得到诸如半径为R的圆形区域内含有p个采样点的LBP算子(见LBP算子.jpg)

2)LBP旋转不变模式

从LBP定义可以看出,LBP算子是灰度不变的,但却不是旋转不变的,图像的旋转就会得到不同的LBP值。为了得到旋转不变性,即不断旋转圆形领域得到一系列初始定义的LBP值,取其最小值作为该领域的LBP值。(见旋转不变的LBP示意.jpg)

3)LBP等价模式

一个LBP算子可以产生不同的二进制模式,对于半径为R的圆形区域内含有p个采样点的LBP算子将会产生2的p次方中模式,显然,随着领域内采样点数的增加,二进制模式的种类急剧增加。如此多的二值模式对于纹理的表达是不利的。如将LBP算子用于纹理分类或人脸识别时,常采用LBP模式的统计直方图来表达图像的信息,而较多的模式种类将使得数据量过大,且直方图过于稀疏,因此,需要对原始的LBP模式进行降维,使得数据减少的情况下能最好的代表图像的信息。

使用python进行LBP特征提取并进行SVM训练

使用到 skimage sklearn 等等

代码稍后写好放上去。。。。

import numpy as np
import cv2
import os
from skimage import io, transform, color, measure, segmentation, morphology, feature
from sklearn import svm, multiclass, model_selection
import csv
import matplotlib.pyplot as plt
# from PIL import Image path = "G:\\Sample1\\"
csvfile = path+"ground_truth.csv"
print(csvfile)
pic_path = []
label_1 = []
label_2 = [] #把标签转换为 数字量
def label2number(label_list):
label=np.zeros(len(label_list),)
label_unique=np.unique(label_list)
num=label_unique.shape[0]
# label_list = np.array(label_list)
for k in range(num):
temp=label_unique[k]
index=[i for i, v in enumerate(label_list) if v == temp]
#
# print(temp)
# index=label_list.find(temp)
label[index]=k
return label,label_unique # 填充空白区域
def imfill(im_th):
# im_th 是0 1 整形二值图
# Copy the thresholded imapge.
im_th = np.uint8(im_th)
im_floodfill = im_th.copy()
# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.shape[:2]
# print('h '+str(h)+' w '+str(w))
mask = np.zeros((h + 2, w + 2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (0, 0), 1)
# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)
# Combine the two images to get the foreground.
im_out = im_th | im_floodfill_inv
return im_out #打开csv文件 第0列是 图片名称 第1 2列是 两种标签
with open(csvfile, "r") as f:
# with open(birth_weight_file, "w") as f:
csvreader = csv.reader(f)
csvheader = next(csvreader)
print(csvheader)
for row in csvreader: # print(len(row))
pic_path.append(path+'Images\\'+row[0])
label_1.append(row[1])
label_2.append(row[2]) # 图片样本进行预处理,进行裁剪,去除非必要部分
vidHeight = 660
vidWidth = 1120
# for i in range(0, len(pic_path)):
Data=[]
for i in range(0, 1000):
if os.path.exists(pic_path[i]):
pic_temp = io.imread(pic_path[i]) pic_temp = pic_temp[300:(660+300), 80:(80+1120)]
roi = color.rgb2gray(pic_temp)
thresh = 140
bw = (roi <= thresh/255) * 1 # 根据阈值进行分割
# dst=np.uint8(dst)
pic_temp2 = imfill(bw) cleared = pic_temp2.copy() # 复制
segmentation.clear_border(cleared) # 清除与边界相连的目标物
label_image = measure.label(cleared) # 连通区域标记 connectivity=1 # 4连通区域标记
# image_label_overlay = color.label2rgb(label_image) # 不同标记用不同颜色显示
# plt.imshow(image_label_overlay, interpolation='nearest')
# plt.show()
borders = np.logical_xor(bw, cleared) # 异或,去除背景
label_image[borders] = -1
Eccentricity = 1 # 离心率
for region in measure.regionprops(label_image): # 循环得到每一个连通区域属性集
# 忽略小区域 if region.area < 100000:
continue
# print('area is ' + str(region.area) + ' ecc is' + str(region.eccentricity))
if Eccentricity > region.eccentricity:
Eccentricity = region.eccentricity
minr, minc, maxr, maxc = region.bbox # 绘制外包矩形
# 判断是否有符合条件的区域
if 'minr' in vars():
pic = pic_temp[minr:maxr, minc:maxc,:]
pic = transform.resize(pic, [256,256,3])
#print(lbp)
# plt.imshow(pic)
# plt.show()
else:
pic = transform.resize(pic_temp, [256, 256, 3]) #提取LBP特征,每个图像分成4块进行提取
pic1 = color.rgb2gray(pic)
rows, cols = pic1.shape
radius = 2;
n_points = radius * 8 lbp_sum=[]
for row in range(2):
for col in range(2):
#print(str((row * rows//2)) + ' : ' + str(((row+1) * rows//2 - 1)))
pic1_block = pic1[(row * rows//2) : ((row+1) * rows//2 - 1) , (col * col//2) : ((col+1) * col//2 - 1)]
lbp = feature.local_binary_pattern(pic1, n_points, radius, 'uniform')
lbp2 = lbp.astype(np.int32)
max_bins = int(lbp2.max() + 1)
train_hist, _ = np.histogram(lbp2, normed=True, bins=max_bins, range=(0, max_bins))
# print(train_hist.dtype)
#print(train_hist)
lbp_sum=lbp_sum + train_hist.tolist()
# Data.append(lbp_sum)

#使用SVM进行训练并计算测试准确率
label1, _ = label2number(label_1[0:1000])
X_train,X_test, y_train, y_test = model_selection.train_test_split(Data,label1,test_size=0.2, random_state=0)
# train_data = Data[0:7]
# train_label = label1[0:7]
# test_data = Data[8:9]
# test_label = label1[8:9]
svr_rbf = svm.SVR(kernel='rbf', C=1e3, gamma=0.1);
model = multiclass .OneVsRestClassifier(svr_rbf,-1) #.fit(train_data, train_label).score(test_data,test_label)
clf = model.fit(X_train, y_train)
sore=clf.score(X_test, y_test)
print('acc'+str(sore))

  

参考文献: http://blog.sina.com.cn/s/blog_4bdbec750101ekuh.html

         https://1043693084-qq-com.iteye.com/blog/2245828

LBP特征学习(附python实现)的更多相关文章

  1. LBP特征 学习笔记

    这几天一直在做人脸识别的项目,有用到LBP特征,但是毫无头绪,师姐这几天也比较忙,没有时间来指导我,随自己找相应的介绍LBP的博文来看,现在总算有了一个大体的思路了,就写下来吧 注:参考博文: 目标检 ...

  2. LBP特征

    此篇摘取 <LBP特征原理及代码实现> <LBP特征 学习笔记> 另可参考实现: <LBP特征学习及实现> <LBP特征的实现及LBP+SVM分类> & ...

  3. Python语言学习之Python入门到进阶

    人们常说Python语言简单,编写简单程序时好像也确实如此.但实际上Python绝不简单,它也是一种很复杂的语言,其功能特征非常丰富,能支持多种编程风格,在几乎所有方面都能深度定制.要想用好Pytho ...

  4. (转)利用Auto ARIMA构建高性能时间序列模型(附Python和R代码)

    转自:  原文标题:Build High Performance Time Series Models using Auto ARIMA in Python and R 作者:AISHWARYA SI ...

  5. XGBoost参数调优完全指南(附Python代码)

    XGBoost参数调优完全指南(附Python代码):http://www.2cto.com/kf/201607/528771.html https://www.zhihu.com/question/ ...

  6. 每个程序员都应该学习使用Python或Ruby

    每个程序员都应该学习使用Python或Ruby 如果你是个学生,你应该会C,C++和Java.还会一些VB,或C#/.NET.多少你还可能开发过一些Web网页,你知道一些HTML,CSS和JavaSc ...

  7. EasyPR源码剖析(6):车牌判断之LBP特征

    一.LBP特征 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点. 原始的LBP算子定义在像素 ...

  8. 图像边缘检测——几种图像边缘检测算子的学习及python 实现

    本文学习利用python学习边缘检测的滤波器,首先读入的图片代码如下: import cv2 from pylab import * saber = cv2.imread("construc ...

  9. LBP人脸识别的python实现

    这几天看了看LBP及其人脸识别的流程,并在网络上搜相应的python代码,有,但代码质量不好,于是自己就重新写了下,对于att_faces数据集的识别率能达到95.0%~99.0%(40种类型,每种随 ...

随机推荐

  1. windows下配置下burpsuite的小方法。

    1.下载破解版burpsuite和正版burpsuite. 2.安装正版burpsuite(免费版) 3.打开安装路径 4.把破解版的burp拷贝到安装路径下 5.该路径下应该有个burpsuite_ ...

  2. socks5服务器编写经验总结

    一.Socks5服务器实现设计 本Socks5服务器是之前做的一个项目中的一个小部分东西,该项目是一个可以实现多级转发代理网络通讯的项目,能够隐藏网络数据包的源IP地址和端口,能够为上网的用户提供安全 ...

  3. 2019CVTE技术支持软件编程

    题目:找出长度为M的数组S中求和为1的任意三个数组合个数,举例:S=[-2, 0, 1, 2, -1, 3],结果为:3个([-2, 0, 3], [-2, 1, 2], [0, 2, -1]). 思 ...

  4. Android Studio学习NO.1 了解项目资源

    2018.3.1 12:40:51 阅读书籍:第一行代码 1. res目录 drawable 图片 mipmap 图标 values 字符串.样式.颜色 layout 布局 2. 引用(可在Andro ...

  5. 像使用数据库一样使用xml

    目录 xml简介 语言结构 tinyxml 下载tinyxml 应用实例 tinyxml的封装 封装源码 实际应用 xml简介 XML 没什么特别的.它仅仅是纯文本而已.有能力处理纯文本的软件都可以处 ...

  6. Linux内核笔记:内存管理

    逻辑地址由16位segment selector和offset组成 根据segment selector到GDT或LDT中去查找segment descriptor 32位base,20位limit, ...

  7. postman进行https接口测试所遇到的ssl证书问题,参考别人方法

    参考文档: https://learning.getpostman.com/docs/postman/sending_api_requests/certificates/ 随着 https 的推动,更 ...

  8. Asp.Net : Page.RegisterStartupScript及 不执行的原因

    RegisterStartupScript 把script放置在ASP.NET page的底部,而RegisterClientScriptBlock把script放置在ASP.NET page的顶部 ...

  9. IntellijIDEA常用快捷键总结

    转载自:http://blog.csdn.net/qq_17586821/article/details/52554731 下面的这些常用快捷键需要在实际操作中不断地体会才能真正感受到它们的方便之处. ...

  10. 多次ajax请求数据json出错

    问题描述: 1.对象数据存放在session中,每次从session中取数据 2.jsp初始化完毕调用ajax请求,返回的数据格式出错(返回部分数据,即丢失了部分数据) 解决方案: