LBP特征学习(附python实现)
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实现)的更多相关文章
- LBP特征 学习笔记
这几天一直在做人脸识别的项目,有用到LBP特征,但是毫无头绪,师姐这几天也比较忙,没有时间来指导我,随自己找相应的介绍LBP的博文来看,现在总算有了一个大体的思路了,就写下来吧 注:参考博文: 目标检 ...
- LBP特征
此篇摘取 <LBP特征原理及代码实现> <LBP特征 学习笔记> 另可参考实现: <LBP特征学习及实现> <LBP特征的实现及LBP+SVM分类> & ...
- Python语言学习之Python入门到进阶
人们常说Python语言简单,编写简单程序时好像也确实如此.但实际上Python绝不简单,它也是一种很复杂的语言,其功能特征非常丰富,能支持多种编程风格,在几乎所有方面都能深度定制.要想用好Pytho ...
- (转)利用Auto ARIMA构建高性能时间序列模型(附Python和R代码)
转自: 原文标题:Build High Performance Time Series Models using Auto ARIMA in Python and R 作者:AISHWARYA SI ...
- XGBoost参数调优完全指南(附Python代码)
XGBoost参数调优完全指南(附Python代码):http://www.2cto.com/kf/201607/528771.html https://www.zhihu.com/question/ ...
- 每个程序员都应该学习使用Python或Ruby
每个程序员都应该学习使用Python或Ruby 如果你是个学生,你应该会C,C++和Java.还会一些VB,或C#/.NET.多少你还可能开发过一些Web网页,你知道一些HTML,CSS和JavaSc ...
- EasyPR源码剖析(6):车牌判断之LBP特征
一.LBP特征 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点. 原始的LBP算子定义在像素 ...
- 图像边缘检测——几种图像边缘检测算子的学习及python 实现
本文学习利用python学习边缘检测的滤波器,首先读入的图片代码如下: import cv2 from pylab import * saber = cv2.imread("construc ...
- LBP人脸识别的python实现
这几天看了看LBP及其人脸识别的流程,并在网络上搜相应的python代码,有,但代码质量不好,于是自己就重新写了下,对于att_faces数据集的识别率能达到95.0%~99.0%(40种类型,每种随 ...
随机推荐
- 文件及文件夹操作- File类、Directory 类、FileInfo 类、DirectoryInfo 类
文件及文件夹操作: C/S:WinForm可以操作客户端文件 Client ServerB/S:Brower Server 命名空间:using system .IO; 1. File类: 创建:Fi ...
- ROS * 了解学习urdf的内容格式及编写
<?xml version="1.0" ?> 声明文件使用xml描述 <robot name="robot_name">定义这是一个机器 ...
- CF999E Reachability from the Capital来自首都的可达性
题目大意: 有n个节点m条边,边都是单向的,请你添加最少的边使得起点s到其他与其他每一个点之间都能互相到达 这题一看就是一个缩点啊 其实对于原有的m条边相连的一些点,如果之前他们已经形成了强连通分量( ...
- java面试总躲不过的并发(二):volatile原理 + happens-before原则
一.happens-before原则 同一个线程中的,前面的操作 happens-before 后续的操作.(即单线程内按代码顺序执行.但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进 ...
- Lunar Lander 月球冒险
发售年份 1979 平台 街机 开发商 雅达利(Atari) 类型 飞行模拟 https://www.youtube.com/watch?v=McAhSoAEbhM
- 面试题-linux基础
Linux基础和git linux的基础命令(怎么区分一个文件还是文件夹) ls -F 在显示名称的时候会在文件夹后面添加“/”, 在文件后面加“*” 日志以什么格式,存放在哪里?日志可以存储在“/ ...
- 关于使用colorbox加载html页面的一些问题
ColorBox是一个基于jQuery 1.3 的轻量级,自定义灯箱插件,功能非常强大,支持图片,图片组,ajax,inline和iframed内容,灯箱样式完全由用户控制,可自定义CSS样 式,不需 ...
- java 身份证工具类
package com.app.wx.common.util; import org.apache.commons.lang3.StringUtils; import java.text.ParseE ...
- python基础知识13---函数对象、函数嵌套、名称空间与作用域、装饰器
阅读目录 一 函数对象 二 函数嵌套 三 名称空间与作用域 四 闭包函数 五 装饰器 六 练习题 一 函数对象 1 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 ...
- DApp demo之pet-shop
注意: 这里使用的truffle版本为4.1.4,貌似使用高版本在truffle test时候会出问题,提示 truffle/Assert.sol is not found等错误 使用Truffle ...