本項目旨在開發一個集車道檢測與物體檢測功能于一體的智能視覺分析系統,利用先進的計算機視覺技術和深度學習模型,實現實時的道路場景理解和目標識別。系統主要依托OpenCV這一強大的計算機視覺庫,以及Python作為編程語言,融合了車道檢測算法和YOLO(You Only Look Once)物體檢測算法,以期達到高效、精準的視覺分析效果。
1. 車道檢測
車道檢測部分主要采用基于圖像處理的技術,具體步驟包括:
-
預處理:對輸入的圖像進行灰度化、高斯模糊、Canny邊緣檢測等操作,以增強圖像的對比度和減少噪聲干擾。
-
興趣區域提取:通過多邊形掩模,只保留包含車道線的區域,忽略無關背景。
-
霍夫變換:利用霍夫直線變換檢測車道線,將邊緣圖像轉換到參數空間,尋找直線的參數。
-
后處理:對檢測到的車道線進行擬合和平滑,確保車道線的連續性和準確性。
2. 物體檢測(YOLO)
YOLO算法是一種實時的目標檢測框架,其核心特點是在一次前向傳播中同時預測物體的位置和類別,大幅提高了檢測速度。本項目中,我們采用YOLOv4或YOLOv5作為基礎模型,針對特定場景進行微調和優化,以提高檢測精度和泛化能力。
實現流程
-
數據準備:收集大量的道路場景圖像和視頻,包括不同天氣、光照條件下的樣本,進行標注,構建訓練數據集。
-
模型訓練:使用標注好的數據集,訓練車道檢測模型和YOLO模型,調整超參數,優化模型性能。
-
系統集成:將車道檢測和物體檢測兩個子系統整合到一起,設計合理的輸入輸出接口,確保兩者的無縫協作。
-
測試與評估:在多種場景下測試系統性能,包括但不限于城市街道、高速公路、夜間環境等,評估檢測精度、實時性和穩定性。
-
部署與優化:根據實際應用需求,將系統部署到目標平臺,如自動駕駛車輛、監控系統等,并持續收集反饋,進行迭代優化。
應用前景
本項目成果可廣泛應用于智能交通、自動駕駛、安防監控等領域,為實現更加安全、高效的交通系統提供技術支持。例如,在自動駕駛車輛中,車道檢測與物體檢測的結合可以幫助車輛實時理解周圍環境,做出準確的決策;在城市監控系統中,則能輔助警察和安保人員快速識別異常情況,提升公共安全水平。
結語
通過融合車道檢測與物體檢測兩大核心技術,本項目致力于打造一個全面、智能的視覺分析系統,推動計算機視覺技術在實際應用中的創新與發展。
關鍵代碼部分
import numpy as np
import cv2
from utils import *
import os
import time
import argparseparser = argparse.ArgumentParser()
parser.add_argument('--model_cfg', type = str, default = '',help = 'Path to config file')
parser.add_argument('--model_weights', type=str,default='',help='path to weights of model')
parser.add_argument('--video', type=str, default='',help='path to video file')
parser.add_argument('--src', type=int, default=0,help='source of the camera')
parser.add_argument('--output_dir', type=str, default='',help='path to the output directory')
args = parser.parse_args()# print the arguments
print('----- info -----')
print('[i] The config file: ', args.model_cfg)
print('[i] The weights of model file: ', args.model_weights)
print('[i] Path to video file: ', args.video)
print('###########################################################\n')
frameWidth= 640
frameHeight = 480net = cv2.dnn.readNet(args.model_weights, args.model_cfg)
classes = []
with open("coco.names", "r") as f:classes = [line.strip() for line in f.readlines()] # we put the names in to an arraylayers_names = net.getLayerNames()
output_layers = [layers_names[i[0] -1] for i in net.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size = (len(classes), 3))font = cv2.FONT_HERSHEY_PLAIN
frame_id = 0
cameraFeed= False
#videoPath = 'road_car_view.mp4'
cameraNo= 1
#frameWidth= 640
#frameHeight = 480if cameraFeed:intialTracbarVals = [24,55,12,100] # #wT,hT,wB,hB
else:intialTracbarVals = [42,63,14,87] #wT,hT,wB,hBoutput_file = ''
if cameraFeed:cap = cv2.VideoCapture(cameraNo)cap.set(3, frameWidth)cap.set(4, frameHeight)
else:cap = cv2.VideoCapture(args.video)output_file = args.video[:-4].rsplit('/')[-1] + '_Detection.avi'
count=0
noOfArrayValues =10
#global arrayCurve, arrayCounter
arrayCounter=0
arrayCurve = np.zeros([noOfArrayValues])
myVals=[]
initializeTrackbars(intialTracbarVals)#fourcc = cv2.VideoWriter_fourcc(*'XVID')
#video_writer = cv2.VideoWriter('output.avi', fourcc, 20.0, (640,480))
video_writer = cv2.VideoWriter('output2.avi', cv2.VideoWriter_fourcc(*'XVID'), cap.get(cv2.CAP_PROP_FPS), (2 * frameWidth,frameHeight))
starting_time = time.time()
while True:success, img = cap.read()if not success:print('[i] ==> Done processing!!!')print('[i] ==> Output file is stored at', os.path.join(args.output_dir, output_file))cv2.waitKey(1000)break#img = cv2.imread('test3.jpg')if cameraFeed== False:img = cv2.resize(img, (frameWidth, frameHeight), None)imgWarpPoints = img.copy()imgFinal = img.copy()imgCanny = img.copy()imgUndis = undistort(img)imgThres,imgCanny,imgColor = thresholding(imgUndis)src = valTrackbars()imgWarp = perspective_warp(imgThres, dst_size=(frameWidth, frameHeight), src=src)imgWarpPoints = drawPoints(imgWarpPoints, src)imgSliding, curves, lanes, ploty = sliding_window(imgWarp, draw_windows=True)try:curverad =get_curve(imgFinal, curves[0], curves[1])lane_curve = np.mean([curverad[0], curverad[1]])imgFinal = draw_lanes(img, curves[0], curves[1],frameWidth,frameHeight,src=src)# AveragecurrentCurve = lane_curve // 50if int(np.sum(arrayCurve)) == 0:averageCurve = currentCurveelse:averageCurve = np.sum(arrayCurve) // arrayCurve.shape[0]if abs(averageCurve-currentCurve) >200: arrayCurve[arrayCounter] = averageCurveelse :arrayCurve[arrayCounter] = currentCurvearrayCounter +=1if arrayCounter >=noOfArrayValues : arrayCounter=0cv2.putText(imgFinal, str(int(averageCurve)), (frameWidth//2-70, 70), cv2.FONT_HERSHEY_DUPLEX, 1.75, (0, 0, 255), 2, cv2.LINE_AA)except:lane_curve=00passimgFinal= drawLines(imgFinal,lane_curve)# Object detection success, frame = cap.read()frame = cv2.resize(frame, (frameWidth, frameHeight), None)frame_id += 1height, width, channels = frame.shape# Detect imageblob = cv2.dnn.blobFromImage(frame, 0.00392, (320, 320), (0,0,0), swapRB = True, crop = False)net.setInput(blob)start = time.time()outs = net.forward(output_layers)# Showing informations on the screenclass_ids = []confidences = []boxes = []for out in outs:for detection in out:scores = detection[5:]class_id = np.argmax(scores)confidence = scores[class_id]if confidence > 0.5:#Object detectedcenter_x = int(detection[0] * width)center_y = int(detection[1] * height)w = int(detection[2] * width)h = int(detection[3] * height)# Rectangle coordinatesx = int(center_x - w / 2)y = int(center_y -h / 2)#cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0))boxes.append([x, y, w, h])confidences.append(float(confidence))# Name of the objectclass_ids.append(class_id)indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)for i in range(len(boxes)):if i in indexes:x, y, w, h = boxes[i]label = "{}: {:.2f}%".format(classes[class_ids[i]], confidences[i]*100)color = colors[i]cv2.rectangle(frame, (x,y), (x+w, y+h), color, 2)cv2.putText(frame, label, (x,y+10), font, 2, color, 2)elapsed_time = time.time() - starting_timefps = frame_id / elapsed_timecv2.putText(frame, "FPS:" + str(fps), (10,30), font, 2, (0, 0, 0), 1)imgBlank = np.zeros_like(img)imgStacked = stackImages(0.7, ([imgUndis,frame],[imgColor, imgCanny],[imgWarp,imgSliding]))#final_frame = cv2.hconcat((frame,imgCanny))#video_writer.write(final_frame)#cv2.imshow('frame',final_frame)cv2.imshow("Image", frame)cv2.imshow("PipeLine",imgStacked)cv2.imshow("Result", imgFinal)
識別道路邊界的過程,即道路檢測管道,主要包括以下步驟:
-
相機校準矩陣計算:首先,使用OpenCV庫中的
cv2.findChessboardCorners()
函數計算相機的校準矩陣,以消除由鏡頭產生的畸變。這一校準步驟確保了車道檢測算法能夠適應不同類型的相機,提高算法的通用性。校準后,將校準矩陣應用于原始圖像,進行畸變校正。 -
圖像邊緣檢測與閾值處理:接著,通過一組基于梯度和顏色的閾值處理技術,使用
cv2.Sobel
和cv2.cvtColor
函數檢測圖像中的邊緣,生成二值化的邊緣圖像。這一步驟有助于突出圖像中的車道線條,為后續的車道邊界識別奠定基礎。 -
透視變換:為了更方便地提取車道邊界,接下來會對處理后的圖像進行透視變換,將其轉換為鳥瞰視角。這種變換使得車道邊界在圖像中呈現出更為直觀和易于識別的形式。
-
車道像素掃描與擬合:在鳥瞰圖的基礎上,系統會掃描整個圖像,尋找屬于車道邊界的像素點。找到足夠的像素點后,通過曲線擬合算法將它們擬合成車道邊界。之后,再將檢測到的車道邊界反向映射回原始圖像中,實現車道的可視化標識。
-
道路屬性估算:最后,系統還會估算一些重要的道路屬性,比如道路的曲率以及車輛在車道內的相對位置。這些信息對于自動駕駛車輛來說至關重要,能夠幫助車輛更好地理解自身在道路上的位置和方向。
整個過程的快照可以這樣描述:從原始圖像開始,經過一系列精心設計的圖像處理步驟,最終在圖像中標記出清晰的車道邊界,并提供關于道路狀況的關鍵信息。這一系列操作構成了一個高效、準確的道路邊界識別系統,是實現自動駕駛和智能交通系統的重要組成部分。