Local Binary Patterns(LBP) 是一種用來描述圖像紋理的特徵提取技術。LBP 對於檢測表面紋理的異常具有很好的效果,尤其在檢測紋理一致的材料表面(例如紡織品、紙張、金屬)時,LBP 非常有用。LBP 的優勢在於它的計算效率高,並且對光照變化不敏感。
LBP 是基於局部像素的灰度值來描述紋理的,通過比較中心像素與其鄰域像素的大小關係,將鄰域像素的比較結果轉換為二進制數,並將這些二進制數轉換成一個整數值來表徵該像素的紋理。
P
個鄰域像素,形成一個環(通常是 8 個像素),半徑為 R
。local_binary_pattern(image, n_points, radius, method='uniform')
中的參數,這裡是每個參數的詳細說明:
n_points
決定參與比較的鄰域像素數。radius
決定鄰域的範圍。method
選擇 LBP 模式,其中 uniform
模式減少了特徵數量,適合大多數應用。8 * radius
,即圍繞中心像素的 n_points
個鄰域點會參與比較。增加這個數量可以使 LBP 更加敏感於大範圍的紋理變化。1, 2, 3
等。'uniform'
表示使用統一模式(Uniform Pattern)。統一模式是指當 LBP 模式中的 0 和 1 之間的轉換次數不超過兩次時,該模式被稱為「統一」。統一模式能夠減少 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()
radius
) 和鄰域像素 (n_points
):決定紋理感知範圍。