日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【教程】opencv-python+yolov3实现目标检测

發(fā)布時間:2025/3/20 python 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【教程】opencv-python+yolov3实现目标检测 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • 【教程】opencv-python+yolov3實現(xiàn)目標檢測
    • 目標檢測概況
      • 目標檢測是?
      • 目標檢測算法?
    • yolov3模型簡介
      • 性能介紹
      • 架構介紹
    • opencv-python實現(xiàn)
      • why opencv?
      • 正文

話說我發(fā)現(xiàn)自己之前辛辛苦苦寫的一篇被人爬了............所以為了應對那種情況,我把自己的博客地址貼上吧...
本博客地址:小塞https://www.cnblogs.com/hesse-summer/

【教程】opencv-python+yolov3實現(xiàn)目標檢測

因為最近的任務有用到目標檢測,所以昨天晚上、今天上午搞了一下,快速地了解了目標檢測這一任務,并且實現(xiàn)了使用opencv進行目標檢測。

網(wǎng)上資料挺亂的,感覺在搜資源上浪費了我不少時間,所以我寫這篇博客,把我這段時間了解到的東西整理起來,供有緣的讀者參考學習。

目標檢測概況

目標檢測是?

目標檢測,粗略來說就是:輸入圖片/視頻,經(jīng)過處理,得到:目標的位置信息(比如左上角和右下角的坐標)、目標的預測類別、目標的預測置信度(confidence)。

拿Faster R-CNN這個算法舉例:輸入一個batch(batch size也可以為1)的圖片或者視頻,網(wǎng)絡直接的outputs是這樣的:
[batchId, classId, confidence, left, top, right, bottom],batchId, classId, confidence, left, top, right, bottom都是標量。
batchId表示這一個batch中,這張圖片的id(也即index),后四個標量即目標的位置信息:左上角像素點和右下角像素點的坐標。

目標檢測算法?

按照歷史脈絡來談:

  • 手工特征提取算法,如VJ、HOG、DPM

  • R-CNN算法(2014),最早的基于深度學習的目標檢測器之一,其結(jié)構是兩級網(wǎng)絡:1)首先需要諸如選擇性搜索之類的算法來提出可能包含對象的候選邊界框;2)然后將這些區(qū)域傳遞到CNN算法進行分類

    R-CNN算法存在的問題是其仿真很慢,并且不是完整的端到端的目標檢測器。

  • Fast R-CNN算法(2014末),對原始R-CNN進行了相當大的改進:提高準確度,并減少執(zhí)行正向傳遞所花費的時間

    但是,該模型仍然依賴于外部區(qū)域搜索算法。

  • faster R-CNN算法(2015),真正的端到端深度學習目標檢測器。刪除了選擇性搜索的要求,而是依賴于
    (1)完全卷積的區(qū)域提議網(wǎng)絡RPN, Region Purpose Network),可以預測對象邊界框和“對象”分數(shù)(量化它是一個區(qū)域的可能性的分數(shù))。
    (2)然后將RPN的輸出傳遞到R-CNN組件以進行最終分類和標記。

  • R-CNN系列算法,都采取了two-stage策略。特點是:雖然檢測結(jié)果一般都非常準確,但仿真速度非常慢,即使是在GPU上也僅獲得5 FPS。

  • one-stage方法有:yolo(2015)、SSD(2015末),以及在這兩個算法基礎上改進的各論文提出的算法。這些算法的基本思路是:均勻地在圖片的不同位置進行密集抽樣,抽樣時可以采用不同尺度和長寬比,然后利用CNN提取特征后直接進行分類與回歸
    整個過程只需要一步,所以其優(yōu)勢是速度快,但是訓練比較困難

  • yolov3(2018)是yolo作者提出的第三個版本(之前還提過yolov2和它們的tinny版本,tinny版本經(jīng)過壓縮更快但是也降低了準確率)。yolov3支持80類物體的目標檢測,完整列表[戳這里]: https://github.com/pjreddie/darknet/blob/master/data/coco.names

  • 時間線:

    yolov3模型簡介

    性能介紹

    首先,套路,yolov3很強大(不強大我用它干啥呢)。速度上,它比 R-CNN 快 1000 倍,比 Fast R-CNN 快 100 倍。檢測準確率上,它不是最準的:YOLOv3-608比 DSSD 更高,接近 FPN。但是它的速度不到后二者的1/3。

    從下圖也可以看出:

    架構介紹

    可以看出,他是一系列卷積、殘差、上采樣組成的。特點在于,它將預測分在三個尺度(Scale)進行(見圖中三個彩色框),也在三個scale分別輸出

    opencv-python實現(xiàn)

    why opencv?

    opencv( 3.4.2+版本)的dnn(Deep Neural Network-DNN)模塊封裝了Darknet框架,這個框架是

    自己寫的,它由封裝了yolo算法。因為這么一層關系,我們可以使用opencv方便地使用yolo的各個版本,而且有數(shù)據(jù)(見下)證明OpenCV的DNN模塊在 CPU的實現(xiàn)速度比使用 OpenML 的 Darknet 快9倍。

    正文

    我會結(jié)合腳本片段講解,給出該腳本的完整代碼,講解。

    引庫

    import numpy as np import cv2 as cv import os import time

    參數(shù):

    yolo_dir = '/home/hessesummer/github/NTS-Net-my/yolov3' # YOLO文件路徑 weightsPath = os.path.join(yolo_dir, 'yolov3.weights') # 權重文件 configPath = os.path.join(yolo_dir, 'yolov3.cfg') # 配置文件 labelsPath = os.path.join(yolo_dir, 'coco.names') # label名稱 imgPath = os.path.join(yolo_dir, 'test.jpg') # 測試圖像 CONFIDENCE = 0.5 # 過濾弱檢測的最小概率 THRESHOLD = 0.4 # 非最大值抑制閾值

    權重文件、配置文件、label名稱的下載地址:

    wget https://pjreddie.com/media/files/yolov3.weights wget https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg wget https://github.com/pjreddie/darknet/blob/master/data/coco.names

    簡單來說:

    過濾弱檢測的最小概率:置信度小于這個值的輸出都不要了;
    非最大值抑制閾值:允許框框重疊的程度(多框框檢測同一個物體),供下面的NMS算法使用,該算法會根據(jù)該值將有重疊的框框合并。值為0時,不允許框框重疊。默認值是0.3。

    詳細來說:

    我沒查。您自己感興趣再了解吧。


    重頭戲1

    # 加載網(wǎng)絡、配置權重 net = cv.dnn.readNetFromDarknet(configPath, weightsPath) ## 利用下載的文件 # print("[INFO] loading YOLO from disk...") ## 可以打印下信息# 加載圖片、轉(zhuǎn)為blob格式、送入網(wǎng)絡輸入層 img = cv.imread(imgPath) blobImg = cv.dnn.blobFromImage(img, 1.0/255.0, (416, 416), None, True, False) ## net需要的輸入是blob格式的,用blobFromImage這個函數(shù)來轉(zhuǎn)格式 net.setInput(blobImg) ## 調(diào)用setInput函數(shù)將圖片送入輸入層# 獲取網(wǎng)絡輸出層信息(所有輸出層的名字),設定并前向傳播 outInfo = net.getUnconnectedOutLayersNames() ## 前面的yolov3架構也講了,yolo在每個scale都有輸出,outInfo是每個scale的名字信息,供net.forward使用 # start = time.time() layerOutputs = net.forward(outInfo) # 得到各個輸出層的、各個檢測框等信息,是二維結(jié)構。 # end = time.time() # print("[INFO] YOLO took {:.6f} seconds".format(end - start)) ## 可以打印下信息

    layerOutputs是二維結(jié)構,第0維代表哪個輸出層,第1維代表各個檢測框。

    其他的我都在注釋里講解了。


    重頭戲2

    # 拿到圖片尺寸 (H, W) = img.shape[:2]

    供下面使用:

    # 過濾layerOutputs # layerOutputs的第1維的元素內(nèi)容: [center_x, center_y, width, height, objectness, N-class score data] # 過濾后的結(jié)果放入: boxes = [] # 所有邊界框(各層結(jié)果放一起) confidences = [] # 所有置信度 classIDs = [] # 所有分類ID# # 1)過濾掉置信度低的框框 for out in layerOutputs: # 各個輸出層for detection in out: # 各個框框# 拿到置信度scores = detection[5:] # 各個類別的置信度classID = np.argmax(scores) # 最高置信度的id即為分類idconfidence = scores[classID] # 拿到置信度# 根據(jù)置信度篩查if confidence > CONFIDENCE:box = detection[0:4] * np.array([W, H, W, H]) # 將邊界框放會圖片尺寸(centerX, centerY, width, height) = box.astype("int")x = int(centerX - (width / 2))y = int(centerY - (height / 2))boxes.append([x, y, int(width), int(height)])confidences.append(float(confidence))classIDs.append(classID)# # 2)應用非最大值抑制(non-maxima suppression,nms)進一步篩掉 idxs = cv.dnn.NMSBoxes(boxes, confidences, CONFIDENCE, THRESHOLD) # boxes中,保留的box的索引index存入idxs

    這里的NMS算法就是前面提到的NMS算法。


    應用檢測結(jié)果,這里是畫出框框。

    # 得到labels列表 with open(labelsPath, 'rt') as f:labels = f.read().rstrip('\n').split('\n')

    供下面使用:

    # 應用檢測結(jié)果 np.random.seed(42) COLORS = np.random.randint(0, 255, size=(len(labels), 3), dtype="uint8") # 框框顯示顏色,每一類有不同的顏色,每種顏色都是由RGB三個值組成的,所以size為(len(labels), 3) if len(idxs) > 0:for i in idxs.flatten(): # indxs是二維的,第0維是輸出層,所以這里把它展平成1維(x, y) = (boxes[i][0], boxes[i][1])(w, h) = (boxes[i][2], boxes[i][3])color = [int(c) for c in COLORS[classIDs[i]]]cv.rectangle(img, (x, y), (x+w, y+h), color, 2) # 線條粗細為2pxtext = "{}: {:.4f}".format(labels[classIDs[i]], confidences[i])cv.putText(img, text, (x, y-5), cv.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) # cv.FONT_HERSHEY_SIMPLEX字體風格、0.5字體大小、粗細2px cv.imshow('目標檢測結(jié)果', img) cv.waitKey(0)

    第一部分講解結(jié)束,下面放完整代碼:

    import numpy as np import cv2 as cv import os import timeyolo_dir = '/home/hessesummer/github/NTS-Net-my/yolov3' # YOLO文件路徑 weightsPath = os.path.join(yolo_dir, 'yolov3.weights') # 權重文件 configPath = os.path.join(yolo_dir, 'yolov3.cfg') # 配置文件 labelsPath = os.path.join(yolo_dir, 'coco.names') # label名稱 imgPath = os.path.join(yolo_dir, 'test.jpg') # 測試圖像 CONFIDENCE = 0.5 # 過濾弱檢測的最小概率 THRESHOLD = 0.4 # 非最大值抑制閾值# 加載網(wǎng)絡、配置權重 net = cv.dnn.readNetFromDarknet(configPath, weightsPath) # # 利用下載的文件 print("[INFO] loading YOLO from disk...") # # 可以打印下信息# 加載圖片、轉(zhuǎn)為blob格式、送入網(wǎng)絡輸入層 img = cv.imread(imgPath) blobImg = cv.dnn.blobFromImage(img, 1.0/255.0, (416, 416), None, True, False) # # net需要的輸入是blob格式的,用blobFromImage這個函數(shù)來轉(zhuǎn)格式 net.setInput(blobImg) # # 調(diào)用setInput函數(shù)將圖片送入輸入層# 獲取網(wǎng)絡輸出層信息(所有輸出層的名字),設定并前向傳播 outInfo = net.getUnconnectedOutLayersNames() # # 前面的yolov3架構也講了,yolo在每個scale都有輸出,outInfo是每個scale的名字信息,供net.forward使用 start = time.time() layerOutputs = net.forward(outInfo) # 得到各個輸出層的、各個檢測框等信息,是二維結(jié)構。 end = time.time() print("[INFO] YOLO took {:.6f} seconds".format(end - start)) # # 可以打印下信息# 拿到圖片尺寸 (H, W) = img.shape[:2] # 過濾layerOutputs # layerOutputs的第1維的元素內(nèi)容: [center_x, center_y, width, height, objectness, N-class score data] # 過濾后的結(jié)果放入: boxes = [] # 所有邊界框(各層結(jié)果放一起) confidences = [] # 所有置信度 classIDs = [] # 所有分類ID# # 1)過濾掉置信度低的框框 for out in layerOutputs: # 各個輸出層for detection in out: # 各個框框# 拿到置信度scores = detection[5:] # 各個類別的置信度classID = np.argmax(scores) # 最高置信度的id即為分類idconfidence = scores[classID] # 拿到置信度# 根據(jù)置信度篩查if confidence > CONFIDENCE:box = detection[0:4] * np.array([W, H, W, H]) # 將邊界框放會圖片尺寸(centerX, centerY, width, height) = box.astype("int")x = int(centerX - (width / 2))y = int(centerY - (height / 2))boxes.append([x, y, int(width), int(height)])confidences.append(float(confidence))classIDs.append(classID)# # 2)應用非最大值抑制(non-maxima suppression,nms)進一步篩掉 idxs = cv.dnn.NMSBoxes(boxes, confidences, CONFIDENCE, THRESHOLD) # boxes中,保留的box的索引index存入idxs # 得到labels列表 with open(labelsPath, 'rt') as f:labels = f.read().rstrip('\n').split('\n') # 應用檢測結(jié)果 np.random.seed(42) COLORS = np.random.randint(0, 255, size=(len(labels), 3), dtype="uint8") # 框框顯示顏色,每一類有不同的顏色,每種顏色都是由RGB三個值組成的,所以size為(len(labels), 3) if len(idxs) > 0:for i in idxs.flatten(): # indxs是二維的,第0維是輸出層,所以這里把它展平成1維(x, y) = (boxes[i][0], boxes[i][1])(w, h) = (boxes[i][2], boxes[i][3])color = [int(c) for c in COLORS[classIDs[i]]]cv.rectangle(img, (x, y), (x+w, y+h), color, 2) # 線條粗細為2pxtext = "{}: {:.4f}".format(labels[classIDs[i]], confidences[i])cv.putText(img, text, (x, y-5), cv.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) # cv.FONT_HERSHEY_SIMPLEX字體風格、0.5字體大小、粗細2px cv.imshow('detected image', img) cv.waitKey(0)

    結(jié)果:

    到此結(jié)束~

    寫博客真累,花太多時間了哎~

    轉(zhuǎn)載于:https://www.cnblogs.com/hesse-summer/p/11335865.html

    與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結(jié)

    以上是生活随笔為你收集整理的【教程】opencv-python+yolov3实现目标检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。