2024-10-23|閱讀時間 ‧ 約 0 分鐘

[OpenCV][Python]使用 LBP(Local Binary Patterns)進行紋理分析和瑕疵檢測

使用 LBP(Local Binary Patterns) 進行紋理分析和瑕疵檢測

Local Binary Patterns(LBP) 是一種用來描述圖像紋理的特徵提取技術。LBP 對於檢測表面紋理的異常具有很好的效果,尤其在檢測紋理一致的材料表面(例如紡織品、紙張、金屬)時,LBP 非常有用。LBP 的優勢在於它的計算效率高,並且對光照變化不敏感。

實驗圖

raw-image


結果圖

1. LBP 的基本概念

LBP 是基於局部像素的灰度值來描述紋理的,通過比較中心像素與其鄰域像素的大小關係,將鄰域像素的比較結果轉換為二進制數,並將這些二進制數轉換成一個整數值來表徵該像素的紋理。


運算的步驟可以參考這篇 我覺得在網路看到解釋得很清楚的文章

LBP 運算的步驟:

  • Step 1:對每個像素選擇一個 P 個鄰域像素,形成一個環(通常是 8 個像素),半徑為 R
  • Step 2:比較每個鄰域像素與中心像素的灰度值,如果鄰域像素的灰度值大於或等於中心像素,記為 1,否則記為 0。
  • Step 3:將這些二進制結果組成一個 8 位的二進制數,並將這個二進制數轉換為十進制數,這就是 LBP 值。
  • Step 4:用該 LBP 值替換原來的中心像素,得到一張新的 LBP 紋理圖。




2. LBP 適用場景

  • 紋理分析:LBP 被廣泛用於紋理分析和分類,尤其在表面檢測中,LBP 能夠有效檢測到紋理的細微變化。
  • 瑕疵檢測:當表面的紋理一致性很高時(例如布料、紙張),LBP 能檢測到表面不規則的紋理變化,如異常的斑點或凹凸不平的瑕疵。
  • 人臉識別:LBP 也被應用於人臉識別系統,通過提取人臉的紋理特徵進行分類。


3. LBP 的優勢

  • 簡單高效:LBP 的計算過程相對簡單,對於實時應用來說是高效的。
  • 光照不變性:LBP 對光照變化具有較好的穩健性,因為它主要基於像素之間的比較,而不是絕對灰度值。

函式說明

local_binary_pattern(image, n_points, radius, method='uniform') 中的參數,這裡是每個參數的詳細說明:

  • n_points 決定參與比較的鄰域像素數。
  • radius 決定鄰域的範圍。
  • method 選擇 LBP 模式,其中 uniform 模式減少了特徵數量,適合大多數應用。
  1. image
    這是要應用 LBP 的輸入圖像,通常是灰度圖像(2D numpy 陣列)。LBP 是基於圖像中的像素進行紋理特徵提取的,因此需要輸入灰度圖像。
  2. n_points
    鄰域像素的數量,定義了 LBP 運算時,與中心像素比較的像素數量。它的典型設置是 8 * radius,即圍繞中心像素的 n_points 個鄰域點會參與比較。增加這個數量可以使 LBP 更加敏感於大範圍的紋理變化。
  3. radius
    定義鄰域範圍的半徑,這是從中心像素到鄰域像素的距離。較大的半徑可以捕捉更大範圍的紋理變化,而較小的半徑則專注於更細小的紋理。常用的值包括 1, 2, 3 等。
  4. method='uniform'
    LBP 的模式選擇,'uniform' 表示使用統一模式(Uniform Pattern)。統一模式是指當 LBP 模式中的 0 和 1 之間的轉換次數不超過兩次時,該模式被稱為「統一」。統一模式能夠減少 LBP 特徵的數量,提高特徵的可分性和計算效率。其他可選模式包括:
    • 'default':標準的 LBP 模式,沒有特別的模式簡化。
    • 'ror':旋轉不變的 LBP 模式,對於旋轉的紋理,該模式能夠提供不變性。
    • 'var':變異模式,使用方差來衡量紋理的變化。

4. LBP 的實現與應用

skimage 庫來計算 LBP,並展示如何用 LBP 來檢測瑕疵。

import cv2
import numpy as np
from skimage.feature import local_binary_pattern
import matplotlib.pyplot as plt

# LBP 參數
radius = 2 # 增大半徑以擴展感知範圍
n_points = 8 * radius # 鄰域像素的數量

# 讀取灰度圖像
image_path = 'F:/python/crab/LBP/1111.png' # 替換成你的圖像路徑
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

# 使用高斯濾波來平滑背景紋理
image_smooth = cv2.GaussianBlur(image, (5, 5), 0)

# 計算 LBP 特徵,使用統一模式
lbp = local_binary_pattern(image_smooth, n_points, radius, method='uniform')

# 調整 LBP 的閾值
_, lbp_binary = cv2.threshold(lbp, 0.4 * lbp.max(), 255, cv2.THRESH_BINARY)

# 使用形態學操作清除噪點
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (15, 15))
lbp_clean = cv2.morphologyEx(lbp_binary, cv2.MORPH_OPEN, kernel)

# 畫出輪廓到原始圖像
output_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) # 將灰度圖轉換為彩色以顯示輪廓
# 檢測瑕疵區域的輪廓
contours, _ = cv2.findContours(lbp_clean.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 設置最小面積閾值(根據你的需求調整)
min_area = 1000
# 遍歷所有輪廓
for contour in contours:
area = cv2.contourArea(contour)
if area > min_area: # 如果輪廓面積大於閾值
# 計算輪廓的外接矩形
x, y, w, h = cv2.boundingRect(contour)
# 畫出矩形框
cv2.rectangle(output_image, (x, y), (x + w, y + h), (0, 255, 0), 2)

# 顯示結果
titles = ['Original Image', 'lbp', 'Binary LBP', 'Output with Contours and Rectangles']
images = [image, lbp, lbp_binary, output_image]

plt.figure(figsize=(10, 10)) # 調整窗口大小
for i in range(4):
plt.subplot(2, 2, i + 1)
if i == 3: # 最後一個是彩色圖像
plt.imshow(cv2.cvtColor(images[i], cv2.COLOR_BGR2RGB))
else:
plt.imshow(images[i], cmap='gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])

plt.show()

因應不同狀況可調整的部分

  • LBP 半徑 (radius) 和鄰域像素 (n_points):決定紋理感知範圍。
  • 高斯濾波核大小:決定背景平滑效果。
  • 二值化閾值:影響異常區域的檢測範圍。
  • 形態學結構元素:決定去噪效果及瑕疵形狀的處理。
  • 最小面積閾值:影響檢測瑕疵的最小大小。
  • 矩形框的顏色和厚度:影響可視化的顯示效果。








分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.