LBP study notes (1) --- Detailed explanation of original mode features (code implementation)

1. Brief description of LBP operator and LBP original mode

        The LBP (Local Binary Pattern) operator is a local image feature for texture description, proposed by T.Ojala, M.Pietikäinen and D.Harwood in 1994. The LBP operator compares each pixel in the image with its surrounding neighborhood pixels, counts the number of neighborhood pixels whose gray value is greater than or equal to the central pixel, and converts the statistical results into binary codes to represent the local features of the pixel .

        The LBP operator has the advantages of grayscale invariance and rotation invariance, and can be calculated quickly. It is widely used in face recognition, texture classification, pedestrian detection and other fields. Based on the improvement of LBP operator, algorithms such as rotation-invariant LBP and multi-scale LBP have also been proposed one after another.

        The LBP original mode means that in the LBP operator, the binary code of each pixel does not include itself, in the 8 neighboring pixels around it, the total number of pixels that are greater than or equal to its intensity value is counted, and these The pixel is stored as a binary code (corresponding to an 8-bit binary number), and the final binary code is the LBP original mode of the pixel. For a set of pixels in a 3*3 neighborhood, there are 256 different LBP modes (including all 0 and all 1 modes).

        LBP original mode is the most basic form of LBP operator, which is widely used in face recognition, texture classification and other fields. The LBP operator has the advantages of gray invariance and rotation invariance, and can be calculated quickly, so it is considered as a simple and effective texture feature descriptor.

2. Code implementation (key functions and complete code)

1. Traversing pixels to obtain original pattern features

def lbp_basic(self, image_array):
    basic_array = np.zeros(image_array.shape, np.uint8)
    width = image_array.shape[0]
    height = image_array.shape[1]
    for i in range(1, width - 1):
        for j in range(1, height - 1):
            sum = self.calute_basic_lbp(image_array, i, j)[1]
            basic_array[i, j] = sum
    return basic_array

First create a matrix of all 0s of the same size, and then start traversing after removing the outer circle from the image. After obtaining the original mode features, assign them to the corresponding position of the matrix just created, and return the matrix

2. Calculate LBP original mode features

# 图像的LBP原始特征计算算法:将图像指定位置的像素与周围8个像素比较
# 比中心像素大的点赋值为1,比中心像素小的赋值为0,返回得到的二进制序列
def calute_basic_lbp(self, image_array, i, j):
    sum = []
    num = 0
    if image_array[i - 1, j - 1] > image_array[i, j]:
        sum.append(1)
        num += 2**0
    else:
        sum.append(0)
    if image_array[i - 1, j] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 1
    else:
        sum.append(0)
    if image_array[i - 1, j + 1] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 2
    else:
        sum.append(0)
    if image_array[i, j - 1] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 3
    else:
        sum.append(0)
    if image_array[i, j + 1] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 4
    else:
        sum.append(0)
    if image_array[i + 1, j - 1] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 5
    else:
        sum.append(0)
    if image_array[i + 1, j] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 6
    else:
        sum.append(0)
    if image_array[i + 1, j + 1] > image_array[i, j]:
        sum.append(1)
        num += 2 ** 7
    else:
        sum.append(0)
    return sum,num

Compare the eight pixel values ​​of the eight neighborhoods of the pixel that have been encountered with this pixel value, and if it is larger, it is 1, otherwise it is 0.

The sum list stores the comparison result of the eight pixel values ​​clockwise from the upper left corner of the pixel and the center pixel, which is the pixel, and is a binary sequence, such as [0,0,1,0,1,1 ,0,1]

num is the decimal number after sum is rotated 180 degrees. For example: sum=[0,0,1,0,1,1,0,1], then sum is rotated 180 degrees to [1,0,1,1,0,1,0,0], the value of num It is the decimal number of [1,0,1,1,0,1,0,0], which is also the original mode feature of the pixel

Calculating its eigenvalue directly here can improve the speed of code operation

3. Draw a histogram

def show_hist(self, img_array, im_bins, im_range):
    # 直方图的x轴是灰度值,y轴是图片中具有同一个灰度值的点的数目, [img_array]原图像图像格式为uint8或float32,[0]0表示灰度,None无掩膜
    hist = cv2.calcHist([img_array], [0], None, im_bins, im_range)
    hist = cv2.normalize(hist, hist).flatten()  # 对计算出来的直方图数据进行归一化处理,并将结果扁平化为1D数组
    # print(hist)
    plt.plot(hist, color='r')
    plt.xlim(im_range)  # 设置X轴的取值范围
    plt.show()

4. Complete code

import numpy as np
import cv2
from PIL import Image
from pylab import *

class LBP:

    # 图像的LBP原始特征计算算法:将图像指定位置的像素与周围8个像素比较
    # 比中心像素大的点赋值为1,比中心像素小的赋值为0,返回得到的二进制序列
    def calute_basic_lbp(self, image_array, i, j):
        sum = []
        num = 0
        if image_array[i - 1, j - 1] > image_array[i, j]:
            sum.append(1)
            num += 2**0
        else:
            sum.append(0)
        if image_array[i - 1, j] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 1
        else:
            sum.append(0)
        if image_array[i - 1, j + 1] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 2
        else:
            sum.append(0)
        if image_array[i, j - 1] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 3
        else:
            sum.append(0)
        if image_array[i, j + 1] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 4
        else:
            sum.append(0)
        if image_array[i + 1, j - 1] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 5
        else:
            sum.append(0)
        if image_array[i + 1, j] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 6
        else:
            sum.append(0)
        if image_array[i + 1, j + 1] > image_array[i, j]:
            sum.append(1)
            num += 2 ** 7
        else:
            sum.append(0)
        return sum,num

    # 获取图像的LBP原始模式特征
    def lbp_basic(self, image_array):
        basic_array = np.zeros(image_array.shape, np.uint8)
        width = image_array.shape[0]
        height = image_array.shape[1]
        for i in range(1, width - 1):
            for j in range(1, height - 1):
                sum = self.calute_basic_lbp(image_array, i, j)[1]
                basic_array[i, j]=sum
        return basic_array

    # 绘制指定维数和范围的图像灰度归一化统计直方图
    def show_hist(self, img_array, im_bins, im_range):
        # 直方图的x轴是灰度值,y轴是图片中具有同一个灰度值的点的数目, [img_array]原图像图像格式为uint8或float32,[0]0表示灰度,None无掩膜
        hist = cv2.calcHist([img_array], [0], None, im_bins, im_range)
        hist = cv2.normalize(hist, hist).flatten()  # 对计算出来的直方图数据进行归一化处理,并将结果扁平化为1D数组
        # print(hist)
        plt.plot(hist, color='r')
        plt.xlim(im_range)  # 设置X轴的取值范围
        plt.show()

    # 绘制图像原始LBP特征的归一化统计直方图
    def show_basic_hist(self, img_array):
        self.show_hist(img_array, [256], [0, 256])

    # 显示图像
    def show_image(self, image_array):
        plt.imshow(image_array, cmap='Greys_r')
        plt.show()

if __name__ == '__main__':
    image = cv2.imread('F:/in_picture/001.png')
    image_array = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    lbp = LBP()
    plt.imshow(image_array, cmap='Greys_r')  # 去掉参数就是热量图了
    plt.title('Original')
    plt.show()

    # 获取图像原始LBP特征,并显示其统计直方图与特征图像
    basic_array = lbp.lbp_basic(image_array)
    lbp.show_image(basic_array)
    lbp.show_basic_hist(basic_array)



3. Summary

        The extraction of LBP original mode features is relatively simple and crude, and does not involve very complicated algorithms, that is, the overall algorithm may need to be optimized, or it can increase the running speed, improve the readability and portability of the code

If there is any mistake, please correct me!

Guess you like

Origin blog.csdn.net/qq_66036911/article/details/130328352