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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码)

發(fā)布時間:2023/12/10 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 1.序言
  • 2.設(shè)計思路以及遇到的問題
  • 3.實(shí)現(xiàn)過程
  • 4.總結(jié)&吐槽
  • 5.更新源碼
  • 6.聯(lián)系方式

1.序言

這里主要說一下遇到的問題以及想法,如有問題歡迎大家指正。

2.設(shè)計思路以及遇到的問題

  • 第一步是完成物體(也就是車輛)的檢測,這里有兩種解決辦法,第一種辦法是使用opencv的形態(tài)學(xué)處理,比如背景消除、做幀差、膨脹腐蝕等等,這個辦法比較基礎(chǔ),但是要處理好需要調(diào)整諸多細(xì)節(jié),我的細(xì)節(jié)調(diào)整的不夠好,因此實(shí)現(xiàn)時會遇到許多小問題。第二個辦法是直接實(shí)現(xiàn)物體的識別,需要用到一定的訓(xùn)練模型,我測試過googlenet和SSD,最終選擇了SSD,如果大家有能力也能自己訓(xùn)練,可能效果更好。
  • 第二步是追蹤,這里我看到很多博文都提到了opencv自帶的追蹤器,比如kcf等,但是我對于追蹤器沒有成功使用,放棄了這個選擇,并選擇了最簡單粗暴的方法:逐幀讀取視頻并尋找車輛,一幀一幀畫出來。
  • 第三步是計數(shù),這里我卡了一個星期,遇到了各種問題,為此我?guī)缀醴榱薈SDN關(guān)于這塊的文章,有些文章確實(shí)給到了一些思路,但大部分都沒給出具體過程。第一個問題是怎么判斷是否計數(shù)的問題,我最開始的想法是:當(dāng)車輛輪廓的y坐標(biāo)碰到檢測線(這里假定為700)時加1,但接下里的測試卻非常失敗,很多車輛在愛檢測線附近會掉幀或者檢測不到或者其他原因,總之僅僅靠一個y軸直接判斷肯定是不夠的,后來我改成往下大于檢測線1(700),往上大于檢測線2(400),發(fā)現(xiàn)問題更大了,你會一直檢測(這里我劃分ROI區(qū)域沒有解決,可能是我方法不對)。之后在CSDN 中找到一篇博文,提到的做法是建立一個類,每次出現(xiàn)新的目標(biāo)就創(chuàng)建一個類,舊的目標(biāo)就替換坐標(biāo),這個做法后來證實(shí)的確有效。但問題是如何判斷這一幀的車輛是否新的目標(biāo),我給出的解決辦法是創(chuàng)建一個列表,將第一幀的所有目標(biāo)(也就是每一個對象)存入,第二幀的時候遍歷每一個目標(biāo)與列表的每一輛車,判斷x,y的距離,如果變化不超過車的長度和寬度,就認(rèn)為這是同一輛車(也有學(xué)長告訴為特征值匹配的辦法,也許更可行,但我能力不夠沒有學(xué)到這里,所以沒有采用)。第三個問題 是來去方向問題,最開始的想法是讀取質(zhì)心,將每一輛車變成點(diǎn),然后讀取幀,當(dāng)這一幀的這一輛車的y坐標(biāo)相較于上一輛車增加時,就認(rèn)為這輛車方向向下,否者認(rèn)為方向向上,后來的測試證明我大錯特錯,有些車的輪廓會來回浮動,質(zhì)點(diǎn)也會來回浮動,因此有時候下一幀中方向向下的車輛的y坐標(biāo)甚至低于上一幀,所以我沒有采取這種方式。最終只能考慮最簡單粗暴的辦法:根據(jù)x坐標(biāo)給定方向,視頻中x軸1000往左為下,1000往右為上,我承認(rèn)這種辦法確實(shí)很笨,但我確實(shí)沒有想出好的辦法來,如有同學(xué)有辦法解決,懇請您大膽指出。第四個問題回到了計數(shù)判斷環(huán)節(jié),這里由于上面問題的解決,所以我給出的判斷條件是y坐標(biāo)+方向+是否已經(jīng)計數(shù)。最后有個非常重要的步驟是車輛跨越一定限度后刪除對象,節(jié)約計算時間。
  • 3.實(shí)現(xiàn)過程

    1.物體檢測識別和追中請看我的上幾篇博文,鏈接1 opencv檢測 鏈接2SSD車輛識別
    結(jié)果如下:

    2.定義類:(其實(shí)id沒啥用,方便測試)

    class Car:def __init__(self,c_id,c_x,c_y,direction,c_count): #初始化self.c_id = c_id #車輛編號self.c_x=c_x #車輛坐標(biāo)(實(shí)時更新)self.c_y=c_yself.direction = direction #車輛方向self.c_count = c_count #車輛是否已經(jīng)計數(shù)def updateCoords(self,x,y): #更新坐標(biāo)self.c_x= xself.c_y=y

    3.計數(shù)

    for i in cars:if abs(cx - i.c_x) < width and abs(cy - i.c_y) < height: # 找到這輛車與上一幀中最近的車new = False#最開始的想法,Y軸坐標(biāo)比上一幀大方向向下,比上一幀小方向向上,但失敗了# if cy > i.c_y:# i.direction = 'down'# if cy < i.c_y:# i.direction = 'up'i.updateCoords(cx, cy)if i.c_y >= 700 and i.direction == 'down' and i.c_count == False:count_down += 1i.c_count = Trueif i.c_y < 400 and i.direction == 'up' and i.c_count == False:count_up += 1i.c_count = True#刪除對象if i.c_y >= 790 or i.c_y <= 290:cars.remove(i)if new == True:p = Car(pid, cx, cy, 'unknow', False)#判斷方向,這里我實(shí)在沒找到好的辦法,只能從簡,大家測試的時候需要修改#如果有好的辦法請您指點(diǎn)if p.c_x > 1000:p.direction = 'up'else:p.direction = 'down'cars.append(p)pid += 1print(len(cars))cv.circle(image, (cx, cy), 5, (0, 0, 255), -1)cv.rectangle(image, (int(left), int(top)), (int(right), int(bottom)), (255, 0, 0), thickness=2)

    4.結(jié)果(由于視頻畫質(zhì)原因,遇到一些車輛比較模糊時會出現(xiàn)很多框,因此還需改進(jìn))

    4.總結(jié)&吐槽

    由于代碼還不夠完善,這里就不給大家一一貼出來了,主要是跟大家說一下我的思路,要是有小伙伴想?yún)⒖嫉脑?#xff0c;我就放一個下載鏈接吧,其實(shí)這個東西只要想明白了應(yīng)該不是什么難事(雖然我現(xiàn)在也有點(diǎn)暈),作為計算機(jī)視覺還在入門的新人,歡迎大家指出我的錯誤以便改進(jìn),也歡迎同樣是計算機(jī)視覺新手的小伙伴們一起學(xué)習(xí),本博客將一直更新相關(guān)內(nèi)容,我會把計算機(jī)視覺入門過程中所遇到的重要問題和自己的想法分享給大家,同時也希望能收到大家的點(diǎn)贊或者指點(diǎn)迷津。
    我在學(xué)習(xí)過程同遇到很多有經(jīng)驗(yàn)的同學(xué),他們有的使用了yolo v3算法,有的使用tensorflow訓(xùn)練模型,深感自己能力的不足,現(xiàn)在我會繼續(xù)學(xué)習(xí)這方面的內(nèi)容,希望能有更多思路和內(nèi)容分享給大家。
    吐槽:算法確實(shí)挺難的,但更難的是找測試素材,這十字路口的監(jiān)控錄像上哪找去(各大視頻網(wǎng)站愣是沒找到幾個能用的,給跪了orz)

    5.更新源碼

    有許多小伙伴詢問,現(xiàn)在將源碼分享給大家,希望大家指正
    2022.3.29更新:
    這篇博客是20年寫的,現(xiàn)在22年了,兩年過去了,沒想到這么多人評論留言和郵件聯(lián)系我,在這里謝謝大家了,作為cv新人(可能一直都會是新人)受寵若驚。

    需要說明的是,其實(shí)這個代碼有很大的局限性,因?yàn)橄袼攸c(diǎn)什么的都寫死了,換個視頻就不行了。而且純圖像處理的方法確實(shí)有很大的問題,一點(diǎn)點(diǎn)調(diào)參數(shù)確實(shí)能把一些大的物體運(yùn)動軌跡給抓住,但是一旦有的視頻會有光線啊、遮擋物啊什么的,僅僅用圖像處理就解決不掉了,因?yàn)檫@個代碼是我剛學(xué)圖像處理的時候做的,所以沒想太多。主要是記錄一下我遇到的問題吧,現(xiàn)在我現(xiàn)在已經(jīng)很久沒有用opencv了,有一些問題我也不知道在哪,這篇博客主要是提供一個思路,其實(shí)我回看一下思路確實(shí)沒啥問題,只是水平有限當(dāng)時沒有做好,如果是現(xiàn)在來做的話,yolo模型確實(shí)是比較優(yōu)秀的選擇,但是你用了yolo后,可以把我過線檢測以及定義類的思路用上。最后,無論是做畢設(shè)的、工作的還是在學(xué)習(xí)的兄弟,如果這篇博客幫到了大家,哪怕是一點(diǎn)點(diǎn)思路,那就是我開源的意義所在了,祝大家一帆風(fēng)順~

    此外,有問題還是可以繼續(xù)留言或者郵件,所有留言和郵件我都會看,并且會一一回復(fù)的!**

    import numpy as np import cv2 as cv import time class Car:def __init__(self,c_id,c_x,c_y,direction,c_count,c_start_time,c_over_time,c_v):self.c_id = c_idself.c_x=c_xself.c_y=c_yself.direction = directionself.c_count = c_countself.c_start_time = c_start_timeself.c_over_time = c_over_timeself.c_v = c_vdef updateCoords(self,x,y):self.c_x= xself.c_y=ycount_up = 0 count_down = 0 cars = [] pid = 1 max_v = 0 distance = 10 vc = cv.VideoCapture(r"C:\Users\zn\Desktop\監(jiān)控錄像_1.mp4")fourcc = cv.VideoWriter_fourcc(*'XVID') out = cv.VideoWriter('output.avi',fourcc,15, (1920,1080))BS = cv.createBackgroundSubtractorMOG2(detectShadows=True) while (vc.isOpened()):ret, frame = vc.read()# cv.imshow("frame01",frame)gray = cv.cvtColor(frame,cv.COLOR_BGR2GRAY)# ret,gray = cv.threshold(gray,127,255,cv.THRESH_BINARY)fgmask = BS.apply(gray)image = cv.medianBlur(fgmask,5)# cv.imshow("BS",fgmask)element = cv.getStructuringElement(cv.MORPH_RECT,(5, 5));#創(chuàng)建結(jié)構(gòu)體image2 = cv.morphologyEx(image, cv.MORPH_CLOSE,element,iterations=5);#閉運(yùn)算# image3 = cv.erode(image2, element)image3 = cv.morphologyEx(image2, cv.MORPH_OPEN, element, iterations=5)# cv.imshow('frame1', image3)contours, hierarchy = cv.findContours(image3, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)cv.line(frame, (0, 700), (1920, 700), (0, 255, 0), 3)cv.line(frame, (0, 400), (1920, 400), (0, 255, 0), 3)cv.line(frame, (0, 800), (1920, 800), (255, 255, 255), 2)cv.line(frame, (0, 300), (1920, 300), (255, 255, 255), 2)cv.putText(frame,"Up:"+str(count_up),(1100,100),cv.FONT_HERSHEY_COMPLEX,2,(255,0,0),3)cv.putText(frame, "Down:" + str(count_down),(700, 100), cv.FONT_HERSHEY_COMPLEX, 2, (255, 0, 0), 3)cv.putText(frame, "max_v:" + str('%.2f' %(max_v*3.6))+'km/h', (50, 100), cv.FONT_HERSHEY_COMPLEX, 1.5, (255, 0, 0), 2)null = True #如果這一幀沒有檢測到任何車,則將cars置空,減小誤差,設(shè)置初始變量null設(shè)為Truefor cnt in contours:x, y, w, h = cv.boundingRect(cnt)cx = int(x + w / 2)cy = int(y + h / 2)if 300<int(y+(h/2))<800 and 400<int(x+(w/2))<1800:if cv.contourArea(cnt) < 13000 or w < 100 or h < 100:continuenull = False #有車時不會清空new = True #是否創(chuàng)建車輛for i in cars:if abs(cx-i.c_x) <100 and abs(cy - i.c_y)<100:#找到這輛車與上一幀中最近的車# cv.putText(frame, 'cid:' + str(i.c_id), (x, y-10), cv.FONT_HERSHEY_COMPLEX, 1, (255, 0, 0), 2)# cv.putText(frame, "now_v:" + str('%.4f' % (i.c_v)) + 'm/s', (x, y-10),# cv.FONT_HERSHEY_COMPLEX, 1,# (255, 0, 0), 2)new = Falsei.updateCoords(cx,cy)#更新車輛位置信息if 700<=i.c_y<=720 and i.direction =='down' and i.c_count ==False:i.c_over_time = time.time()i.c_v = distance/(i.c_over_time - i.c_start_time)if i.c_v>max_v:max_v = i.c_vcount_down+=1i.c_count=Trueif 380<=i.c_y<=400 and i.direction =='up' and (i.c_count == False):i.c_over_time = time.time()i.c_v = distance/ (i.c_over_time - i.c_start_time)if i.c_v > max_v:max_v = i.c_vcount_up+=1i.c_count=Trueif i.c_y>720 or i.c_y<380:cars.remove(i) #超過一定范圍,刪除對象if new == True and 340<cy<760: #符合一定條件,創(chuàng)建對象start_time = time.time()p = Car(pid, cx, cy, 'unknow', False, start_time ,0,0)if p.c_x <1000:p.direction = 'down'else:p.direction = 'up'cars.append(p)pid += 1cv.circle(frame, (cx, cy), 5, (0, 0, 255), -1)cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 3)if null == True: #該幀沒車,清空carscars = []# cv.putText(frame, 'cars:' + str(len(cars)), (100, 100), cv.FONT_HERSHEY_COMPLEX, 2, (255, 0, 0), 3)cv.imshow("frame",frame)out.write(frame)#cv.imshow('frame2', image3)# print(max_v*3.6)k = cv.waitKey(30) & 0xffif k == 27:break vc.release() cv.destroyAllWindows()

    6.聯(lián)系方式

    有問題歡迎聯(lián)系我:
    視頻刪掉了,好像是從優(yōu)酷還是騰訊視頻找的吧。
    1759412770@qq.com
    zn1759412770@163.com

    總結(jié)

    以上是生活随笔為你收集整理的Python + OpenCv实现视频中的车辆检测计数(车流量统计) (2020.7.15已更新源码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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