LBP学習記(1) --- オリジナルモード機能の詳細解説(コード実装)

1. LBP オペレーターと LBP オリジナルモードの簡単な説明

        LBP (ローカル バイナリ パターン) オペレーターは、1994 年に T.Ojala、M.Pietikäinen、D.Harwood によって提案された、テクスチャ記述のためのローカル画像特徴です。LBP オペレーターは、画像内の各ピクセルを周囲の近傍ピクセルと比較し、グレー値が中心ピクセル以上である近傍ピクセルの数を数え、統計結果をバイナリ コードに変換してピクセルの局所的特徴を表します。 。

        LBP オペレータは、グレースケール不変性と回転不変性の利点を持ち、高速に計算できるため、顔認識、テクスチャ分類、歩行者検出などの分野で広く使用されています。LBP 演算子の改良に基づいて、回転不変 LBP やマルチスケール LBP などのアルゴリズムも次々と提案されています。

        LBP オリジナル モードとは、LBP 演算子において、各ピクセルのバイナリ コードにはそれ自体が含まれず、周囲の 8 つの隣接ピクセルのうち、その強度値以上のピクセルの総数がカウントされ、これらのピクセルがカウントされることを意味します。ピクセルはバイナリ コード (8 ビットの 2 進数に対応) として保存され、最終的なバイナリ コードがピクセルの LBP オリジナル モードになります。3*3 近傍内のピクセルのセットには、256 の異なる LBP モードがあります (すべて 0 およびすべて 1 モードを含む)。

        LBP オリジナルモードは LBP 演算子の最も基本的な形式で、顔認識、テクスチャ分類などの分野で広く使用されています。LBP オペレーターは、グレー不変性と回転不変性という利点があり、高速に計算できるため、シンプルで効果的なテクスチャ特徴記述子と考えられています。

2. コードの実装 (主要な機能と完全なコード)

1. ピクセルを走査して元のパターンの特徴を取得する

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

まず同じサイズのすべて 0 の行列を作成し、画像から外側の円を削除してから走査を開始します。元のモード特徴を取得した後、作成したばかりの行列の対応する位置に割り当てて、行列を返します。

2. 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

このピクセル値と遭遇したピクセルの 8 つの近傍の 8 つのピクセル値を比較し、それが大きければ 1、それ以外の場合は 0 になります。

合計リストは、ピクセルの左上隅とそのピクセルである中央のピクセルから時計回りに8つのピクセル値の比較結果を格納し、[0,0,1,0, 1,1,0,1]

num は、合計を 180 度回転した後の 10 進数です。例: sum=[0,0,1,0,1,1,0,1] の場合、sum は 180 度回転されて [1,0,1,1,0,1,0,0] になります。 of num [1,0,1,1,0,1,0,0] の 10 進数であり、ピクセルの元のモード機能でもあります。

ここで固有値を直接計算すると、コード操作の速度が向上します。

3. ヒストグラムを描く

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. 完全なコード

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. まとめ

        LBP オリジナル モードの特徴の抽出は比較的単純かつ大まかであり、非常に複雑なアルゴリズムは必要ありません。つまり、アルゴリズム全体を最適化する必要がある場合があり、そうしないと、実行速度が向上し、コードの可読性と移植性が向上します。

間違いがあれば修正してください!

おすすめ

転載: blog.csdn.net/qq_66036911/article/details/130328352