0 簡介
今天學長向大家分享一個畢業(yè)設計項目
畢業(yè)設計 基于深度學習的抽煙行為檢測算法實現(xiàn)(源碼分享)
項目運行效果:
畢業(yè)設計 深度學習的抽煙行為檢測算法實現(xiàn)
項目獲取:文章來源:http://www.zghlxwxcb.cn/news/detail-835923.html
https://gitee.com/sinonfin/algorithm-sharing文章來源地址http://www.zghlxwxcb.cn/news/detail-835923.html
通過目前應用比較廣泛的 Web 開發(fā)平臺,將模型訓練完成的算法模型部署,部署于 Web 平臺。并且利用目前流行的前后端技術在該平臺進行整合實現(xiàn)運營車輛駕駛員吸煙行為檢測系統(tǒng),方便用戶使用。
1 系統(tǒng)概述
本系統(tǒng)是一種運營車輛駕駛員吸煙行為檢測系統(tǒng),為了降低誤檢率,對駕駛員視頻中的吸煙煙霧和香煙目標分別進行檢測,若同時檢測到則判定該駕駛員存在吸煙行為。進行流程化處理,以滿足用戶的需要。駕駛員吸煙行為檢測系統(tǒng)結合了當前機器學習技術以及深度學習技術,通過對真實拍攝的駕駛員車內視頻數(shù)據進行測試,最終實現(xiàn)吸煙檢測功能。針對目前駕駛員開車吸煙現(xiàn)狀人工監(jiān)控困難的問題,本系統(tǒng)為監(jiān)控人員提供輔助監(jiān)控功能,降低監(jiān)控人員失誤率,解決監(jiān)控人員因為疲勞作業(yè)出現(xiàn)工作失誤。
本系統(tǒng)的主要工作流程如下:
系統(tǒng)設計原則
為了使本次設計的吸煙檢測系統(tǒng)具有更好的實用性、準確性和穩(wěn)定性,同時能夠讓相關操作人員在使用時感受到便捷并且容易上手,在設計本系統(tǒng)時,主要遵循了以下五項基本原則:
(1)規(guī)范性原則:
在系統(tǒng)開發(fā)的過程當中所用到的控制協(xié)議、傳輸協(xié)議,編碼類型等都應該符合國家標準和行業(yè)標準。在代碼撰寫時,應該符合一般的技術規(guī)范。
(2)模塊化設計原則
模塊化設計是指在系統(tǒng)設計時,盡可能的將多個基本功能設計為多個獨立運行的模塊,并且每一個模塊只負責一件事情。這樣就可以讓系統(tǒng)結構更加清晰,同時在實際的運行過程中可以實現(xiàn)不同模塊之間的調用,大大增加了系統(tǒng)的靈活性。這樣做既可以用有限的模塊來最大限度的完成用戶的要求,同時對系統(tǒng)后期的維護以及功能的增加都非常有利。
(3)可操作性與可維護性原則
一個好的系統(tǒng)應該具有很好的可操作性,所以在符合用戶使用習慣的基礎上,對每一個具體操作進行簡化。同時,為了使系統(tǒng)可以更加便于維護,在系統(tǒng)設計的過程當中,應該提前想清楚各個功能模塊之間的難點與邏輯,這樣才能在日后的維護當中減少工作量。
(4)可拓展性原則
系統(tǒng)開發(fā)將多個基本功能盡可能的設計為多個獨立運行的模塊,大大增加了系統(tǒng)的可拓展性。與此同時,開發(fā)過程當中,前端和后端的功能是分開進行的,通過提前設計好的可供數(shù)據傳輸?shù)慕涌?,?JSON 數(shù)據格式在各個模塊之間進行數(shù)據交換操作,使前后端之間具有解耦關系,這樣做可以保證了系統(tǒng)具有比較良好的可擴展能力和穩(wěn)定能力。
(5)經濟性原則
在系統(tǒng)設計的時候,首先是要考慮用戶的具體需求,設計實用的功能,發(fā)揮系統(tǒng)的最大性能。但是在滿足用戶所需的功能后,也應該盡可能的減少開發(fā)成本,采用更加經濟的技術設備,不能只是一味地追求更高級更復雜的設計方案,要充分利用現(xiàn)有的設備和資源,綜合考慮系統(tǒng)建設、升級以及維護時所需的費用,在有限的成本下更好的去完成任務。
3 實現(xiàn)效果
左圖為原圖,右圖為推理后的圖片,以圖片方式展示,視頻流和實時流也能達到這個效果,由于視頻轉GIF大小原因,這里暫不演示。
4 Yolov5算法
4.1 簡介
YOLO系列是基于深度學習的回歸方法。該系列陸續(xù)誕生出YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5。YOLOv5算法,它是一種單階段目標檢測的算法,該算法可以根據落地要求靈活地通過chaneel和layer的控制因子來配置和調節(jié)模型,所以在比賽和落地中應用比較多。同時它有YOLOv5x、YOLOv5l、YOLOv5m、YOLOv5s四種模型。
具有以下優(yōu)點:
- 在pytorch環(huán)境下編寫;
- 可以很容易編譯成ON?NX和Core ML;
- 運行速度很快,每秒可以達到140FPS的速度;
- 模型精度高;
- 集成了YOLOv3和YOLOv4的部分優(yōu)秀特性,進行了推陳出新的改進。
4.2 相關技術
Mosaic數(shù)據增強
Mosaic數(shù)據增強技術采用了四張圖片的隨機縮放、隨機剪裁、隨機排布的方式對數(shù)據進行拼接,相比CutMix數(shù)據增強多用了兩張圖片。在目標識別過程中,要識別的目標有大目標、中等目標、小目標,并且三種目標的占比例不均衡,其中,小目標的數(shù)量是最多的,但是出現(xiàn)的頻率很低,這種情況就會導致在bp時對小目標的優(yōu)化不足,模型正確識別小目標的難度比識別中、大目標的難度要大很多,于是對于小目標來說很容易出現(xiàn)誤檢和漏檢的情況。Mosaic數(shù)據增強技術做出改進后,上述的問題得到有效的解決。
該技術的優(yōu)點是:
- 豐富了數(shù)據集,采用“三個隨機”的方式對數(shù)據進行拼接豐富了檢測的數(shù)據集,尤其是隨機縮放增加了很多小目標,克服了小目標的不足,讓網絡的魯棒性得到提高;
- 減少GPU的使用,在Mosaic增強訓練時,四張圖片拼接在一起,GPU可以直接計算四張圖片的數(shù)據,讓Mini-batch的大小減少了很多,這使得一個GPU就可以達到比較可觀的效果。
自適應anchor
自適應anchor是check_anchors函數(shù)通過遺傳算法與Kmeans迭代算出的最大可能召回率的anchor組合。在網絡模型的訓練過程中,網絡在初始化的錨框的基礎上輸出預測框,然后與真實框groundtruth進行對比,計算兩個框之間的差值,再根據差值進行反向更新,迭代網絡參數(shù),最后求出最佳的錨框值。自適應的anchor能夠更好地配合網絡訓練,提高模型的精度,減少對anchor的設計難度,具有很好的實用性。
自適應圖片縮放
為了提高模型的推理速度,YOLOv5提出自適應圖片縮放,根據長寬比對圖像進行縮放,并添加最少的黑邊,減少計算量。該方法是用縮放后的長邊減去短邊再對32進行取余運算,求出padding。在訓練時并沒有采用縮減黑邊的方法,該方法只是在測試模型推理的時候才使用,這樣提高了目標檢測的準確率和速度。
Focus結構
該結構采用切片操作,將特征切片成四份,每一份將當成下采樣的特征,然后在channel維度進行concat。例如:原始6086083的數(shù)據圖片,經過切片操作先變成30430412的特征圖,再經過一次32個卷積核的卷積操作,變成30430432的特征圖。
CSP結構
YOLOv5中的CSP[5]結構應用于兩處,一處是CSP1_X結構應用于Backbone的主干網絡中,另一處的CSP2_X結構應用于Neck中,用于加強網絡的特征融合的能力。CSPNet主要從網絡結構設計的角度解決推理中從計算量很大的問題。該結構的優(yōu)點有:1)增強CNN的學習能力,使得模型在輕量化的同時保持較高的準確性;2)減低計算的瓶頸問題;3)減低內存的分險。
PFN+PAN結構
這個結構是FPN和PAN的聯(lián)合。FPN是自頂向下的,將高層的特征信息通過上采樣的方式進行傳遞融合,得到進行預測的特征圖,而PAN正好與FPN的方向是相反的方向,它是自底向上地采取特征信息。兩個結構各自從不同的主干層對不同的檢測層進行參數(shù)聚合。兩個結構的強強聯(lián)合讓得到的特征圖的特征更加明顯和清楚。
Bounding box的損失函數(shù)
Bounding box損失函數(shù)[6]增加了相交尺度的衡量方式,有效緩解了當兩個框不相交和兩個框大小完全相同的兩種特殊情況。因為當預測框和目標框不相交時,IOU=0,無法反應兩個框距離的遠近的時候,此時的損失函數(shù)不可導;兩個框大小完全相同,兩個IOU也相同,IOU_LOSS無法區(qū)分以上兩種特殊情況。
nms非極大值抑制
在目標檢測過程的后續(xù)處理中,對于大量的目標框的篩選問題,通常會進行nms操作,以此來達到一個不錯的效果。YO?LOv5算法同樣采用了加權的nms操作。
5 數(shù)據集處理及實驗
數(shù)據集準備
由于目前針對吸煙圖片并沒有現(xiàn)成的數(shù)據集,我們使用Python爬蟲利用關鍵字在互聯(lián)網上獲得的圖片數(shù)據,編寫程序爬了1w張,篩選下來有近1000張可用,以及其他途徑獲取到的,暫時可用數(shù)據集有5k張,
深度學習圖像標注軟件眾多,按照不同分類標準有多中類型,本文使用LabelImg單機標注軟件進行標注。LabelImg是基于角點的標注方式產生邊界框,對圖片進行標注得到xml格式的標注文件,由于邊界框對檢測精度的影響較大因此采用手動標注,并沒有使用自動標注軟件。
考慮到有的朋友時間不足,博主提供了標注好的數(shù)據集和訓練好的模型,需要請聯(lián)系。
數(shù)據標注簡介
通過pip指令即可安裝
pip install labelimg
在命令行中輸入labelimg即可打開
6 部分核心代碼
# data/smoke.yaml
# COCO 2017 dataset http://cocodataset.org
# Download command: bash yolov5/data/get_coco2017.sh
# Train command: python train.py --data ./data/coco.yaml
# Dataset should be placed next to yolov5 folder:
# /parent_folder
# /coco
# /yolov5
# train and val datasets (image directory or *.txt file with image paths)
train: data\train.txt # 上面我們生成的train,根據自己的路徑進行更改
val: data\test.txt # 上面我們生成的test
#test: ../coco/test-dev2017.txt # 20k images for submission to https://competitions.codalab.org/competitions/20794
# number of classes
nc: 1 #訓練的類別
# class names
names: ['smoke']
# Print classes
# with open('data/coco.yaml') as f:
# d = yaml.load(f, Loader=yaml.FullLoader) # dict
# for i, x in enumerate(d['names']):
# print(i, x)
# model/yolov5s.yaml
# parameters
nc: 1 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
# anchors
anchors:
- [116,90, 156,198, 373,326] # P5/32
- [30,61, 62,45, 59,119] # P4/16
- [10,13, 16,30, 33,23] # P3/8
# YOLOv5 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, BottleneckCSP, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, BottleneckCSP, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, BottleneckCSP, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
]
# YOLOv5 head
head:
[[-1, 3, BottleneckCSP, [1024, False]], # 9
[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, BottleneckCSP, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, BottleneckCSP, [256, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 18 (P3/8-small)
[-2, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, BottleneckCSP, [512, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 22 (P4/16-medium)
[-2, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, BottleneckCSP, [1024, False]],
[-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]], # 26 (P5/32-large)
[[], 1, Detect, [nc, anchors]], # Detect(P5, P4, P3)
]
# 訓練部分主函數(shù)
if __name__ == '__main__':
check_git_status()
parser = argparse.ArgumentParser()
parser.add_argument('--epochs', type=int, default=300)
parser.add_argument('--batch-size', type=int, default=16)
parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='*.cfg path')
parser.add_argument('--data', type=str, default='data/smoke.yaml', help='*.data path')
parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='train,test sizes')
parser.add_argument('--rect', action='store_true', help='rectangular training')
parser.add_argument('--resume', action='store_true', help='resume training from last.pt')
parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
parser.add_argument('--notest', action='store_true', help='only test final epoch')
parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')
parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')
parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')
parser.add_argument('--weights', type=str, default='', help='initial weights path')
parser.add_argument('--name', default='', help='renames results.txt to results_name.txt if supplied')
parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--adam', action='store_true', help='use adam optimizer')
parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%')
parser.add_argument('--single-cls', action='store_true', help='train as single-class dataset')
opt = parser.parse_args()
opt.weights = last if opt.resume else opt.weights
opt.cfg = check_file(opt.cfg) # check file
opt.data = check_file(opt.data) # check file
print(opt)
opt.img_size.extend([opt.img_size[-1]] * (2 - len(opt.img_size))) # extend to 2 sizes (train, test)
device = torch_utils.select_device(opt.device, apex=mixed_precision, batch_size=opt.batch_size)
if device.type == 'cpu':
mixed_precision = False
# Train
if not opt.evolve:
tb_writer = SummaryWriter(comment=opt.name)
print('Start Tensorboard with "tensorboard --logdir=runs", view at http://localhost:6006/')
train(hyp)
# Evolve hyperparameters (optional)
else:
tb_writer = None
opt.notest, opt.nosave = True, True # only test/save final epoch
if opt.bucket:
os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket) # download evolve.txt if exists
for _ in range(10): # generations to evolve
if os.path.exists('evolve.txt'): # if evolve.txt exists: select best hyps and mutate
# Select parent(s)
parent = 'single' # parent selection method: 'single' or 'weighted'
x = np.loadtxt('evolve.txt', ndmin=2)
n = min(5, len(x)) # number of previous results to consider
x = x[np.argsort(-fitness(x))][:n] # top n mutations
w = fitness(x) - fitness(x).min() # weights
if parent == 'single' or len(x) == 1:
# x = x[random.randint(0, n - 1)] # random selection
x = x[random.choices(range(n), weights=w)[0]] # weighted selection
elif parent == 'weighted':
x = (x * w.reshape(n, 1)).sum(0) / w.sum() # weighted combination
# Mutate
mp, s = 0.9, 0.2 # mutation probability, sigma
npr = np.random
npr.seed(int(time.time()))
g = np.array([1, 1, 1, 1, 1, 1, 1, 0, .1, 1, 0, 1, 1, 1, 1, 1, 1, 1]) # gains
ng = len(g)
v = np.ones(ng)
while all(v == 1): # mutate until a change occurs (prevent duplicates)
v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)
for i, k in enumerate(hyp.keys()): # plt.hist(v.ravel(), 300)
hyp[k] = x[i + 7] * v[i] # mutate
# Clip to limits
keys = ['lr0', 'iou_t', 'momentum', 'weight_decay', 'hsv_s', 'hsv_v', 'translate', 'scale', 'fl_gamma']
limits = [(1e-5, 1e-2), (0.00, 0.70), (0.60, 0.98), (0, 0.001), (0, .9), (0, .9), (0, .9), (0, .9), (0, 3)]
for k, v in zip(keys, limits):
hyp[k] = np.clip(hyp[k], v[0], v[1])
# Train mutation
results = train(hyp.copy())
# Write mutation results
print_mutation(hyp, results, opt.bucket)
# Plot results
# plot_evolution_results(hyp)
項目運行效果:
畢業(yè)設計 深度學習的抽煙行為檢測算法實現(xiàn)
最后
項目獲取:
https://gitee.com/sinonfin/algorithm-sharing
到了這里,關于大數(shù)據畢設分享 基于深度學習的抽煙行為檢測算法實現(xiàn)(源碼分享)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!