具有Python&OpenCV的本地二进制模式
具有Python&OpenCV的本地二進制模式
- 1. 效果圖
- 2. 原理
- 2.1 項目結構
- 2.2 數據集構建
- 2.3 什么是本地二進制模式?
- 3. 源碼
- 參考
這篇博客將介紹如何使用本地二進制模式圖像描述符(以及一點機器學習)來自動分類和識別圖像中的紋理和模式(例如包裝紙,蛋糕糖霜或蠟燭的紋理/模式)。
1. 效果圖
效果圖如下:能準確的識別出筆記本封面、桌布、地毯、鍵盤 四種紋理不同的物品;
四種不同類型紋理的LBP圖與識別圖如下:
可以看到紋理還是有極大的不同的~
2. 原理
2.1 項目結構
2.2 數據集構建
隨手拿起了相機,拍了觸手可及的桌布、鍵盤、筆記本封面、地毯4種紋理不同的照片各5張;
2.3 什么是本地二進制模式?
本地二進制模式LBPS,是由Ojala等人的工作流行的紋理描述符。
與Haralick紋理功能不同,Haralick紋理功能:基于灰度級共發生矩陣計算紋理的全局表示。而LBPS只計算紋理的局部表示,通過將每個像素與其周圍的像素鄰域進行比較來構造該本地表示。
構建LBP紋理描述符的第一步是將圖像轉換為灰度。對于灰度圖像中的每個像素,我們選擇圍繞中心像素的R個附近像素。然后計算該中心像素的LBP值,并存儲在輸出2D陣列中,其寬度和高度與輸入圖像相同。
將中心像素(以紅色突出顯示)并抵靠其鄰近8像素的鄰居。如果中心像素的強度大于或等于其鄰居,則將值設置為1;否則,將其設置為0。周圍像素8個,總共有2 ^ 8 = 256個可能的LBP代碼組合。
從右上角開始,順時針0~7,將二進制值轉換為十進制值,并填在中心像素值上。
然后對輸入圖像中的每個像素重復該閾值,累積二進制字符串和存儲LBP陣列中的輸出十進制值的過程。
最后一步是在輸出LBP數組上計算直方圖。由于3×3鄰域有2 ^ 8 = 256可能的模式,因此LBP 2D陣列具有0的最小值為0和最大值為255,允許將其作為最終特征向量構建LBP代碼的256箱直方圖:
這個原始LBP實施的主要好處是可以在圖像中捕獲極其細粒度的細節。但是,能夠以這樣的小規模捕獲細節也是算法的最大缺點——無法以不同的尺度捕獲細節,只有固定的3 x 3刻度!
為了處理這一點,Ojala等人提出了對原始LBP實施的擴展。處理變量鄰域大小。要考慮可變鄰域大小,介紹了兩個參數:
- 循環對稱鄰域中的點P的數量(從而消除依賴于方形鄰域)。
- 圓圈R的半徑,這使我們能夠考慮不同的尺度。
可變鄰域大小示例:
那么為什么統一的LBP模式如此有趣?簡單地說:它們增加了額外的旋轉級別和灰度不變性,因此在從圖像中提取LBP功能向量時通常使用它們。
本地二進制模式LBPS實現可以在Scikit-Image和Mahotas封裝中找到。 OpenCV還實現了LBP,但未公布源碼。通常建議使用Lbps的Scikit-Image實現,因為其提供了更多控制要生成的LBP直方圖類型。此外,Scikit-Image實現還包括LBP的變體,可提高旋轉和灰度不變性。
3. 源碼
# USAGE
# python recognize.py --training images/training --testing images/testingimport argparse
import osimport cv2
import imutils
from imutils import paths
# 導入必要的包
from pyimagesearch.localbinarypatterns import LocalBinaryPatterns
from sklearn.svm import LinearSVC# 構建命令行參數及解析
# --training 用于訓練模型的圖像 4*4 =16
# --testing 用于測試模型的圖像 4*1 =4
ap = argparse.ArgumentParser()
ap.add_argument("-t", "--training", required=True,help="path to the training images")
ap.add_argument("-e", "--testing", required=True,help="path to the tesitng images")
args = vars(ap.parse_args())# 初始化本地二進制描述符類,data和類標簽list
desc = LocalBinaryPatterns(24, 8)
data = []
labels = []# 遍歷訓練集圖片
for imagePath in paths.list_images(args["training"]):# 加載圖像,轉換灰度圖,提取本地二進制模式image = cv2.imread(imagePath)image = imutils.resize(image, width=400)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)hist = desc.describe(gray)# 從圖像路徑中提取類標簽,更新data和圖像類標簽labels.append(imagePath.split(os.path.sep)[-2])data.append(hist)# 在數據上訓練線性SVM分類器
model = LinearSVC(C=100.0, random_state=42)
model.fit(data, labels)# 測試分類器的性能和準確性
# 遍歷測試數據集
for imagePath in paths.list_images(args["testing"]):# 加載圖像,轉換灰度圖,提取分類本地二進制描述符即紋理image = cv2.imread(imagePath)image = imutils.resize(image, width=400)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)hist = desc.describe(gray, imagePath)prediction = model.predict(hist.reshape(1, -1))# 展示圖像和預測結果cv2.putText(image, prediction[0], (10, 30), cv2.FONT_HERSHEY_SIMPLEX,1.0, (0, 0, 255), 3)cv2.imshow("Image " + str(imagePath), image)cv2.waitKey(0)
參考
- https://www.pyimagesearch.com/2015/12/07/local-binary-patterns-with-python-opencv/
總結
以上是生活随笔為你收集整理的具有Python&OpenCV的本地二进制模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python写的代码打包成.exe可执行
- 下一篇: 用代码优雅的终止springboot服务