-
yolov3
2018-05-16 12:23:56yolov3延续了yolov2的anchor策略,基本没有变化。 边框的表示方式通过框的中心坐标bx,by,和框的宽bw,高bh这4个变量来表示。实际预测的值为tx,ty,tw,th。 由tx,ty,tw,th得到bx,by,bw,bh的详细公式如上图,其中, ...Anchor策略:
yolov3延续了yolov2的anchor策略,基本没有变化。
边框的表示方式通过框的中心坐标bx,by,和框的宽bw,高bh这4个变量来表示。实际预测的值为tx,ty,tw,th。
由tx,ty,tw,th得到bx,by,bw,bh的详细公式如上图,其中,
cx,cy为框的中心坐标所在的grid cell 距离左上角第一个grid cell的cell个数。
tx,ty为预测的边框的中心点坐标。
σ()函数为logistic函数,将坐标归一化到0-1之间。最终得到的bx,by为归一化后的相对于grid cell的值
tw,th为预测的边框的宽,高。
pw,ph为anchor的宽,高。实际在使用中,作者为了将bw,bh也归一化到0-1,实际程序中的 pw,ph为anchor的宽,高和featuremap的宽,高的比值。最终得到的bw,bh为归一化后相对于feature map的比值
σ(t0)表示预测的边框的置信度,为预测的边框的概率和预测的边框与ground truth的IOU值的乘积。
这里有别于faster系列,yolov3只为ground truth 匹配一个最优的边界框。
分类损失函数:
yolov3中将yolov2中多分类损失函数softmax cross-entropy loss 换为2分类损失函数binary cross-entropy loss 。因为当图片中存在物体相互遮挡的情形时,一个box可能属于好几个物体,而不是单单的属于这个不属于那个,这时使用2分类的损失函数就更有优势。
多尺度预测:
Yolov3采用了类似SSD的mul-scales策略,使用3个scale(13*13,26*26,52*52)的feature map进行预测。
有别于yolov2,这里作者将每个grid cell预测的边框数从yolov2的5个减为yolov3的3个。最终输出的tensor维度为N × N × [3 ∗ (4 + 1 + 80)] 。其中N为feature map的长宽,3表示3个预测的边框,4表示边框的tx,ty,tw,th,1表示预测的边框的置信度,80表示分类的类别数。
和yolov2一样,anchor的大小作者还是使用kmeans聚类得出。在coco数据集上的9个anchor大小分别为:(10× 13); (16× 30); (33× 23); (30× 61); (62× 45); (59×119); (116 × 90); (156 × 198); (373 × 326)
其中在yolov3中,最终有3个分支输出做预测,输出的特征图大小分别为13*13,26*26,52*52,每个特征图使用3个anchor,
13*13的特征图使用(116 × 90); (156 × 198); (373 × 326);这3个anchor
26*26的特征图使用(30× 61); (62× 45); (59×119);这3个anchor
52*52的特征图使用(10× 13); (16× 30); (33× 23);这3个anchor
而在yolov3-tiny中,一共有6个anchor,(10,14), ( 23,27), (37,58), (81,82), (135,169), (344,319),
yolov3-tiny最终有2给分支输出作预测,特征图大小分别为13*13,26*26。每个特征图使用3个anchor做预测。
13*13的特征图使用(81,82), (135,169), (344,319)这3个anchor
26*26的特征图使用( 23,27), (37,58), (81,82)这3个anchor
plus:
faster rcnn:3个scale(128*128,256*256,512*512),3个aspect ratio(1:1,1:2,2:1)共9个anchor
ssd:5个aspect ratio(1:1,1:2,1:3,2:1,3:1),再加一个中间的default box,一共6个anchor
yolov3:一共9个anchor
tiny-yolov3:一共6个anchor
FPN:5个scale(32*32; 64*64; 128*128; 256*256; 512*512),3个aspect ratio(1:1,1:2,2:1),共15个anchor
ctpn:anchor宽度固定为16,高度为11-283之间的10个数,每次处以0.7得到,最终得到[11, 16, 23, 33, 48, 68, 97, 139, 198, 283]共10个anchor
plus:
假设都是用voc数据集
faster rcnn:最后的输出层分类部分的全连接层输出的个数是21。虽然faster已经先经过前面的RPN的2分类,过滤掉了大部分背景类别,但是后续仍然有可能存在背景类别。
SSD:分类的类别为21类,因为,使用softmax loss,肯定会有一个值最大,所以必须得加背景类别。
yolov3:20类,因为使用的是多个sigmoid来代替softmax,本质上每一个sigmoid都是前景,背景分类问题。
使用多尺度融合的策略,使得yolov3的召回率和准确性都有大的提升。
Backbone骨架:
和yolov2的19层的骨架(Darknet-19 )不同,yolov3中,作者提出了53层的骨架(Darknet-53 ),并且借鉴了ResNet的shortcut结构。
上图为论文中的网络结构,但是卷积层只有52层,和作者实际的程序还是有点出入。为此,自己根据作者的程序撸了一个,主干网络还是52层。
一个需要注意的地方,yolov3-tiny 有max pooling,而yolov3使用stride=2的卷积代替pooling操作
yolov3-tiny:
yolov3:
精度vs速度:
Yolov3的精度和速度都达到的空前的高快。
在分类任务中,以darknet-53的骨架网络,速度是ResNet-152的2倍,精度也基本相当。
在检测任务中,当IOU标准定为0.5时,只比RetinaNet低3.2%个点。在IOU标准定为0.75时,比RetinaNet低9.7%个点。其实这个问题也是yolo一直存在的一个问题,在相对比较小的检测物体上,会存在检测框不是很准的想象。速度方面比RetinaNet快出3倍多。
RUN:(测试显卡为P40)
git clone https://github.com/pjreddie/darknet cd darknet Make -j32 wget https://pjreddie.com/media/files/yolov3.weights wget https://pjreddie.com/media/files/yolov3-tiny.weights ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
./darknet detect cfg/yolov3-tiny.cfg yolov3-tiny.weights data/dog.jpg
训练自己数据:
这里假定我要实现一个简单的3个类别检测(3个类别)。
(1)首先就是数据集的准备,这里建议使用python+QT开发的抠图小工具,labelImg。保存的时候可以选择保存为voc格式,也可以保存为yolo格式。建议保存为VOC格式,因为格式更加标准通用。
(2)模仿VOC的格式建立相应的文件夹,执行,
cd darknet mkdir VOCdevkit cd VOCdevkit mkdir VOC2019 mkdir Annotations ImageSets JPEGImages labels cd ImageSets/ mkdir Main
tree -d
目录结构显示如下,
其中,VOC2019为我自己的数据集起的名字,你也可以起别的名字,Annotations存放XML文件,Main中存放,train.txt,val.txt,test.txt,txt中只写图片的名字,一行一个。JPEGImages中存放图片。labels中存放由XML生成的txt文件。
(3)修改scripts下面的voc_label.py,将数据集的目录修改为自己的目录,
开始几行 sets=[('2019', 'train'), ('2019', 'val'),('2019', 'test')] classes = ["apple", "banana", "orange"] 最后2行 os.system("cat 2019_train.txt > train.txt") os.system("cat 2019_train.txt > train.all.txt")
然后执行
Python3 scripts/voc_label.py
就会生成labels文件夹,以及文件夹下面的txt标记,以及train.txt 和train.all.txt
其中,train.txt中存储路径+图片名,一行一个
/data/darknet/VOCdevkit/VOC2019/JPEGImages/55000087.jpg /data/darknet/VOCdevkit/VOC2019/JPEGImages/43000097.jpg /data/darknet/VOCdevkit/VOC2019/JPEGImages/14000107.jpg
Labels文件夹下每个图片对应一个txt文件,里面存储类别 框坐标的归一化值
2 0.368896484375 0.14908854166666666 0.03076171875 0.03515625 2 0.328125 0.18359375 0.0283203125 0.03515625 0 0.190185546875 0.6207682291666666 0.03173828125 0.026692708333333332 1 0.40625 0.21028645833333331 0.193359375 0.16666666666666666
(4)修改,cfg/voc.data
class为训练的类别数
train为训练集train.txt
valid为验证集val.txt
names为voc.names,里面为自己训练的目标名称
backup为weights的存储位置
classes= 3 train = /DATA/darknet/VOCdevkit/2019_train.txt valid = /DATA/darknet/VOCdevkit/2019_test.txt names = /DATA/darknet/data/voc.names backup = /DATA/darknet/weights
(5)修改cfg/yolov3.cfg
修改每个classes=3(610,696,783共3处修改)
修改最后一个卷基层,filters和最后一个region的classes,num参数是因为yolov3有3给分支,每个分支3个anchor。
其中,filters=num×(classes + coords + 1)=3*(3+4+1)=24,这里我有3个类别。(603,689,776行,共3处修改)
(6)执行下面的语句进行训练
./darknet detector train ./cfg/voc.data ./cfg/yolov3.cfg ./ yolov3.weights -clear
-clear参数可以加载作者的预训练模型,重新进行微调训练。
训练完毕就可以生成weights文件,
(7)测试,执行下面语句,
./darknet detect ./cfg/yolov3.cfg weights/yolov3_final.weights 1.jpg
(8)anchor修改,根据自己的数据集重新kmeans设置anchor,自己撸的程序
import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs from sklearn.cluster import KMeans from sklearn import metrics import xml.etree.ElementTree as ET import os def parse_xml(xmlpath,train_input_width,train_input_height): tree = ET.parse(xmlpath) root = tree.getroot() for size in root.iter('size'): width_text = int(size.find('width').text) height_text = int(size.find('height').text) width_list=[] height_list=[] for box in root.iter('bndbox'): x1 = int(box.find('xmin').text) y1 = int(box.find('ymin').text) x2 = int(box.find('xmax').text) y2 = int(box.find('ymax').text) width=(x2-x1)/width_text*train_input_width#经过resize后的长宽 height=(y2-y1)/height_text*train_input_height#经过resize后的长宽 width_list.append(width) height_list.append(height) return width_list,height_list xml_path_lists=["./VOC2012/Annotations/","./VOC2017/Annotations/"]#xml位置 kmeans_num=6#聚类类别数 train_input_width=320#训练网络输入图片宽度 train_input_height=320#训练网络输入图片高度 width_list_all=[] height_list_all=[] for xml_path in xml_path_lists: for xml in os.listdir(xml_path): width_list,height_list=parse_xml(xml_path+xml,train_input_width,train_input_height) width_list_all.extend(width_list) height_list_all.extend(height_list) plt.scatter(width_list_all, height_list_all, marker='o') # 假设暂不知道y类别,不设置c=y,使用kmeans聚类 plt.show() kmeans = KMeans(n_clusters=kmeans_num, random_state=9).fit(list(zip(width_list_all,height_list_all))) y_pred = KMeans(n_clusters=kmeans_num, random_state=9).fit_predict(list(zip(width_list_all,height_list_all))) plt.scatter(width_list_all, height_list_all, c=y_pred) plt.show() print (kmeans.cluster_centers_) print(metrics.calinski_harabaz_score(list(zip(width_list_all,height_list_all)), y_pred))
最终输出结果,
官方程序:
''' Created on Feb 20, 2017 @author: jumabek ''' from os import listdir from os.path import isfile, join import argparse #import cv2 import numpy as np import sys import os import shutil import random import math width_in_cfg_file = 416. height_in_cfg_file = 416. def IOU(x,centroids): similarities = [] k = len(centroids) for centroid in centroids: c_w,c_h = centroid w,h = x if c_w>=w and c_h>=h: similarity = w*h/(c_w*c_h) elif c_w>=w and c_h<=h: similarity = w*c_h/(w*h + (c_w-w)*c_h) elif c_w<=w and c_h>=h: similarity = c_w*h/(w*h + c_w*(c_h-h)) else: #means both w,h are bigger than c_w and c_h respectively similarity = (c_w*c_h)/(w*h) similarities.append(similarity) # will become (k,) shape return np.array(similarities) def avg_IOU(X,centroids): n,d = X.shape sum = 0. for i in range(X.shape[0]): #note IOU() will return array which contains IoU for each centroid and X[i] // slightly ineffective, but I am too lazy sum+= max(IOU(X[i],centroids)) return sum/n def write_anchors_to_file(centroids,X,anchor_file): f = open(anchor_file,'w') anchors = centroids.copy() print(anchors.shape) for i in range(anchors.shape[0]): anchors[i][0]*=width_in_cfg_file/32. anchors[i][1]*=height_in_cfg_file/32. widths = anchors[:,0] sorted_indices = np.argsort(widths) print('Anchors = ', anchors[sorted_indices]) for i in sorted_indices[:-1]: f.write('%0.2f,%0.2f, '%(anchors[i,0],anchors[i,1])) #there should not be comma after last anchor, that's why f.write('%0.2f,%0.2f\n'%(anchors[sorted_indices[-1:],0],anchors[sorted_indices[-1:],1])) f.write('%f\n'%(avg_IOU(X,centroids))) print() def kmeans(X,centroids,eps,anchor_file): N = X.shape[0] iterations = 0 k,dim = centroids.shape prev_assignments = np.ones(N)*(-1) iter = 0 old_D = np.zeros((N,k)) while True: D = [] iter+=1 for i in range(N): d = 1 - IOU(X[i],centroids) D.append(d) D = np.array(D) # D.shape = (N,k) print("iter {}: dists = {}".format(iter,np.sum(np.abs(old_D-D)))) #assign samples to centroids assignments = np.argmin(D,axis=1) if (assignments == prev_assignments).all() : print("Centroids = ",centroids) write_anchors_to_file(centroids,X,anchor_file) return #calculate new centroids centroid_sums=np.zeros((k,dim),np.float) for i in range(N): centroid_sums[assignments[i]]+=X[i] for j in range(k): centroids[j] = centroid_sums[j]/(np.sum(assignments==j)) prev_assignments = assignments.copy() old_D = D.copy() def main(argv): parser = argparse.ArgumentParser() parser.add_argument('-filelist', default = '\\path\\to\\voc\\filelist\\train.txt', help='path to filelist\n' ) parser.add_argument('-output_dir', default = 'generated_anchors/anchors', type = str, help='Output anchor directory\n' ) parser.add_argument('-num_clusters', default = 0, type = int, help='number of clusters\n' ) args = parser.parse_args() if not os.path.exists(args.output_dir): os.mkdir(args.output_dir) f = open(args.filelist) lines = [line.rstrip('\n') for line in f.readlines()] annotation_dims = [] size = np.zeros((1,1,3)) for line in lines: line = line.replace('JPEGImages','labels') line = line.replace('.jpg','.txt') line = line.replace('.png','.txt') print(line) f2 = open(line) for line in f2.readlines(): line = line.rstrip('\n') w,h = line.split(' ')[3:] #print(w,h) annotation_dims.append(tuple(map(float,(w,h)))) annotation_dims = np.array(annotation_dims) eps = 0.005 if args.num_clusters == 0: for num_clusters in range(1,11): #we make 1 through 10 clusters anchor_file = join( args.output_dir,'anchors%d.txt'%(num_clusters)) indices = [ random.randrange(annotation_dims.shape[0]) for i in range(num_clusters)] centroids = annotation_dims[indices] kmeans(annotation_dims,centroids,eps,anchor_file) print('centroids.shape', centroids.shape) else: anchor_file = join( args.output_dir,'anchors%d.txt'%(args.num_clusters)) indices = [ random.randrange(annotation_dims.shape[0]) for i in range(args.num_clusters)] centroids = annotation_dims[indices] kmeans(annotation_dims,centroids,eps,anchor_file) print('centroids.shape', centroids.shape) if __name__=="__main__": main(sys.argv)
输出结果,
2个结果有一些差异,但是相差不是很大。
Python接口:
Python/darknet.py
注意这里Python检测输出的结果为中心坐标和宽高。
原始的接口读取图片为作者自己的结构体IMAGE方式,这里增加numpy转IMAGE的接口。
1、在darkenet.py中自定义一个函数,大概48行
def nparray_to_image(img): data = img.ctypes.data_as(POINTER(c_ubyte)) image = ndarray_image(data, img.ctypes.shape, img.ctypes.strides) return image
2、在darknet.py中增加如下行代码,大概127行
ndarray_image = lib.ndarray_to_image ndarray_image.argtypes = [POINTER(c_ubyte), POINTER(c_long), POINTER(c_long)] ndarray_image.restype = IMAGE
3、在src/image.c中增加如下代码段,增加位置大概550行,
#ifdef NUMPY image ndarray_to_image(unsigned char* src, long* shape, long* strides) { int h = shape[0]; int w = shape[1]; int c = shape[2]; int step_h = strides[0]; int step_w = strides[1]; int step_c = strides[2]; image im = make_image(w, h, c); int i, j, k; int index1, index2 = 0; for(i = 0; i < h; ++i){ for(k= 0; k < c; ++k){ for(j = 0; j < w; ++j){ index1 = k*w*h + i*w + j; index2 = step_h*i + step_w*j + step_c*k; //fprintf(stderr, "w=%d h=%d c=%d step_w=%d step_h=%d step_c=%d \n", w, h, c, step_w, step_h, step_c); //fprintf(stderr, "im.data[%d]=%u data[%d]=%f \n", index1, src[index2], index2, src[index2]/255.); im.data[index1] = src[index2]/255.; } } } rgbgr_image(im); return im; } #endif
4、在src/image.h的23行后面加如下代码
#ifdef NUMPY image ndarray_to_image(unsigned char* src, long* shape, long* strides); #endif
5、在makefile的47行后面中加如下代码
ifeq ($(NUMPY), 1) COMMON+= -DNUMPY -I/usr/include/python3.6/ -I /usr/lib/python3/dist-packages/numpy/core/include/numpy/ CFLAGS+= -DNUMPY Endif
在makefile的第1行后面中加如下代码NUMPY =1
CUDNN=1 OPENCV=1 OPENMP=0 NUMPY=1 DEBUG=0
6、重新编译make clean + make
7、修改darknet.py的后续处理
if __name__ == "__main__": net = load_net(b"cfg/yolov3.cfg", b"yolov3.weights", 0) meta = load_meta(b"cfg/coco.data") image = cv2.imread(b'data/dog.jpg') im=nparray_to_image(image) r = detect(net, meta, im) print(r) for newbox in r: p1 = (int(newbox[0]), int(newbox[1])) p2 = (int(newbox[2]), int(newbox[3])) cv2.rectangle(image, p1, p2, (255,0,0)) cv2.imshow('tracking', image) cv2.waitKey()
References:
https://pjreddie.com/darknet/yolo/
https://github.com/pjreddie/darknet
-
YOLOv3
2020-04-16 22:38:26一、 YOLOv2+YOLO9000 二、YOLOv3论文内容结构 1、Absract 三、YOLOv3改进部分 1、loss改进 (1) 交叉熵: (2) yoloV3的loss: (3) yoloV1的loss 2、YOLOv3网络结构 四、YOLOv3结果分析 ...YOLOv3
一、前期知识储备
(一) YOLOv2+YOLO9000
(二) YOLOv3论文内容结构
1、Absract
(三) YOLOv3改进部分
1、loss改进
(1) 交叉熵:
(2) yoloV3的loss:
(3) yoloV1的loss
2、YOLOv3网络结构
(1)由一个11的卷积核和一个33的卷积核构成残差块,有跳层连接。每一个卷积后链接BN层和激活函数
(2)多尺度预测
YOLOv1只利用了最后一个输出特征来预测信息
YOLOv3利用了三个尺度的特征来预测信息,并且进行了特征融合,每个尺寸对应不同大小的anchor
二、论文精读
(一) YOLOv3先验框(bounding box priors)
yolov1无先验框,yolov2、yolov3借鉴fasterRCNN anchor框的概念效果较好。
(二) YOLOv3网络结构
具体详情:
本地:yolov3网络结构.pdf&&yolov3.pdf
(一) YOLOv3损失函数
(二) YOLOv3网络训练
三、代码实现
https://www.jianshu.com/p/3fddf7c08a58
-
YOLOV3
2019-03-21 21:39:23YOLOV3 YOLO v3网络优点 相比于YOLO v2网络,在保持速度优势的前提下,提升了预测精度,尤其是加强了对小物体的识别能力。 YOLO v3对相对于v1和v2的改进 将多个好的方案融合到YOLO里面 基于Darknet-53网络结构 ...YOLOV3
YOLO v3网络优点
相比于YOLO v2网络,在保持速度优势的前提下,提升了预测精度,尤其是加强了对小物体的识别能力 。
YOLO v3对相对于v1和v2的改进
将多个好的方案融合到YOLO里面
- 基于Darknet-53网络结构
- 使用13*13、26*26、52*52的三个尺度特征进行对象检测
- 在COCO数据集采用9个先验框,大框的先验框尺寸较大,小框则较小
- 最后的分类方法,由softmax改成logistic
YOLO v3网络模型
YOLO v3网络结构
如下,下述网络结构顺序中没有画出归一化过程,具体的归一化过程如上图的 BN 操作。没有全连接层的darknet-53为下图的1x、2x、8x、8x、4x这块网络。
网络搜集代码链接
-
深入浅出Yolo系列之Yolov3&Yolov4&Yolov5核心基础知识完整讲解
2020-05-20 23:45:24因为工作原因,项目中经常遇到目标检测的任务,因此对目标检测算法会经常使用和关注,比如Yolov3、Yolov4算法。 当然,实际项目中很多的第一步,也都是先进行目标检测任务,比如人脸识别、多目标追踪、REID、客流...因为工作原因,项目中经常遇到目标检测的任务,因此对目标检测算法会经常使用和关注,比如Yolov3、Yolov4算法、Yolov5算法。
当然,实际项目中很多的第一步,也都是先进行目标检测任务,比如人脸识别、多目标追踪、REID、客流统计等项目。因此目标检测是计算机视觉项目中非常重要的一部分。
从2018年Yolov3年提出的两年后,在原作者声名放弃更新Yolo算法后,俄罗斯的Alexey大神扛起了Yolov4的大旗,然后不久又出现了Yolov5。
因为项目中Yolov3、Yolov4、Yolov5使用很多,所以大白将项目中,需要了解的Yolov3、Yolov4、Yolov5系列相关知识点以及相关代码进行完整的汇总,希望和大家共同学习探讨。
同时,大白每周会整理几十个人工智能公众号的精华文章,并系统的分类,让大家对于人工智能行业每周的内容动态可以一目了然,点击查看。
版权申明:本文包含图片,都为大白使用PPT所绘制的,如需网络结构高清图和模型权重,可点击查看下载。
1 论文汇总
Yolov3论文名:《Yolov3: An Incremental Improvement》
Yolov3论文地址:https://arxiv.org/pdf/1804.02767.pdfYolov4论文名:《Yolov4: Optimal Speed and Accuracy of Object Detection》
Yolov4论文地址:https://arxiv.org/pdf/2004.10934.pdf
2 Yolov3核心基础内容
2.1 网络结构可视化
Yolov3是目标检测Yolo系列非常非常经典的算法。
不过很多同学拿到Yolov3或者Yolov4的cfg文件时,并不知道如何直观的可视化查看网络结构。如果纯粹看cfg里面的内容,肯定会一脸懵逼。
其实可以很方便的用netron查看Yolov3的网络结构图,一目了然。
这里不多说,如果需要安装,可以移步大白的另一篇文章:《网络可视化工具netron详细安装流程》
如果不想安装,也可以直接点击此链接,查看Yolov3可视化流程图。2.2 网络结构图
绘制网络结构图受到Yolov3另一位作者文章的启发,包括下面Yolov4的结构图,从总体框架上先了解了Yolov3的流程,再针对去学习每一小块的知识点,会事半功倍。
上图三个蓝色方框内表示Yolov3的三个基本组件:
(1)CBL:Yolov3网络结构中的最小组件,由Conv+Bn+Leaky_relu激活函数三者组成。
(2)Res unit:借鉴Resnet网络中的残差结构,让网络可以构建的更深。
(3)ResX:由一个CBL和X个残差组件构成,是Yolov3中的大组件。每个Res模块前面的CBL都起到下采样的作用,因此经过5次Res模块后,得到的特征图是608->304->152->76->38->19大小。其他基础操作:
(1)Concat:张量拼接,会扩充两个张量的维度,例如26×26×256和26×26×512两个张量拼接,结果是26×26×768。Concat和cfg文件中的route功能一样。
(2)Add:张量相加,张量直接相加,不会扩充维度,例如104×104×128和104×104×128相加,结果还是104×104×128。add和cfg文件中的shortcut功能一样。Backbone中卷积层的数量:
每个ResX中包含1+2×X个卷积层,因此整个主干网络Backbone中一共包含1+(1+2×1)+(1+2×2)+(1+2×8)+(1+2×8)+(1+2×4)=52,再加上一个FC全连接层,即可以组成一个Darknet53分类网络。不过在目标检测Yolov3中,去掉FC层,不过为了方便称呼,仍然把Yolov3的主干网络叫做Darknet53结构。2.3 核心基础内容
Yolov3是2018年发明提出的,这成为了目标检测one-stage中非常经典的算法,包含Darknet-53网络结构、anchor锚框、FPN等非常优秀的结构。
本文主要目的在于描述Yolov4和Yolov3算法的不同及创新之处,对Yolov3的基础不过多描述。
不过大白也正在准备Yolov3算法非常浅显易懂的基础视频课程,让小白也能简单清楚的了解Yolov3的整个过程及各个算法细节,制作好后会更新到此处,便于大家查看。
在准备课程过程中,大白搜集查看了网络上几乎所有的Yolov3资料,在此整理几个非常不错的文章及视频,大家也可以点击查看,学习相关知识。
(1)视频:吴恩达目标检测Yolo入门讲解
https://www.bilibili.com/video/BV1N4411J7Y6?from=search&seid=18074481568368507115
(2)文章:Yolo系列之Yolov3【深度解析】
https://blog.csdn.net/leviopku/article/details/82660381
(3)文章:一文看懂Yolov3
https://blog.csdn.net/litt1e/article/details/88907542
相信大家看完,对于Yolov3的基础知识点会有一定的了解。
3 Yolov3相关代码
3.1 python代码
代码地址:https://github.com/ultralytics/Yolov3
3.2 C++代码
这里推荐Yolov4作者的darknetAB代码,代码和原始作者代码相比,进行了很多的优化,如需要运行Yolov3网络,加载cfg时,使用Yolov3.cfg即可
代码地址:https://github.com/AlexeyAB/darknet3.3 python版本的Tensorrt代码
除了算法研究外,实际项目中还需要将算法落地部署到工程上使用,比如GPU服务器使用时还需要对模型进行tensorrt加速。
(1)Tensort中的加速案例
强烈推荐tensort软件中,自带的Yolov3加速案例,路径位于tensorrt解压文件夹的TensortX/samples/python/Yolov3_onnx中
针对案例中的代码,如果有不明白的,也可参照下方文章上的详细说明:
代码讲解文章:https://www.cnblogs.com/shouhuxianjian/p/10550262.html
(2)Github上的tensorrt加速
除了Tensorrt软件中的代码, Github上也有其他作者的开源代码
代码地址:https://github.com/lewes6369/TensorRT-Yolov33.4 C++版本的Tensorrt代码
项目的工程部署上,如果使用C++版本进行Tensorrt加速,一方面可以参照Alexey的Github代码,另一方面也可以参照下面其他作者的开源代码
代码地址:https://github.com/wang-xinyu/tensorrtx/tree/master/Yolov3
4 YoloV4核心基础内容
4.1 网络结构可视化
Yolov4的网络结构也可以使用netron工具查看,大白也是对照其展示的可视化流程图绘制的下方网络结构图。
netron可视化显示Yolov4网络结构可以参照大白的另一篇文章:《netron可视化网络结构详细安装流程》
如果不想安装,也可以直接点击此链接,查看Yolov4可视化流程图。4.2 网络结构图
Yolov4的结构图和Yolov3相比,因为多了CSP结构,PAN结构,如果单纯看可视化流程图,会觉得很绕,但是在绘制出上面的图形后,会觉得豁然开朗,其实整体架构和Yolov3是相同的,不过使用各种新的算法思想对各个子结构都进行了改进。
先整理下Yolov4的五个基本组件:
1. CBM:Yolov4网络结构中的最小组件,由Conv+Bn+Mish激活函数三者组成。
2. CBL:由Conv+Bn+Leaky_relu激活函数三者组成。
3. Res unit:借鉴Resnet网络中的残差结构,让网络可以构建的更深。
4. CSPX:借鉴CSPNet网络结构,由卷积层和X个Res unint模块Concat组成。
5. SPP:采用1×1,5×5,9×9,13×13的最大池化的方式,进行多尺度融合。其他基础操作:
1. Concat:张量拼接,维度会扩充,和Yolov3中的解释一样,对应于cfg文件中的route操作。
2. Add:张量相加,不会扩充维度,对应于cfg文件中的shortcut操作。Backbone中卷积层的数量:
和Yolov3一样,再来数一下Backbone里面的卷积层数量。
每个CSPX中包含5+2×X个卷积层,因此整个主干网络Backbone中一共包含1+(5+2×1)+(5+2×2)+(5+2×8)+(5+2×8)+(5+2×4)=72。
这里大白有些疑惑,按照Yolov3设计的传统,72个卷积层,加上最后的一个全连接层,主干网络的名字不应该叫CSPDarknet73吗????4.3 核心基础内容
Yolov4本质上和Yolov3相差不大,可能有些人会觉得失望。
但我觉得算法创新分为三种方式:
(1)第一种:面目一新的创新,比如Yolov1、Faster-RCNN、Centernet等,开创出新的算法领域,不过这种也是最难的。
(2)第二种:守正出奇的创新,比如将图像金字塔改进为特征金字塔。
(3)第三种:各种先进算法集成的创新,比如不同领域发表的最新论文的tricks,集成到自己的算法中,却发现有出乎意料的改进。
Yolov4既有第二种也有第三种创新,组合尝试了大量深度学习领域最新论文的20多项研究成果,而且不得不佩服的是作者Alexey在Github代码库维护的频繁程度。
目前Yolov4代码的Star数量已经1万左右,据我所了解,目前超过这个数量的,目标检测领域只有Facebook的Detectron(v1-v2)、和Yolo(v1-v3)官方代码库(已停止更新)。
所以Yolov4中的各种创新方式,大白觉得还是很值得仔细研究的。为了便于分析,将Yolov4的整体结构拆分成四大板块:
大白主要从以上4个部分对YoloV4的创新之处进行讲解,让大家一目了然。(1)输入端:这里指的创新主要是训练时对输入端的改进,主要包括Mosaic数据增强、cmBN、SAT自对抗训练。
(2)BackBone主干网络:将各种新的方式结合起来,包括:CSPDarknet53、Mish激活函数、Dropblock
(3)Neck:目标检测网络在BackBone和最后的输出层之间往往会插入一些层,比如Yolov4中的SPP模块、FPN+PAN结构
(4)Prediction:输出层的锚框机制和Yolov3相同,主要改进的是训练时的损失函数CIOU_Loss,以及预测框筛选的nms变为DIOU_nms
总体来说,Yolov4对Yolov3的各个部分都进行了改进优化,下面丢上作者的算法对比图。
仅对比Yolov3和Yolov4,在COCO数据集上,同样的FPS等于83左右时,Yolov4的AP是43,而Yolov3是33,直接上涨了10个百分点。
不得不服,当然可能针对具体不同的数据集效果也不一样,但总体来说,改进效果是很优秀的,下面大白对Yolov4的各个创新点继续进行深挖。4.3.1 输入端创新
考虑到很多同学GPU显卡数量并不是很多,Yolov4对训练时的输入端进行改进,使得训练在单张GPU上也能有不错的成绩。比如数据增强Mosaic、cmBN、SAT自对抗训练。
但感觉cmBN和SAT影响并不是很大,所以这里主要讲解Mosaic数据增强。(1)Mosaic数据增强
Yolov4中使用的Mosaic是参考2019年底提出的CutMix数据增强的方式,但CutMix只使用了两张图片进行拼接,而Mosaic数据增强则采用了4张图片,随机缩放、随机裁剪、随机排布的方式进行拼接。
这里首先要了解为什么要进行Mosaic数据增强呢?
在平时项目训练时,小目标的AP一般比中目标和大目标低很多。而Coco数据集中也包含大量的小目标,但比较麻烦的是小目标的分布并不均匀。
首先看下小、中、大目标的定义:
2019年发布的论文《Augmentation for small object detection》对此进行了区分
可以看到小目标的定义是目标框的长宽0×0~32×32之间的物体。
但在整体的数据集中,小、中、大目标的占比并不均衡。
如上表所示,Coco数据集中小目标占比达到41.4%,数量比中目标和大目标都要多。
但在所有的训练集图片中,只有52.3%的图片有小目标,而中目标和大目标的分布相对来说更加均匀一些。
针对这种状况,Yolov4的作者采用了Mosaic数据增强的方式。
主要有几个优点:
a. 丰富数据集:随机使用4张图片,随机缩放,再随机分布进行拼接,大大丰富了检测数据集,特别是随机缩放增加了很多小目标,让网络的鲁棒性更好。
b. 减少GPU:可能会有人说,随机缩放,普通的数据增强也可以做,但作者考虑到很多人可能只有一个GPU。
因此Mosaic增强训练时,可以直接计算4张图片的数据,使得Mini-batch大小并不需要很大,一个GPU就可以达到比较好的效果。
此外,发现另一研究者的训练方式也值得借鉴,采用的数据增强和Mosaic比较类似,也是使用4张图片(不是随机分布),但训练计算loss时,采用“缺啥补啥”的思路:
如果上一个iteration中,小物体产生的loss不足(比如小于某一个阈值),则下一个iteration就用拼接图;否则就用正常图片训练,也很有意思。
参考链接:https://www.zhihu.com/question/390191723?rf=3901940814.3.2 BackBone创新
(1)CSPDarknet53
CSPDarknet53是在Yolov3主干网络Darknet53的基础上,借鉴2019年CSPNet的经验,产生的Backbone结构,其中包含了5个CSP模块。
这里因为CSP模块比较长,不放到本处,大家也可以点击Yolov4的netron网络结构图,对比查看,一目了然。
每个CSP模块前面的卷积核的大小都是3×3,步长为2,因此可以起到下采样的作用。
因为Backbone有5个CSP模块,输入图像是608*608,所以特征图变化的规律是:608->304->152->76->38->19
经过5次CSP模块后得到19*19大小的特征图。
而且作者只在Backbone中采用了Mish激活函数,网络后面仍然采用Leaky_relu激活函数。
我们再看看下作者为啥要参考2019年的CSPNet,采用CSP模块?
CSPNet论文地址:https://arxiv.org/pdf/1911.11929.pdf
CSPNet全称是Cross Stage Paritial Network,主要从网络结构设计的角度解决推理中从计算量很大的问题。
CSPNet的作者认为推理计算过高的问题是由于网络优化中的梯度信息重复导致的。
因此采用CSP模块先将基础层的特征映射划分为两部分,然后通过跨阶段层次结构将它们合并,在减少了计算量的同时可以保证准确率。
因此Yolov4在主干网络Backbone采用CSPDarknet53网络结构,主要有三个方面的优点:
优点一:增强CNN的学习能力,使得在轻量化的同时保持准确性。
优点二:降低计算瓶颈
优点三:降低内存成本(2)Mish激活函数
Mish激活函数是2019年下半年提出的激活函数
论文地址:https://arxiv.org/abs/1908.08681
和leaky_relu激活函数的图形对比如下:
Yolov4的Backbone中都使用了Mish激活函数,而后面的网络则还是使用Leaky_relu函数。
Yolov4作者实验测试时,使用CSPDarknet53网络在ImageNet数据集上做图像分类任务,发现使用了Mish激活函数的TOP-1和TOP-5的精度比没有使用时都略高一些。
因此在设计Yolov4目标检测任务时,主干网络Backbone还是使用Mish激活函数。(3)Dropblock
Yolov4中使用的Dropblock,其实和常见网络中的Dropout功能类似,也是缓解过拟合的一种正则化方式。
Dropblock在2018年提出,论文地址:https://arxiv.org/pdf/1810.12890.pdf传统的Dropout很简单,一句话就可以说的清:随机删除减少神经元的数量,使网络变得更简单。
而Dropblock和Dropout相似,比如下图:中间Dropout的方式会随机的删减丢弃一些信息,但Dropblock的研究者认为,卷积层对于这种随机丢弃并不敏感.
因为卷积层通常是三层连用:卷积+激活+池化层,池化层本身就是对相邻单元起作用。
而且即使随机丢弃,卷积层仍然可以从相邻的激活单元学习到相同的信息。因此,在全连接层上效果很好的Dropout在卷积层上效果并不好。
所以右图Dropblock的研究者则干脆整个局部区域进行删减丢弃。
这种方式其实是借鉴2017年的Cutout数据增强的方式,cutout是将输入图像的部分区域清零,而Dropblock则是将Cutout应用到每一个特征图。而且并不是用固定的归零比率,而是在训练时以一个小的比率开始,随着训练过程线性的增加这个比率。
Dropblock的研究者与Cutout数据增强对训练效果进行对比验证时,发现有几个优点:
优点一:Dropblock的效果优于Cutout
优点二:cutout只能作用于输入层,而Dropblock则是将Cutout应用到网络中的每一个特征图上
优点三:Dropblock可以定制各种组合,在训练的不同阶段可以修改删减的概率,从空间层面和时间层面,和cutout相比都有更精细的改进。
Yolov4中直接采用了更优的Dropblock,对网络的正则化过程进行了全面的升级改进。4.3.3 Neck创新
在目标检测领域,为了更好的提取融合特征,通常在Backbone和输出层,会插入一些层,这个部分称为Neck。相当于目标检测网络的颈部,也是非常关键的。
Yolov4的Neck结构主要采用了SPP模块、FPN+PAN的方式。(1)SPP模块
SPP模块,其实在Yolov3中已经存在了,在Yolov4的C++代码文件夹中有一个Yolov3_spp版本,但有的同学估计从来没有使用过,在Yolov4中,SPP模块仍然是在Backbone主干网络之后:
作者在SPP模块中,使用k={1×1,5×5,9×9,13×13}的最大池化的方式,再将不同尺度的特征图进行Concat操作。
注意:这里最大池化采用padding操作,移动的步长为1,比如13×13的输入特征图,使用5×5大小的池化核池化,padding=2,因此池化后的特征图仍然是13×13大小。
在2019年的《DC-SPP-Yolo》文章:https://arxiv.org/ftp/arxiv/papers/1903/1903.08589.pdf
也对Yolo目标检测的SPP模块进行了对比测试。
和Yolov4作者的研究相同,采用SPP模块的方式,比单纯的使用k×k最大池化的方式,更有效的增加主干特征的接收范围,显著的分离了最重要的上下文特征。
Yolov4的作者在使用608×608大小的图像进行测试时发现,在COCO目标检测任务中,以0.5%的额外计算代价将AP50增加了2.7%,因此Yolov4中也采用了SPP模块。(2)FPN+PAN
PAN结构比较有意思,看了网上Yolov4关于这个部分的讲解,大多都是讲的比较笼统的,而PAN是借鉴**2018年图像分割领域PANet的创新点,有些同学可能不是很清楚。
下面大白将这个部分拆解开来,看下Yolov3和Yolov4**中是如何设计的。Yolov3各个网络结构
可以看到经过几次下采样,三个紫色箭头指向的地方,输出分别是76×76、38×38、19×19。
以及最后的Prediction中用于预测的三个特征图①19×19×255、②38×38×255、③76×76×255 [注:255表示80类别 (1+4+80)×3=255]。
我们将Neck部分用立体图画出来,更直观的看下两部分之间是如何通过FPN结构融合的。
如图所示,FPN是自顶向下的,将高层的特征信息通过上采样的方式进行传递融合,得到进行预测的特征图。Yolov4各个网络结构
而Yolov4中Neck这部分除了使用FPN外,还在此基础上使用了PAN结构。
前面CSPDarknet53中讲到,每个CSP模块前面的卷积核都是3×3大小,相当于下采样操作。
因此可以看到三个紫色箭头处的特征图是76×76、38×38、19×19。
以及最后Prediction中用于预测的三个特征图:①76×76×255,②38×38×255,③19×19×255。
我们也看下Neck部分的立体图像,看下两部分是如何通过FPN+PAN结构进行融合的。
和Yolov3的FPN层不同,Yolov4在FPN层的后面还添加了一个自底向上的特征金字塔。
其中包含两个PAN结构。
这样结合操作,FPN层自顶向下传达强语义特征,而特征金字塔则自底向上传达强定位特征,两两联手,从不同的主干层对不同的检测层进行特征聚合,这样的操作确实很皮。
FPN+PAN借鉴的是18年CVPR的PANet,当时主要应用于图像分割领域,但Alexey将其拆分应用到Yolov4中,进一步提高特征提取的能力。不过这里需要注意几点:
注意一:
Yolov3的FPN层输出的三个大小不一的特征图①②③直接进行预测
但Yolov4的FPN层,只使用最后的一个76×76特征图①,而经过两次PAN结构,输出预测的特征图②和③。
这里的不同也体现在cfg文件中,这一点有很多同学之前不太明白。
比如Yolov3.cfg中输入时608×608,最后的三个Yolo层中,
第一个Yolo层是最小的特征图19×19,mask=6,7,8,对应最大的anchor box。
第二个Yolo层是中等的特征图38×38,mask=3,4,5,对应中等的anchor box。
第三个Yolo层是最大的特征图76×76,mask=0,1,2,对应最小的anchor box。
而Yolov4.cfg则恰恰相反
第一个Yolo层是最大的特征图76×76,mask=0,1,2,对应最小的anchor box。
第二个Yolo层是中等的特征图38×38,mask=3,4,5,对应中等的anchor box。
第三个Yolo层是最小的特征图19×19,mask=6,7,8,对应最大的anchor box。
注意二:
原本的PANet网络的PAN结构中,两个特征图结合是采用shortcut操作,而Yolov4中则采用concat(route)操作,特征图融合后的尺寸发生了变化。
这里也可以对应Yolov4的netron网络图查看,很有意思。4.3.4 Prediction创新
(1)CIOU_loss
目标检测任务的损失函数一般由Classificition Loss(分类损失函数)和Bounding Box Regeression Loss(回归损失函数)两部分构成。
Bounding Box Regeression的Loss近些年的发展过程是:Smooth L1 Loss-> IoU Loss(2016)-> GIoU Loss(2019)-> DIoU Loss(2020)->CIoU Loss(2020)
我们从最常用的IOU_Loss开始,进行对比拆解分析,看下Yolov4为啥要选择CIOU_Loss。a. IOU_loss
可以看到IOU的loss其实很简单,主要是交集/并集,但其实也存在两个问题。
问题1:即状态1的情况,当预测框和目标框不相交时,IOU=0,无法反应两个框距离的远近,此时损失函数不可导,IOU_Loss无法优化两个框不相交的情况。
问题2:即状态2和状态3的情况,当两个预测框大小相同,两个IOU也相同,IOU_Loss无法区分两者相交情况的不同。
因此2019年出现了GIOU_Loss来进行改进。b. GIOU_loss
可以看到右图GIOU_Loss中,增加了相交尺度的衡量方式,缓解了单纯IOU_Loss时的尴尬。
但为什么仅仅说缓解呢?因为还存在一种不足:
问题:状态1、2、3都是预测框在目标框内部且预测框大小一致的情况,这时预测框和目标框的差集都是相同的,因此这三种状态的GIOU值也都是相同的,这时GIOU退化成了IOU,无法区分相对位置关系。
基于这个问题,2020年的AAAI又提出了DIOU_Loss。c. DIOU_loss
好的目标框回归函数应该考虑三个重要几何因素:重叠面积、中心点距离,长宽比。
针对IOU和GIOU存在的问题,作者从两个方面进行考虑
一:如何最小化预测框和目标框之间的归一化距离?
二:如何在预测框和目标框重叠时,回归的更准确?
针对第一个问题,提出了DIOU_Loss(Distance_IOU_Loss)
DIOU_Loss考虑了重叠面积和中心点距离,当目标框包裹预测框的时候,直接度量2个框的距离,因此DIOU_Loss收敛的更快。
但就像前面好的目标框回归函数所说的,这时并没有考虑到长宽比。
问题:比如上面三种状态,目标框包裹预测框,本来DIOU_Loss可以起作用。
但预测框的中心点的位置都是一样的,因此按照DIOU_Loss的计算公式,三者的值都是相同的。
针对这个问题,又提出了CIOU_Loss,不对不说,科学总是在解决问题中,不断进步!!d. CIOU_loss
CIOU_Loss和DIOU_Loss前面的公式都是一样的,不过在此基础上还增加了一个影响因子,将预测框和目标框的长宽比都考虑了进去。
其中v是衡量长宽比一致性的参数,我们也可以定义为:
这样CIOU_Loss就将目标框回归函数应该考虑三个重要几何因素:重叠面积、中心点距离,长宽比全都考虑进去了。再来综合的看下各个Loss函数的不同点:
IOU_Loss:主要考虑检测框和目标框重叠面积。
GIOU_Loss:在IOU的基础上,解决边界框不重合时的问题。
DIOU_Loss:在IOU和GIOU的基础上,考虑边界框中心点距离的信息。
CIOU_Loss:在DIOU的基础上,考虑边界框宽高比的尺度信息。
Yolov4中采用了CIOU_Loss的回归方式,使得预测框回归的速度和精度更高一些。(2)DIOU_nms
nms主要用于预测框的筛选,常用的目标检测算法中,一般采用普通的nms的方式,Yolov4则借鉴上面D/CIOU loss的论文:https://arxiv.org/pdf/1911.08287.pdf
将其中计算IOU的部分替换成DIOU的方式:
再来看下实际的案例:
在上图重叠的摩托车检测中,中间的摩托车因为考虑边界框中心点的位置信息,也可以回归出来。
因此在重叠目标的检测中,DIOU_nms的效果优于传统的nms。注意:
有读者会有疑问,这里为什么不用CIOU_nms,而用DIOU_nms?
答:因为前面讲到的CIOU_loss,实在DIOU_loss的基础上,添加的影响因子,包含groundtruth标注框的信息,在训练时用于回归。
但在测试过程中,并没有groundtruth的信息,不用考虑影响因子,因此直接用DIOU_nms即可。总体来说,YOLOv4的论文称的上良心之作,将近几年关于深度学习领域最新研究的tricks移植到Yolov4中做验证测试,将Yolov3的精度提高了不少。
虽然没有全新的创新,但很多改进之处都值得借鉴,借用Yolov4作者的总结。Yolov4 主要带来了 3 点新贡献:
(1)提出了一种高效而强大的目标检测模型,使用 1080Ti 或 2080Ti 就能训练出超快、准确的目标检测器。
(2)在检测器训练过程中,验证了最先进的一些研究成果对目标检测器的影响。
(3)改进了 SOTA 方法,使其更有效、更适合单 GPU 训练。
5 YoloV4相关代码
5.1 python代码
代码地址:https://github.com/Tianxiaomo/pytorch-Yolov4
作者的训练和测试推理代码都已经完成5.2 C++代码
Yolov4作者Alexey的代码,俄罗斯的大神,应该是个独立研究员,更新算法的频繁程度令人佩服。
在Yolov3作者Joseph Redmon宣布停止更新Yolo算法之后,Alexey凭借对于Yolov3算法的不断探索研究,赢得了Yolov3作者的认可,发布了Yolov4。
代码地址:https://github.com/AlexeyAB/darknet5.3 python版本的Tensorrt代码
目前测试有效的有tensorflow版本:weights->pb->trt
代码地址:https://github.com/hunglc007/tensorflow-Yolov4-tflite5.4 C++版本的Tensorrtrt代码
代码地址:https://github.com/wang-xinyu/tensorrtx/tree/master/Yolov4
作者自定义了Mish激活函数的Plugin层,Tensorrt加速后速度还是挺快的。6 Yolov5核心基础知识完整讲解
因为Yolov5的核心基础知识点也很多,可以查看大白的另一篇文章《深入浅出Yolov5核心基础知识完整讲解》
7 相关数据集下载
实际项目中,目标检测算法应该的非常多非常多,比如人脸识别,比如疫情期间的口罩人脸识别,比如车流统计,人流统计等等。
因此大白也会将不错的值得一试的数据集汇总到此处,方便需要的同学进行下载。(1)口罩遮挡人脸数据集
数据集详情:由武汉大学多媒体研究中心发起,目前是全球最大的口罩遮挡人脸数据集。
分为真实口罩人脸和模拟口罩人脸两部分,真实口罩人脸包含525人的5000张口罩人脸和9万张正常人脸。模拟口罩人脸包含1万个人共50万张模拟人脸数据集。
应用项目:人脸检测、人脸识别
数据集地址:https://github.com/X-zhangyang/Real-World-Masked-Face-Dataset(2)Wider Face人脸数据集
数据集详情:香港中文大学发起的,包含3万张图片共40万张人脸。
应用项目:人脸检测
数据集地址:http://shuoyang1213.me/WIDERFACE/WiderFace_Results.html(3)Wider Person拥挤场景行人数据集
数据集详情:多种场景比较拥挤场景的行人检测数据集,包含13382张图片,共计40万个不同遮挡程度的人体。
应用项目:人体检测
数据集地址:http://www.cbsr.ia.ac.cn/users/sfzhang/WiderPerson/因为工作原因,会搜集大量的各类公开应用场景数据集,如果有同学需要其他场景或者其他项目的,也可以留言,或者发送邮件到jiangdabai@126.com,也会将对应的数据集更新到此处。
8 不断更新ing
在深度学习的图像领域,肯定会涉及目标检测,而在目标检测中,Yolov3和Yolov4是非常经典,必须要学习的算法。
有些同学,特别新接触的同学,刚学习时会觉得Yolo算法很繁琐。
而且我发现,网上很多的教程其实讲的还是比较笼统,并不适合小白学习。
所以大白也在耗尽洪荒之力,在准备Yolov3和Yolov4及相关的基础入门视频,让大家看完就能明白整体的流程和各种算法细节,大家可以先收藏,后期制作好后会更新到此处。
希望和大家一起努力,在人工智能深度学习领域一起进步,一起提升,一起变强! -
Yolov3&Yolov4&Yolov5模型权重及网络结构图资源下载
2020-08-09 10:27:27(1)Yolov3&Yolov4的《深入浅出Yolo系列之Yolov3&Yolov4核心基础完整讲解》 (2)Yolov5的《深入浅出Yolo系列之Yolov5核心基础完整讲解》 其中提到很多网络模型的权重,由于不是国内资源,很多同学反馈不好... -
目标检测:YOLOv3: 训练自己的数据
2018-03-26 10:59:02(1)文件修改: (A)关于 .data .names 两个文件修改非常简单,参考官网或者群文件YOLOv3.txt连接中的文件。 (B)关于cfg修改,以6类目标检测为例,主要有以下几处调整(蓝色标出),也可参考我上传的文件,... -
yolov3 yolov3-tiny yolov4 yolov-tiny预训练模型下载
2020-09-22 16:38:53yolov3-tiny预训练 yolov3预训练 yolov4 预训练yolov4-tiny预训练模型,全部打包在压缩文件 -
YoLov3训练自己的数据集(小白手册)
2018-08-02 11:00:12工具:labelimg、MobaXterm 1.标注自己的数据集。用labelimg进行标注,保存后会生成与所标注图片文件名相同...2.下载yolov3项目工程。按照YoLo官网下载 git clone https://github.com/pjreddie/darknet cd darkn... -
[YoLoV3目标检测实战] keras+yolov3训练自身口罩检测数据集
2020-02-16 20:30:12[YoLoV3目标检测实战] keras+yolov3训练自身的数据集 本文用keras版本的yolov3来训练人脸口罩数据集,从而完成一个简单的目标检测。 首先先上目标检测效果,准备好了吗? go!go!go! 看到 目标检测的效果之后,... -
DL之YoloV3:YoloV3论文《YOLOv3: An Incremental Improvement》的翻译与解读
2018-12-12 08:50:48DL之YoloV3:YoloV3论文《YOLOv3: An Incremental Improvement》的翻译与解读 目录 YoloV3论文翻译与解读 Abstract 1. Introduction 2. The Deal YoloV3论文翻译与解读 Abstract We present some... -
yolov3,yolov4,yolov5网络架构图
2021-02-19 11:11:47yolov3,yolov4,yolov5网络架构图 Visio 2013绘制 vsdx文件 可编辑 -
yolov3.weights
2020-07-13 10:19:37pytorch yolov3 目标检测 yolov3.weights https://pjreddie.com/media/files/yolov3.weights yolov3 yolov3.weights -
Python-YOLOv3tensorflow用TensorFlow实现的YOLOv3目标检测
2019-08-11 04:05:05YOLOv3 tensorflow:用TensorFlow实现的YOLOv3目标检测 -
YOLOV3的配置文件,yolov3.weights等
2018-11-20 16:27:53YOLO v3的配置文件,模型文件等,包括yolov3.weights,yolov3.cfg,coco.name三个主要文件。 -
yolov3损失函数_目标检测算法之YOLOv3及YOLOv3Tiny
2020-12-12 07:29:49这是我在上面写的一个回答:在这里插入图片描述因此,这一节我们只用关注YOLOv3算法本身,训练的时候将它的损失函数认为和YOLOv2一样就好,Darknet以及很多开源代码都是这样来做的。算法原理YOLOv3应该是现在Y... -
yolov3.cfg
2019-10-12 14:40:01只有一个yolov3.cfg只有一个yolov3.cfg只有一个yolov3.cfg只有一个yolov3.cfg只有一个yolov3.cfg -
YOLOv3网络结构和解析
2019-05-09 23:03:07学了这么久的YOLOv3,把自己的学习心得记录下。欢迎指正! 参考: YOLOv3网络结构细致解析 基于keras-yolov3,原理及代码细节的理解 论文地址:https://pjreddie.com/media/files/papers/YOLOv3.pdf yolov3官网:... -
YOLOv3源码解析3-网络结构YOLOV3()
2019-11-12 14:20:34YOLOv3源码解析1-代码整体结构 YOLOv3源码解析2-数据预处理Dataset() YOLOv3源码解析3-网络结构YOLOV3() YOLOv3源码解析4-计算损失compute_loss() YOLOv3源码解析5-损失函数 理论部分参照大神的文章学习: ...