導? 讀
????本文主要介紹使用YOLOv8圖像分割實現路面坑洞檢測(步驟 + 代碼)。??
背 景
????如上圖所示,現實生活中路面坑洞對車輛和駕駛員安全來說存在巨大隱患,本文將介紹如何使用YoloV8圖像分割技術來檢測路面坑洞,從而提示駕駛員注意避讓,盡可能保證安全。
??
實現步驟
? ??【1】準備數據集。
????本教程中使用Pothole圖像分割數據集。獲取坑洼圖像分割數據集。您可以從?Kaggle?訪問它,這是一個流行的數據科學競賽、數據集和機器學習資源平臺。數據集下載鏈接:
https://www.kaggle.com/datasets/farzadnekouei/pothole-image-segmentation-dataset
????下載數據集后,如果數據集已打包,您可能需要從壓縮格式(例如 ZIP 或 TAR 文件)中提取文件。
? ??【2】安裝Ultralytics,導入必要的庫。
????安裝Ultralytics:
pip?install?ultralytics
????導入必要的庫:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
import warnings
from ultralytics import YOLO
import cv2
from PIL import Image
import yaml
import random
? ??【3】設置數據路徑。
dataDir = '/content/Pothole_Segmentation_YOLOv8/'
? ??dataDir目錄路徑“/content/Pothole_Segmentation_YOLOv8/”的變量。該變量表示存儲圖像分割任務的數據集的目錄。
? ??【4】加載并繪制圖像。???????
trainImagePath = os.path.join(dataDir, 'train','images')
#list of the images
imageFiles = [f for f in os.listdir(trainImagePath) if f.endswith('.jpg')]
randomImages = random.sample(imageFiles, 15)
plt.figure(figsize=(10, 10))
for i, image_file in enumerate(randomImages):
image_path = os.path.join(trainImagePath, image_file)
image = Image.open(image_path)
plt.subplot(3, 5, i + 1)
plt.imshow(image)
plt.axis('off')
# Add a suptitle
plt.suptitle('Random Selection of Dataset Images', fontsize=24)
# Show the plot
plt.tight_layout()
plt.show()
????設置訓練圖像路徑:
??? trainImagePath = os.path.join(dataDir, 'train','images'):此行構造包含訓練圖像的目錄的路徑。它使用該os.path.join()函數將基本目錄路徑 ( dataDir) 與存儲訓練圖像的子目錄“train”和“images”連接起來。
????列出圖像文件:
??? imageFiles = [f for f in os.listdir(trainImagePath) if f.endswith('.jpg')]:此行在目錄中創建圖像文件列表trainImagePath。它使用列表理解來迭代目錄中的文件,并僅過濾那些以“.jpg”擴展名結尾的文件。
????選擇隨機圖像:
??? randomImages = random.sample(imageFiles, 15):此行從上一步使用該函數獲得的圖像文件列表中隨機選擇 15 個圖像random.sample()。
????繪制圖像:
-
-
以下代碼行迭代隨機選擇的圖像,使用?PIL?( Image.open()) 打開每個圖像,然后用于matplotlib.pyplot創建顯示所選圖像的子圖網格。
-
該plt.subplot()函數用于定位網格中的每個圖像。
-
plt.imshow()在子圖中顯示圖像。
-
plt.axis('off')刪除軸標簽以獲得更清晰的可視化效果。
-
????添加標題并顯示繪圖:
??? plt.suptitle('Random Selection of Dataset Images', fontsize=24):為整個情節添加標題。
??? plt.tight_layout()調整子圖的布局以防止重疊。
??? plt.show()顯示情節。
隨機選擇數據集圖像
? ??【5】下載并訓練YoloV8分割模型。
model = YOLO('yolov8n-seg.pt')
????加載預訓練權重:'yolov8n-seg.pt'傳遞給 YOLO 構造函數指定 YOLOv8n 模型預訓練權重的文件路徑。這些權重對于使用訓練過程中學到的參數初始化神經網絡至關重要。
yamlFilePath = os.path.join(dataDir,'data.yaml' )
??? yamlFilePath = os.path.join(dataDir,'data.yaml')用于構造名為 的 YAML 文件的文件路徑data.yaml。???????
results = model.train(
data= yamlFilePath,
epochs= 30 ,
imgsz= 640 ,
batch= 32 ,
optimizationr= 'auto' ,
lr0= 0.0001 , # 初始學習率
lrf= 0.01 , # 最終學習率 (lr0 * lrf)
?????dropout?=?0.25?,???????????#?使用?dropout?正則化
device= 0 , # 運行的設備,即 cuda device=0
seed= 42
)
????開始 YOLOv8 圖像分割模型的訓練過程。讓我們分解一下傳遞給該model.train()方法的參數:
-
data:此參數指定 YAML 文件 ( ) 的路徑,yamlFilePath其中包含配置設置和有關用于訓練的數據集的信息。YAML 文件可能包含圖像文件路徑、注釋文件、類名等詳細信息。
-
epochs:該參數決定訓練過程中的 epoch 數(完整遍歷整個數據集)。在我們的例子中,模型將訓練 30 個?epoch。
-
imgsz:該參數指定訓練時模型的輸入圖像大小。圖像在輸入網絡之前可能會調整為 640x640 像素。
-
batch:該參數設置訓練期間使用的批量大小。它確定在訓練過程的每次迭代中同時處理的圖像數量。這里使用的批量大小為 32。
-
optimizer:該參數指定用于訓練模型的優化器。該值'auto'表明訓練過程會根據模型架構或其他設置自動選擇優化器。
-
lr0:該參數設置優化器的初始學習率。指定學習率為 0.0001,這是許多優化任務的常見起始值。
-
lrf:該參數指定最終學習率,其計算方式為初始學習率乘以lrf。它有助于在訓練過程中逐漸降低學習率以穩定學習過程。
-
dropout:該參數指定 dropout 率,這是一種用于防止訓練期間過度擬合的正則化技術。丟棄率為 0.25 表示在每次訓練迭代期間將隨機丟棄 25% 的神經元。
-
device:此參數指定模型將在其上進行訓練的設備。值0通常表示在第一個 CUDA 設備 (GPU) 上進行訓練(如果可用),否則將使用 CPU。
-
seed:此參數設置用于訓練期間再現性的隨機種子。設置固定種子可確保每次執行代碼時生成相同的隨機數序列,這對于調試和結果再現性很有用。
? ??【6】加載性能最佳的模型。???????
bestModelpath = '/content/runs/segment/train/weights/best.pt'
bestModel = YOLO(bestModelpath)
-
-
bestModelpath:該變量包含訓練期間獲得的最佳模型的文件路徑。
-
'/content/runs/segment/train/weights/best.pt':該字符串指定包含最佳模型權重的文件的路徑。
-
? ??【7】加載圖像做推理。???????
validImagePath = os.path.join(dataDir, 'valid', 'images')
imageFiles = [f for f in os.listdir(validImagePath) if f.endswith('.jpg')]
#select Random images
numImages = len(imageFiles)
selectedImage = [imageFiles[i] for i in range(0, numImages, numImages // 9)]
fig, axes = plt.subplots(3, 3, figsize=(10, 10))
fig.suptitle('Validation Set Inferences')
for i, ax in enumerate(axes.flatten()):
imagePath = os.path.join(validImagePath, selectedImage[i])
results = bestModel.predict(source= imagePath, imgsz=640)
annotatedImage = results[0].plot()
annotatedImageRGB = cv2.cvtColor(annotatedImage, cv2.COLOR_BGR2RGB)
ax.imshow(annotatedImageRGB)
ax.axis('off')
plt.tight_layout()
plt.show()
????使用訓練期間獲得的最佳模型對驗證圖像集進行推斷。
????設置驗證圖像路徑:
-
-
validImagePath = os.path.join(dataDir, 'valid', 'images'):此行構造包含驗證圖像的目錄的路徑。
-
????列出驗證圖像文件:
-
-
imageFiles = [f for f in os.listdir(validImagePath) if f.endswith('.jpg')]:此行在目錄中創建圖像文件列表validImagePath。
-
????選擇隨機圖像:
-
-
numImages = len(imageFiles):此行計算驗證集中的圖像總數。
-
selectedImage = [imageFiles[i] for i in range(0, numImages, numImages // 9)]:此行從驗證集中選擇圖像的子集。似乎通過將圖像總數 ( numImages) 除以 9 來選擇 9 個圖像。
-
????繪制推斷圖像:
-
-
然后,代碼繼續使用 來創建 3x3 子圖網格plt.subplots()。整個圖的標題設置為“驗證集推斷”,使用fig.suptitle().
-
它使用 迭代子圖enumerate(axes.flatten()),其中每個子圖代表驗證集中的一個圖像。
-
對于每個子圖,它使用 加載相應的圖像os.path.join(validImagePath, selectedImage[i]),使用 方法執行推理bestModel.predict(),并使用 繪制帶注釋的圖像results[0].plot()。
-
OpenCV的cv2.cvtColor()函數用于將帶注釋的圖像從BGR轉換為RGB格式,適合用Matplotlib顯示。
-
最后,它使用 隱藏每個子圖的軸ax.axis('off')。
-
? ??【8】加載視頻做推理。???????????
import shutil
videoPath = '/content/Pothole_Segmentation_YOLOv8/sample_video.mp4'
bestModel.predict(source=videoPath, save=True)
??????????????
import subprocess
# Convert AVI to MP4 using FFmpeg
subprocess.call(['ffmpeg', '-y', '-loglevel', 'panic', '-i', '/content/runs/segment/predict/sample_video.avi', 'output_video.mp4'])
from IPython.display import Video
# Display the converted MP4 video
Video("output_video.mp4", embed=True, width=960)
????結論:
????當我們結束使用 YOLOv8 的圖像分割迷人世界的旅程時,我們發現自己配備了新的見解、技能和可能性。在整個項目中,我們從數據管理到模型訓練、推理和評估,揭示了圖像分割的復雜性及其在計算機視覺中的變革潛力。
—THE END—