0 前言
?? 優(yōu)質(zhì)競賽項(xiàng)目系列,今天要分享的是
?? **基于深度學(xué)習(xí)YOLO安檢管制誤判識(shí)別與檢測 **
該項(xiàng)目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦!
??學(xué)長這里給一個(gè)題目綜合評分(每項(xiàng)滿分5分)
- 難度系數(shù):4分
- 工作量:3分
- 創(chuàng)新點(diǎn):4分
?? 更多資料, 項(xiàng)目分享:文章來源:http://www.zghlxwxcb.cn/news/detail-830972.html
https://gitee.com/dancheng-senior/postgraduate文章來源地址http://www.zghlxwxcb.cn/news/detail-830972.html
1 課題背景
軍事信息化建設(shè)一直是各國的研究熱點(diǎn),但我國的武器存在著種類繁多、信息散落等問題,這不利于國防工作提取有效信息,大大妨礙了我軍信息化建設(shè)的步伐。同時(shí),我軍武器常以文字、二維圖片和實(shí)體武器等傳統(tǒng)方式進(jìn)行展示,交互性差且無法滿足更多軍迷了解武器性能、近距離觀賞或把玩武器的迫切需求。本文將改進(jìn)后的Yolov5算法應(yīng)用到武器識(shí)別中,將武器圖片中的武器快速識(shí)別出來,提取武器的相關(guān)信息,并將其放入三維的武器展現(xiàn)系統(tǒng)中進(jìn)行展示,以期讓人們了解和掌握各種武器,有利于推動(dòng)軍事信息化建設(shè)。
2 實(shí)現(xiàn)效果
檢測展示
3 卷積神經(jīng)網(wǎng)絡(luò)
簡介
卷積神經(jīng)網(wǎng)絡(luò) (CNN)
是一種算法,將圖像作為輸入,然后為圖像的所有方面分配權(quán)重和偏差,從而區(qū)分彼此。神經(jīng)網(wǎng)絡(luò)可以通過使用成批的圖像進(jìn)行訓(xùn)練,每個(gè)圖像都有一個(gè)標(biāo)簽來識(shí)別圖像的真實(shí)性質(zhì)(這里是貓或狗)。一個(gè)批次可以包含十分之幾到數(shù)百個(gè)圖像。
對于每張圖像,將網(wǎng)絡(luò)預(yù)測與相應(yīng)的現(xiàn)有標(biāo)簽進(jìn)行比較,并評估整個(gè)批次的網(wǎng)絡(luò)預(yù)測與真實(shí)值之間的距離。然后,修改網(wǎng)絡(luò)參數(shù)以最小化距離,從而增加網(wǎng)絡(luò)的預(yù)測能力。類似地,每個(gè)批次的訓(xùn)練過程都是類似的。
相關(guān)代碼實(shí)現(xiàn)
cnn卷積神經(jīng)網(wǎng)絡(luò)的編寫如下,編寫卷積層、池化層和全連接層的代碼
?
conv1_1 = tf.layers.conv2d(x, 16, (3, 3), padding='same', activation=tf.nn.relu, name='conv1_1')
conv1_2 = tf.layers.conv2d(conv1_1, 16, (3, 3), padding='same', activation=tf.nn.relu, name='conv1_2')
pool1 = tf.layers.max_pooling2d(conv1_2, (2, 2), (2, 2), name='pool1')
conv2_1 = tf.layers.conv2d(pool1, 32, (3, 3), padding='same', activation=tf.nn.relu, name='conv2_1')
conv2_2 = tf.layers.conv2d(conv2_1, 32, (3, 3), padding='same', activation=tf.nn.relu, name='conv2_2')
pool2 = tf.layers.max_pooling2d(conv2_2, (2, 2), (2, 2), name='pool2')
conv3_1 = tf.layers.conv2d(pool2, 64, (3, 3), padding='same', activation=tf.nn.relu, name='conv3_1')
conv3_2 = tf.layers.conv2d(conv3_1, 64, (3, 3), padding='same', activation=tf.nn.relu, name='conv3_2')
pool3 = tf.layers.max_pooling2d(conv3_2, (2, 2), (2, 2), name='pool3')
conv4_1 = tf.layers.conv2d(pool3, 128, (3, 3), padding='same', activation=tf.nn.relu, name='conv4_1')
conv4_2 = tf.layers.conv2d(conv4_1, 128, (3, 3), padding='same', activation=tf.nn.relu, name='conv4_2')
pool4 = tf.layers.max_pooling2d(conv4_2, (2, 2), (2, 2), name='pool4')
flatten = tf.layers.flatten(pool4)
fc1 = tf.layers.dense(flatten, 512, tf.nn.relu)
fc1_dropout = tf.nn.dropout(fc1, keep_prob=keep_prob)
fc2 = tf.layers.dense(fc1, 256, tf.nn.relu)
fc2_dropout = tf.nn.dropout(fc2, keep_prob=keep_prob)
fc3 = tf.layers.dense(fc2, 2, None)
4 Yolov5
我們選擇當(dāng)下YOLO最新的卷積神經(jīng)網(wǎng)絡(luò)YOLOv5來進(jìn)行火焰識(shí)別檢測。6月9日,Ultralytics公司開源了YOLOv5,離上一次YOLOv4發(fā)布不到50天。而且這一次的YOLOv5是完全基于PyTorch實(shí)現(xiàn)的!在我們還對YOLOv4的各種高端操作、豐富的實(shí)驗(yàn)對比驚嘆不已時(shí),YOLOv5又帶來了更強(qiáng)實(shí)時(shí)目標(biāo)檢測技術(shù)。按照官方給出的數(shù)目,現(xiàn)版本的YOLOv5每個(gè)圖像的推理時(shí)間最快0.007秒,即每秒140幀(FPS),但YOLOv5的權(quán)重文件大小只有YOLOv4的1/9。
目標(biāo)檢測架構(gòu)分為兩種,一種是two-stage,一種是one-stage,區(qū)別就在于 two-stage 有region
proposal過程,類似于一種海選過程,網(wǎng)絡(luò)會(huì)根據(jù)候選區(qū)域生成位置和類別,而one-stage直接從圖片生成位置和類別。今天提到的 YOLO就是一種
one-stage方法。YOLO是You Only Look Once的縮寫,意思是神經(jīng)網(wǎng)絡(luò)只需要看一次圖片,就能輸出結(jié)果。YOLO
一共發(fā)布了五個(gè)版本,其中 YOLOv1 奠定了整個(gè)系列的基礎(chǔ),后面的系列就是在第一版基礎(chǔ)上的改進(jìn),為的是提升性能。
YOLOv5有4個(gè)版本性能如圖所示:
網(wǎng)絡(luò)架構(gòu)圖
YOLOv5是一種單階段目標(biāo)檢測算法,該算法在YOLOv4的基礎(chǔ)上添加了一些新的改進(jìn)思路,使其速度與精度都得到了極大的性能提升。主要的改進(jìn)思路如下所示:
輸入端
在模型訓(xùn)練階段,提出了一些改進(jìn)思路,主要包括Mosaic數(shù)據(jù)增強(qiáng)、自適應(yīng)錨框計(jì)算、自適應(yīng)圖片縮放;
Mosaic數(shù)據(jù)增強(qiáng)
:Mosaic數(shù)據(jù)增強(qiáng)的作者也是來自YOLOv5團(tuán)隊(duì)的成員,通過隨機(jī)縮放、隨機(jī)裁剪、隨機(jī)排布的方式進(jìn)行拼接,對小目標(biāo)的檢測效果很不錯(cuò)
基準(zhǔn)網(wǎng)絡(luò)
融合其它檢測算法中的一些新思路,主要包括:Focus結(jié)構(gòu)與CSP結(jié)構(gòu);
Neck網(wǎng)絡(luò)
在目標(biāo)檢測領(lǐng)域,為了更好的提取融合特征,通常在Backbone和輸出層,會(huì)插入一些層,這個(gè)部分稱為Neck。Yolov5中添加了FPN+PAN結(jié)構(gòu),相當(dāng)于目標(biāo)檢測網(wǎng)絡(luò)的頸部,也是非常關(guān)鍵的。
FPN+PAN的結(jié)構(gòu)
這樣結(jié)合操作,F(xiàn)PN層自頂向下傳達(dá)強(qiáng)語義特征(High-Level特征),而特征金字塔則自底向上傳達(dá)強(qiáng)定位特征(Low-
Level特征),兩兩聯(lián)手,從不同的主干層對不同的檢測層進(jìn)行特征聚合。
FPN+PAN借鑒的是18年CVPR的PANet,當(dāng)時(shí)主要應(yīng)用于圖像分割領(lǐng)域,但Alexey將其拆分應(yīng)用到Y(jié)olov4中,進(jìn)一步提高特征提取的能力。
Head輸出層
輸出層的錨框機(jī)制與YOLOv4相同,主要改進(jìn)的是訓(xùn)練時(shí)的損失函數(shù)GIOU_Loss,以及預(yù)測框篩選的DIOU_nms。
對于Head部分,可以看到三個(gè)紫色箭頭處的特征圖是40×40、20×20、10×10。以及最后Prediction中用于預(yù)測的3個(gè)特征圖:
?
①==>40×40×255
②==>20×20×255
③==>10×10×255
?
-
相關(guān)代碼
class Detect(nn.Module): stride = None # strides computed during build onnx_dynamic = False # ONNX export parameter def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer super().__init__() self.nc = nc # number of classes self.no = nc + 5 # number of outputs per anchor self.nl = len(anchors) # number of detection layers self.na = len(anchors[0]) // 2 # number of anchors self.grid = [torch.zeros(1)] * self.nl # init grid self.anchor_grid = [torch.zeros(1)] * self.nl # init anchor grid self.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2)) # shape(nl,na,2) self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) # output conv self.inplace = inplace # use in-place ops (e.g. slice assignment) def forward(self, x): z = [] # inference output for i in range(self.nl): x[i] = self.m[i](x[i]) # conv bs, _, ny, nx = x[i].shape # x(bs,255,20,20) to x(bs,3,20,20,85) x[i] = x[i].view(bs, self.na, self.no, ny, nx).permute(0, 1, 3, 4, 2).contiguous() if not self.training: # inference if self.onnx_dynamic or self.grid[i].shape[2:4] != x[i].shape[2:4]: self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i) y = x[i].sigmoid() if self.inplace: y[..., 0:2] = (y[..., 0:2] * 2 - 0.5 + self.grid[i]) * self.stride[i] # xy y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh else: # for YOLOv5 on AWS Inferentia https://github.com/ultralytics/yolov5/pull/2953 xy = (y[..., 0:2] * 2 - 0.5 + self.grid[i]) * self.stride[i] # xy wh = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh y = torch.cat((xy, wh, y[..., 4:]), -1) z.append(y.view(bs, -1, self.no)) return x if self.training else (torch.cat(z, 1), x) def _make_grid(self, nx=20, ny=20, i=0): d = self.anchors[i].device if check_version(torch.__version__, '1.10.0'): # torch>=1.10.0 meshgrid workaround for torch>=0.7 compatibility yv, xv = torch.meshgrid([torch.arange(ny).to(d), torch.arange(nx).to(d)], indexing='ij') else: yv, xv = torch.meshgrid([torch.arange(ny).to(d), torch.arange(nx).to(d)]) grid = torch.stack((xv, yv), 2).expand((1, self.na, ny, nx, 2)).float() anchor_grid = (self.anchors[i].clone() * self.stride[i]) \ .view((1, self.na, 1, 1, 2)).expand((1, self.na, ny, nx, 2)).float() return grid, anchor_grid
5 模型訓(xùn)練
訓(xùn)練效果如下
相關(guān)代碼
?
#部分代碼
def train(hyp, opt, device, tb_writer=None):
print(f'Hyperparameters {hyp}')
log_dir = tb_writer.log_dir if tb_writer else 'runs/evolve' # run directory
wdir = str(Path(log_dir) / 'weights') + os.sep # weights directory
os.makedirs(wdir, exist_ok=True)
last = wdir + 'last.pt'
best = wdir + 'best.pt'
results_file = log_dir + os.sep + 'results.txt'
epochs, batch_size, total_batch_size, weights, rank = \
opt.epochs, opt.batch_size, opt.total_batch_size, opt.weights, opt.local_rank
# TODO: Use DDP logging. Only the first process is allowed to log.
# Save run settings
with open(Path(log_dir) / 'hyp.yaml', 'w') as f:
yaml.dump(hyp, f, sort_keys=False)
with open(Path(log_dir) / 'opt.yaml', 'w') as f:
yaml.dump(vars(opt), f, sort_keys=False)
# Configure
cuda = device.type != 'cpu'
init_seeds(2 + rank)
with open(opt.data) as f:
data_dict = yaml.load(f, Loader=yaml.FullLoader) # model dict
train_path = data_dict['train']
test_path = data_dict['val']
nc, names = (1, ['item']) if opt.single_cls else (int(data_dict['nc']), data_dict['names']) # number classes, names
assert len(names) == nc, '%g names found for nc=%g dataset in %s' % (len(names), nc, opt.data) # check
# Remove previous results
if rank in [-1, 0]:
for f in glob.glob('*_batch*.jpg') + glob.glob(results_file):
os.remove(f)
# Create model
model = Model(opt.cfg, nc=nc).to(device)
# Image sizes
gs = int(max(model.stride)) # grid size (max stride)
imgsz, imgsz_test = [check_img_size(x, gs) for x in opt.img_size] # verify imgsz are gs-multiples
# Optimizer
nbs = 64 # nominal batch size
# default DDP implementation is slow for accumulation according to: https://pytorch.org/docs/stable/notes/ddp.html
# all-reduce operation is carried out during loss.backward().
# Thus, there would be redundant all-reduce communications in a accumulation procedure,
# which means, the result is still right but the training speed gets slower.
# TODO: If acceleration is needed, there is an implementation of allreduce_post_accumulation
# in https://github.com/NVIDIA/DeepLearningExamples/blob/master/PyTorch/LanguageModeling/BERT/run_pretraining.py
accumulate = max(round(nbs / total_batch_size), 1) # accumulate loss before optimizing
hyp['weight_decay'] *= total_batch_size * accumulate / nbs # scale weight_decay
pg0, pg1, pg2 = [], [], [] # optimizer parameter groups
for k, v in model.named_parameters():
if v.requires_grad:
if '.bias' in k:
pg2.append(v) # biases
elif '.weight' in k and '.bn' not in k:
pg1.append(v) # apply weight decay
else:
pg0.append(v) # all else
if opt.adam:
optimizer = optim.Adam(pg0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999)) # adjust beta1 to momentum
else:
optimizer = optim.SGD(pg0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)
optimizer.add_param_group({'params': pg1, 'weight_decay': hyp['weight_decay']}) # add pg1 with weight_decay
optimizer.add_param_group({'params': pg2}) # add pg2 (biases)
print('Optimizer groups: %g .bias, %g conv.weight, %g other' % (len(pg2), len(pg1), len(pg0)))
del pg0, pg1,
6 實(shí)現(xiàn)效果
7 最后
?? 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate
到了這里,關(guān)于計(jì)算機(jī)設(shè)計(jì)大賽 深度學(xué)習(xí)YOLO安檢管制物品識(shí)別與檢測 - python opencv的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!