『youcans 的 OpenCV 例程200篇 - 总目录』
【youcans 的 OpenCV 例程200篇】230. 特征描述之 LBP 统计直方图
局部二值模式(LBP,Local binary patterns)是一种用来描述图像局部纹理特征的算子,它具有旋转不变性和灰度不变性的优点 。 LBP 特征计算简单、效果较好,在计算机视觉领域得到了广泛的应用。
4.2.3 LBP 特征的统计直方图
描述纹理的常用方法是使用图像或目标区域的统计直方图。
基本 LBP 算子
基本的 LBP 算子定义在 3×3 的窗口内,以窗口中心像素为阈值,与相邻的 8 个像素的灰度值比较,大于阈值则标记为 1,否则标记为 0。从右上角开始顺时针旋转,排列 8 个 0/1标记值,得到一个 8 位二进制数,就是窗口中心像素点的 LBP 值。
LBPP,R(xc,yc)=∑p=0P−1S(gp−gc)∗2pS(gp−gc)={1,gp≥gc0,gp<gcLBP_{P,R} (x_c,y_c) = \sum_{p=0}^{P-1} S(g_p-g_c)*2^p\\ S(g_p-g_c) = \begin{cases} 1, \quad g_p \ge g_c\\ 0, \quad g_p \lt g_c \end{cases} LBPP,R(xc,yc)=p=0∑P−1S(gp−gc)∗2pS(gp−gc)={1,gp≥gc0,gp<gc
LBP 直方图
图像可以用 LBP 特征向量来表示,但在应用中一般并不是直接使用 LBP 图谱进行分类识别,而是使用 LBP 特征谱的统计直方图进行分类识别。因为 LBP 特征是与图像中的位置紧密相关的,直接对两幅图片提取 LBP 特征进行判别分析,会由于位置没有对准而带来很大的误差。
为了解决这个问题,可以将图像划分为若干子区域,对每个子区域内提取 LBP 特征后在子区域内建立 LBP 特征的统计直方图。图片的每个子区域可以用一个统计直方图来描述,整个图片就由若干个统计直方图组成,称为 LBP 特征的统计直方图(LBPH,Local Binary Patterns Histograms)。
LBPH 将 LBP 特征与图像的空间信息结合起来。将 LBP 特征图像分成 m 个子块,提取每个子块的 LBP 特征并建立统计直方图,将这些直方图依次连接在一起,就形成 LBP 特征的统计直方图。
计算 LBP 统计直方图的步骤为:
(1)计算 LBP 特征图像;
(2)将 LBP 特征图像划分为若干块子区域(cell),默认划分 8*8=64 块子区域;
(3)计算每个子区域 LBP 特征图像的直方图(cell_LBPH),并进行归一化处理;
(4)将每个子区域的 LBP 直方图依次排列成一行,形成 LBP 特征向量;
(5)用机器学习方法对 LBP 特征向量进行训练,检测和识别目标。
例程只给出 LBP 统计直方图的构造,基于 LBP 直方图的特征检测和目标识别,将在模式识别中介绍。
例程 14.10:特征描述之 LBP 直方图
# 14.10 特征描述之 LBP 直方图def basicLBP(gray):height, width = gray.shapedst = np.zeros((height, width), np.uint8)kernelFlatten = np.array([1, 2, 4, 128, 0, 8, 64, 32, 16]) # 从左上角开始顺时针旋转for h in range(1, height-1):for w in range(1, width-1):LBPFlatten = (gray[h-1:h+2, w-1:w+2] >= gray[h, w]).flatten() # 展平为一维向量, (9,)dst[h, w] = np.vdot(LBPFlatten, kernelFlatten) # 一维向量的内积return dstdef calLBPHistogram(imgLBP, nCellX, nCellY): # 计算 LBP 直方图height, width = gray.shape# nCellX, nCellY = 4, 4 # 将图像划分为 nCellX*nCellY 个子区域hCell, wCell = height//nCellY, width//nCellX # 子区域的高度与宽度 (150,120)LBPHistogram = np.zeros((nCellX*nCellY, 256), np.int)for j in range(nCellY):for i in range(nCellX):cell = imgLBP[j * hCell:(j + 1) * hCell, i * wCell:(i + 1) * wCell].copy() # 子区域 cell LBPprint("{}, Cell({}{}): [{}:{}, {}:{}]".format(j*nCellX+i+1, j+1, i+1, j*hCell, (j+1)*hCell, i*wCell, (i+1)*wCell))histCell = cv2.calcHist([cell], [0], None, [256], [0, 256]) # 子区域 LBP 直方图LBPHistogram[(i+1)*(j+1)-1, :] = histCell.flatten()print(LBPHistogram.shape)return LBPHistogram# 特征描述之 LBP 直方图img = cv2.imread("../images/fabric2.png", flags=1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图像height, width = gray.shapenCellX, nCellY = 4, 4 # 将图像划分为 nCellX*nCellY 个子区域hCell, wCell = height//nCellY, width//nCellX # 子区域的高度与宽度 (150,120)print("img: h={},w={}, cell: h={},w={}".format(height, width, hCell, wCell))basicLBP = basicLBP(gray) # 计算 basicLBP 特征算子# LBPHistogram = calLBPHistogram(basicLBP, nCellX, nCellY) # 计算 LBP 直方图 (16, 256)fig1 = plt.figure(figsize=(9, 8))fig1.suptitle("basic LBP")fig2 = plt.figure(figsize=(9, 8))fig2.suptitle("LBP histogram")for j in range(nCellY):for i in range(nCellX):cell = basicLBP[j*hCell:(j+1)*hCell, i*wCell:(i+1)*wCell].copy() # 子区域 cell LBPhistCV = cv2.calcHist([cell], [0], None, [256], [0, 256]) # 子区域 cell LBP 直方图ax1 = fig1.add_subplot(nCellY, nCellX, j * nCellX + i + 1)ax1.set_xticks([]), ax1.set_yticks([])ax1.imshow(cell, 'gray') # 绘制子区域 LBP ax2 = fig2.add_subplot(nCellY,nCellX,j*nCellX+i+1)ax2.set_xticks([]), ax2.set_yticks([])ax2.bar(range(256), histCV[:, 0]) # 绘制子区域 LBP 直方图print("{}, Cell({}{}): [{}:{}, {}:{}]".format(j * nCellX + i + 1, j + 1, i + 1, j * hCell, (j + 1) * hCell, i * wCell, (i + 1) * wCell))plt.show()
【本节完】
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125681261)
Copyright 2022 youcans, XUPT
Crated:2022-7-7
227. 特征描述之 LBP 纹理特征算子
228. 特征描述之 extendLBP 改进算子
229. 特征描述之 LBP 算子比较(skimage)
230. 特征描述之 LBP 统计直方图