├── save └── README.md ├── weights └── readme.md ├── demo.mlx ├── images ├── dog.jpg ├── giraffe.jpg ├── mynet.png ├── person.jpg ├── yolov4.jpg ├── lgraphLayer.png ├── lgraphWeight.png ├── rec_result.png ├── yolov4Detect.jpg ├── dogYolov4Detect.jpg ├── importerExporter.png ├── importDarknetLayers.png ├── importDarknetNetwork.png └── importDarknetWeights.png ├── .gitignore ├── utils ├── getClasses.m ├── preprocessTrainData.m ├── getGIOU.m ├── yolov3v4Predict.m ├── importDarknetNetwork.m ├── importDarknetWeights.m ├── exportDarkNetNetwork.m ├── importDarkNetLayers.m └── synset_words.txt ├── CustomLayers ├── mycheckLayer.m ├── empty2dLayer.m ├── mishLayer.m ├── upsample2dLayer.m ├── sliceLayer.m ├── prnAdditionLayer.m └── yolov3Layer.m ├── coco.names ├── README.md ├── detect.m ├── cfg ├── yolov3-tiny.cfg ├── yolov3-tiny-prn.cfg ├── darknet19.cfg ├── yolov4-tiny.cfg ├── mobilenetv2.cfg ├── yolov3.cfg ├── yolov4.cfg └── matlabExportYoloV4.cfg └── train.m /save/README.md: -------------------------------------------------------------------------------- 1 | 此目录保存的checkpoint模型 2 | -------------------------------------------------------------------------------- /weights/readme.md: -------------------------------------------------------------------------------- 1 | 此处存放darknet模型权重文件 “*.weights” -------------------------------------------------------------------------------- /demo.mlx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/demo.mlx -------------------------------------------------------------------------------- /images/dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/dog.jpg -------------------------------------------------------------------------------- /images/giraffe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/giraffe.jpg -------------------------------------------------------------------------------- /images/mynet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/mynet.png -------------------------------------------------------------------------------- /images/person.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/person.jpg -------------------------------------------------------------------------------- /images/yolov4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/yolov4.jpg -------------------------------------------------------------------------------- /images/lgraphLayer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/lgraphLayer.png -------------------------------------------------------------------------------- /images/lgraphWeight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/lgraphWeight.png -------------------------------------------------------------------------------- /images/rec_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/rec_result.png -------------------------------------------------------------------------------- /images/yolov4Detect.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/yolov4Detect.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.mat 2 | *.jpg 3 | *.png 4 | *.pdf 5 | *.asv 6 | *.weights 7 | 8 | !images/*.jpg 9 | !images/*.png -------------------------------------------------------------------------------- /images/dogYolov4Detect.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/dogYolov4Detect.jpg -------------------------------------------------------------------------------- /images/importerExporter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/importerExporter.png -------------------------------------------------------------------------------- /images/importDarknetLayers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/importDarknetLayers.png -------------------------------------------------------------------------------- /images/importDarknetNetwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/importDarknetNetwork.png -------------------------------------------------------------------------------- /images/importDarknetWeights.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cuixing158/yolov3-yolov4-matlab/HEAD/images/importDarknetWeights.png -------------------------------------------------------------------------------- /utils/getClasses.m: -------------------------------------------------------------------------------- 1 | function classes = getClasses(labelsPath) 2 | fid = fopen(labelsPath,'r'); 3 | s = textscan(fid,'%s', 'Delimiter',{' '}); 4 | s = s{1}; 5 | % classes =cellfun(@(x)x(11:end),s,'UniformOutput',false); 6 | classes = s; 7 | fclose(fid); -------------------------------------------------------------------------------- /CustomLayers/mycheckLayer.m: -------------------------------------------------------------------------------- 1 | validInputSize = [3,3,18,1]; 2 | layer = yolov3Layer('yolov3', rand(3,2),1,1,[416,416],'default'); 3 | checkLayer(layer,validInputSize,'ObservationDimension' ,4) 4 | 5 | %% 6 | layer = mishLayer('mishACT'); 7 | validInputSize = [24 24 20]; 8 | checkLayer(layer,validInputSize,'ObservationDimension',4) 9 | 10 | 11 | -------------------------------------------------------------------------------- /CustomLayers/empty2dLayer.m: -------------------------------------------------------------------------------- 1 | classdef empty2dLayer < nnet.layer.Layer 2 | % 主要想用于导入yolov3中route层的单个跳层连接 3 | % 2019.9.8 4 | % 2020.4.29加入属性connectID,用于连接前面的层 5 | properties 6 | connectID %connectID 是以cfg文件中第一个非[net]开始的module为0开始的计数 7 | end 8 | 9 | methods 10 | function layer = empty2dLayer(name,con) 11 | layer.Name = name; 12 | text = ['[', num2str(1), ' ', num2str(1), '] emptyLayer ']; 13 | layer.Description = text; 14 | layer.Type = 'empty2dLayer'; 15 | layer.connectID= con; 16 | end 17 | 18 | function Z = predict(layer, X) 19 | Z = X; 20 | end 21 | 22 | function [dX] = backward( layer, X, ~, dZ, ~ ) 23 | dX = dZ; 24 | end 25 | end 26 | end 27 | %% 28 | % 参考:https://ww2.mathworks.cn/matlabcentral/fileexchange/71277-deep-learning-darknet-importer -------------------------------------------------------------------------------- /CustomLayers/mishLayer.m: -------------------------------------------------------------------------------- 1 | classdef mishLayer < nnet.layer.Layer 2 | % custom MishLayer layer.激活函数优于relu 3 | % 参考:https://arxiv.org/abs/1908.08681 4 | % 《Mish: A Self Regularized Non-Monotonic Neural Activation Function》 5 | % cuixingxing150@gmail.com 6 | % 2020.4.29 7 | % 8 | properties 9 | 10 | end 11 | 12 | methods 13 | function layer = mishLayer(name) 14 | % Set layer name. 15 | layer.Name = name; 16 | 17 | % Set layer description. 18 | layer.Description = "mishLayer activation layer"; 19 | 20 | layer.Type = 'mishLayer'; 21 | end 22 | 23 | function Z = predict(~, X) 24 | % Z = predict(layer, X) forwards the input data X through the 25 | % layer and outputs the result Z. 26 | Z = X.*tanh(log(1+exp(X))); 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /CustomLayers/upsample2dLayer.m: -------------------------------------------------------------------------------- 1 | classdef upsample2dLayer < nnet.layer.Layer 2 | properties 3 | size % 标量,一般为2 4 | end 5 | 6 | methods 7 | function layer = upsample2dLayer(name, size) 8 | layer.Name = name; 9 | text = ['[', num2str(size), ' ', num2str(size), '] upsampling for YOLOv3']; 10 | layer.Description = text; 11 | layer.Type = 'upsample2dLayer'; 12 | layer.size = size; 13 | end 14 | 15 | function Z = predict(layer, X) 16 | Z = repelem(X, layer.size, layer.size); 17 | end 18 | 19 | function [dX] = backward( layer, X, ~, dZ, ~ ) 20 | dX = dZ(1:layer.size:end, 1:layer.size:end, :, :); 21 | end 22 | end 23 | end 24 | %% 25 | % 参考:https://ww2.mathworks.cn/matlabcentral/fileexchange/71277-deep-learning-darknet-importer 26 | % 官方文档:Define Custom Deep Learning Layers 27 | -------------------------------------------------------------------------------- /coco.names: -------------------------------------------------------------------------------- 1 | person 2 | bicycle 3 | car 4 | motorbike 5 | aeroplane 6 | bus 7 | train 8 | truck 9 | boat 10 | traffic light 11 | fire hydrant 12 | stop sign 13 | parking meter 14 | bench 15 | bird 16 | cat 17 | dog 18 | horse 19 | sheep 20 | cow 21 | elephant 22 | bear 23 | zebra 24 | giraffe 25 | backpack 26 | umbrella 27 | handbag 28 | tie 29 | suitcase 30 | frisbee 31 | skis 32 | snowboard 33 | sports ball 34 | kite 35 | baseball bat 36 | baseball glove 37 | skateboard 38 | surfboard 39 | tennis racket 40 | bottle 41 | wine glass 42 | cup 43 | fork 44 | knife 45 | spoon 46 | bowl 47 | banana 48 | apple 49 | sandwich 50 | orange 51 | broccoli 52 | carrot 53 | hot dog 54 | pizza 55 | donut 56 | cake 57 | chair 58 | sofa 59 | pottedplant 60 | bed 61 | diningtable 62 | toilet 63 | tvmonitor 64 | laptop 65 | mouse 66 | remote 67 | keyboard 68 | cell phone 69 | microwave 70 | oven 71 | toaster 72 | sink 73 | refrigerator 74 | book 75 | clock 76 | vase 77 | scissors 78 | teddy bear 79 | hair drier 80 | toothbrush 81 | -------------------------------------------------------------------------------- /CustomLayers/sliceLayer.m: -------------------------------------------------------------------------------- 1 | classdef sliceLayer < nnet.layer.Layer 2 | % 对应于yolov4-tiny.cfg中的route的group层,用于通道分组 3 | % https://github.com/AlexeyAB/darknet 4 | % 5 | % cuixingxing150@gmail.com 6 | % 2020.6.29 7 | properties 8 | connectID %connectID 是以cfg文件中第一个非[net]开始的module为0开始的计数,用于用于连接前面的层,目的方便exportDarkNetwork函数使用 9 | groups % 与cfg中的route的group一致 10 | group_id % 与cfg中的route的group_id一致,group_id在cfg中是从0开始的索引,matlab中为从1开始 11 | end 12 | 13 | methods 14 | function layer = sliceLayer(name,con,groups,group_id) 15 | layer.Name = name; 16 | text = [ num2str(groups), ' groups,group_id: ', num2str(group_id), ' sliceLayer ']; 17 | layer.Description = text; 18 | layer.Type = 'sliceLayer'; 19 | layer.connectID= con; 20 | layer.groups= groups; 21 | layer.group_id= group_id; 22 | assert(group_id>0,'group_id must great zero! it must start index from 1'); 23 | end 24 | 25 | function Z = predict(layer, X) %输出Z保证是4维 26 | X = reshape(X,[size(X),1]); 27 | channels = size(X,3); 28 | deltaChannels = channels/layer.groups; 29 | selectStart = (layer.group_id-1)*deltaChannels+1; 30 | selectEnd = layer.group_id*deltaChannels; 31 | Z = X(:,:,selectStart:selectEnd,:); 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /utils/preprocessTrainData.m: -------------------------------------------------------------------------------- 1 | function out = preprocessTrainData(data,networkInputSize,structNamesIDs) 2 | % 功能:对输入数据图像进行预处理,大小一致,加入bbox标签 3 | % 输入: 4 | % data:bs*3大小的cell array,第一列cell存储图像,第二列cell存储[x,y,w,h],第三列cell存储classID 5 | % networkInputSize:输入网络统一大小,[height,width] 6 | % structNamesIDs: 结构体,类别映射到数字ID 7 | % 输出: 8 | % out:table类型,1*2大小,第一个为图像数据,第二个为bbox label,形式为[x,y,w,h,classID] 9 | % 10 | % email:cuixingxing150@gmail.com 11 | % 2020.4.22 12 | % 13 | 14 | nums = size(data,1);% batchSize大小 15 | XTrain = zeros([networkInputSize,nums],'single'); 16 | YTrain = cell(nums,1);% 每个值存储label,x,y,w,h,classID 17 | 18 | invalidBboxInd = [];% bbox is invalid and will not be considered in the training set! 19 | for ii = 1:nums 20 | I = data{ii,1}; 21 | imgSize = size(I); 22 | 23 | % Convert an input image with single channel to 3 channels. 24 | if numel(imgSize) == 1 25 | I = repmat(I,1,1,3); 26 | end 27 | bboxes = data{ii,2}; 28 | I = im2single(imresize(I,networkInputSize(1:2))); 29 | scale = networkInputSize(1:2)./imgSize(1:2); 30 | 31 | try 32 | bboxes = bboxresize(bboxes,scale); 33 | catch 34 | invalidBboxInd = [invalidBboxInd;ii]; 35 | end 36 | 37 | % bbox label 38 | idxs = zeros(size(bboxes,1),1); 39 | for jj = 1:size(bboxes,1) 40 | labels = string(data{ii,3}); 41 | idxs(jj) = structNamesIDs.(labels(jj)); 42 | end 43 | 44 | XTrain(:,:,:,ii) = I; 45 | YTrain{ii} = [bboxes,idxs]; 46 | end 47 | 48 | % remove invalid bbox and label 49 | XTrain(:,:,:,invalidBboxInd) = []; 50 | YTrain(invalidBboxInd) = []; 51 | 52 | out = table({XTrain},{YTrain}); 53 | end -------------------------------------------------------------------------------- /CustomLayers/prnAdditionLayer.m: -------------------------------------------------------------------------------- 1 | classdef prnAdditionLayer < nnet.layer.Layer 2 | % 对应于yolov3-tiny-prn.cfg中的shortcut层,通道部分相加 3 | % https://github.com/WongKinYiu/PartialResidualNetworks 4 | % 5 | % cuixingxing150@gmail.com 6 | % 2020.6.29 7 | methods 8 | function layer = prnAdditionLayer(numInputs,name) 9 | % layer = prnAdditionLayer(numInputs,name) creates a 10 | % prn addition layer and specifies the number of inputs 11 | % and the layer name. 12 | 13 | % Set number of inputs. 14 | layer.NumInputs = numInputs; 15 | 16 | % Set layer name. 17 | layer.Name = name; 18 | 19 | % Set layer description. 20 | layer.Description = "Prn addition of " + numInputs + ... 21 | " inputs"; 22 | end 23 | 24 | function Z = predict(layer, varargin) 25 | % Z = predict(layer, X1, ..., Xn) forwards the input data X1, 26 | % ..., Xn through the layer and outputs the result Z. 27 | X = varargin; 28 | 29 | % Initialize output 30 | [minChannels,ind] = min(cellfun(@(x)min(size(x,3)),X)); 31 | X1 = X{1}; 32 | [h,w,~,n] = size(X1); 33 | Z = zeros([h,w,minChannels,n],'like',X1); 34 | 35 | % prn addition 36 | for i = 1:layer.NumInputs 37 | item = X{i}; 38 | if i ~= ind 39 | startInd = 1; 40 | endInd = minChannels; 41 | item = item(:,:,startInd:endInd,:); 42 | end 43 | Z = Z + item; 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo has been deprecated. Please see [MATLAB Deep Learning Model Hub](https://github.com/matlab-deep-learning/MATLAB-Deep-Learning-Model-Hub), which includes an implementation of [YOLOV3/V4](https://github.com/matlab-deep-learning/MATLAB-Deep-Learning-Model-Hub#object-detection-). 2 | --- 3 | 4 | ![RUNOOB 图标](https://github.com/cuixing158/yolov3-yolov4-matlab/blob/master/images/importerExporter.png)
5 | ![RUNOOB 图标](https://github.com/cuixing158/yolov3-yolov4-matlab/blob/master/images/yolov4Detect.jpg)
6 | ![RUNOOB 图标](https://github.com/cuixing158/yolov3-yolov4-matlab/blob/master/images/dogYolov4Detect.jpg)
7 | 8 | # yoloV3/yolov4 matlab 9 | This respository uses simplified and minimal code to reproduce the yolov3 / yolov4 detection networks and darknet classification networks. The highlights are as follows:
10 | - Support original version of darknet model
11 | - Support training, inference, import and export of "* .cfg", "* .weights" models
12 | - Support the latest [yolov3, yolov4](https://github.com/AlexeyAB/darknet) models
13 | - Support darknet classification model
14 | - Support all kinds of indicators such as feature map size calculation, flops calculation and so on.
15 | 16 | --- 17 | 本库代码比pytorch和tensorflow等其他框架更具可读性和精简性!
18 | These code is highly readable and more brief than other frameworks such as pytorch and tensorflow!
19 | 但是不包含各种训练数据增强tricks!
20 | But it does not contain various training data augmentation tricks!
21 | 22 | # Requirements 23 | Matlab R2020a or higher,the newer the better,no other dependencies!!! 24 | 25 | # How to use 26 | 训练使用train.m,推理测试使用detect.m,demo.mlx
27 | 百度网盘yolov3/4,[weights文件](https://pan.baidu.com/s/1UvPKSlT7K3hzeXof4ovN_A) 提取码:dbbo 28 | -------------------------------------------------------------------------------- /utils/getGIOU.m: -------------------------------------------------------------------------------- 1 | function [giouRatio,iouRatio] = getGIOU(bboxA,bboxB) 2 | % 功能:获取bboxA和bboxB之间的GIOU或IOU,两两组合计算GIOU值 3 | % 输入: 4 | % bboxA, M*4大小矩阵,形式为[x,y,w,h] 5 | % bboxB, N*4大小矩阵,形式为[x,y,w,h] 6 | % 输出: 7 | % giouRatio:M*N大小矩阵,每个元素的值表示所在的行列(i,j)分别表示来自bboxA,bboxB的第i,j个bbox的GIOU值 8 | % iouRatio:M*N大小矩阵,每个元素的值表示所在的行列(i,j)分别表示来自bboxA,bboxB的第i,j个bbox的IOU值 9 | % 10 | % 参考:1、https://arxiv.org/abs/1902.09630,CVPR2019, 11 | % 《Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression 》 12 | % https://zhuanlan.zhihu.com/p/57992040 13 | % 14 | % cuixingxing150@gmail.com 15 | % 2020.4.25 16 | % 17 | M = size(bboxA,1); 18 | N = size(bboxB,1); 19 | giouRatio = zeros(M,N,'like',bboxA); 20 | iouRatio = zeros(M,N,'like',bboxA); 21 | 22 | areasA = bboxA(:,3).*bboxA(:,4); 23 | areasB = bboxB(:,3).*bboxB(:,4); 24 | xyxyA = [bboxA(:,1:2),bboxA(:,1)+bboxA(:,3),bboxA(:,2)+bboxA(:,4)]; 25 | xyxyB = [bboxB(:,1:2),bboxB(:,1)+bboxB(:,3),bboxB(:,2)+bboxB(:,4)]; 26 | 27 | for i = 1:M 28 | for j = 1:N 29 | x1 = max(xyxyA(i,1),xyxyB(j,1)); 30 | x2 = min(xyxyA(i,3),xyxyB(j,3)); 31 | y1 = max(xyxyA(i,2),xyxyB(j,2)); 32 | y2 = min(xyxyA(i,4),xyxyB(j,4)); 33 | Intersection = max(0,(x2-x1)).*max(0,(y2-y1)); 34 | Union = areasA(i)+areasB(j)-Intersection; 35 | iouRatio(i,j) = Intersection./Union; 36 | 37 | x1 = min(xyxyA(i,1),xyxyB(j,1)); 38 | x2 = max(xyxyA(i,3),xyxyB(j,3)); 39 | y1 = min(xyxyA(i,2),xyxyB(j,2)); 40 | y2 = max(xyxyA(i,4),xyxyB(j,4)); 41 | Convex = (x2-x1).*(y2-y1); 42 | giouRatio(i,j) = iouRatio(i,j) - (Convex-Union)./Convex; 43 | end 44 | end 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /detect.m: -------------------------------------------------------------------------------- 1 | %% custom input 2 | addpath('./CustomLayers/','./utils/') 3 | % clear all % 如果更换模型,需重置静态函数(影响性能),否则可以不用清理 4 | cfg_file = 'cfg/yolov4-tiny.cfg'; 5 | weight_file = 'weights/yolov4-tiny.weights'; 6 | throushold = 0.1; 7 | NMS = 0.4; 8 | 9 | %% import all classes 10 | fid = fopen('coco.names','r'); 11 | names = textscan(fid, '%s', 'Delimiter',{' '}); 12 | fclose(fid);classesNames = categorical(names{1}); 13 | RGB = randi(255,length(classesNames),3); 14 | 15 | %% 摄像头视频流识别 16 | cap = webcam(); 17 | player = vision.DeployableVideoPlayer(); 18 | image = cap.snapshot(); 19 | step(player, image); 20 | 21 | while player.isOpen() 22 | image = cap.snapshot(); 23 | t1 = tic; 24 | outFeatures = yolov3v4Predict(cfg_file,weight_file,image);% M*(5+nc) ,为[x,y,w,h,Pobj,p1,p2,...,pn] 25 | fprintf('预测耗时:%.2f 秒\n',toc(t1));% yolov4大概0.4秒,yolov3大概0.2秒,yolov3-tiny大概0.06秒,yolov4-tiny大概0.07秒,yolov3-tiny-prn大概0.06秒 26 | 27 | %% 阈值过滤+NMS处理 28 | scores = outFeatures(:,5); 29 | outFeatures = outFeatures(scores>throushold,:); 30 | 31 | allBBoxes = outFeatures(:,1:4); 32 | allScores = outFeatures(:,5); 33 | [maxScores,indxs] = max(outFeatures(:,6:end),[],2); 34 | allScores = allScores.*maxScores; 35 | allLabels = classesNames(indxs); 36 | 37 | % NMS非极大值抑制 38 | if ~isempty(allBBoxes) 39 | [bboxes,scores,labels] = selectStrongestBboxMulticlass(allBBoxes,allScores,allLabels,... 40 | 'RatioType','Min','OverlapThreshold',NMS); 41 | annotations = string(labels) + ": " + string(scores); 42 | [~,ids] = ismember(labels,classesNames); 43 | colors = RGB(ids,:); 44 | image = insertObjectAnnotation(image,... 45 | 'rectangle',bboxes,cellstr(annotations),... 46 | 'Color',colors,... 47 | 'LineWidth',3); 48 | end 49 | step(player,image); 50 | end 51 | release(player); 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /cfg/yolov3-tiny.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | batch=1 4 | subdivisions=1 5 | # Training 6 | # batch=64 7 | # subdivisions=2 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=16 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | [maxpool] 34 | size=2 35 | stride=2 36 | 37 | [convolutional] 38 | batch_normalize=1 39 | filters=32 40 | size=3 41 | stride=1 42 | pad=1 43 | activation=leaky 44 | 45 | [maxpool] 46 | size=2 47 | stride=2 48 | 49 | [convolutional] 50 | batch_normalize=1 51 | filters=64 52 | size=3 53 | stride=1 54 | pad=1 55 | activation=leaky 56 | 57 | [maxpool] 58 | size=2 59 | stride=2 60 | 61 | [convolutional] 62 | batch_normalize=1 63 | filters=128 64 | size=3 65 | stride=1 66 | pad=1 67 | activation=leaky 68 | 69 | [maxpool] 70 | size=2 71 | stride=2 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=256 76 | size=3 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [maxpool] 82 | size=2 83 | stride=2 84 | 85 | [convolutional] 86 | batch_normalize=1 87 | filters=512 88 | size=3 89 | stride=1 90 | pad=1 91 | activation=leaky 92 | 93 | [maxpool] 94 | size=2 95 | stride=1 96 | 97 | [convolutional] 98 | batch_normalize=1 99 | filters=1024 100 | size=3 101 | stride=1 102 | pad=1 103 | activation=leaky 104 | 105 | ########### 106 | 107 | [convolutional] 108 | batch_normalize=1 109 | filters=256 110 | size=1 111 | stride=1 112 | pad=1 113 | activation=leaky 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=512 118 | size=3 119 | stride=1 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | size=1 125 | stride=1 126 | pad=1 127 | filters=255 128 | activation=linear 129 | 130 | 131 | 132 | [yolo] 133 | mask = 3,4,5 134 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 135 | classes=80 136 | num=6 137 | jitter=.3 138 | ignore_thresh = .7 139 | truth_thresh = 1 140 | random=1 141 | 142 | [route] 143 | layers = -4 144 | 145 | [convolutional] 146 | batch_normalize=1 147 | filters=128 148 | size=1 149 | stride=1 150 | pad=1 151 | activation=leaky 152 | 153 | [upsample] 154 | stride=2 155 | 156 | [route] 157 | layers = -1, 8 158 | 159 | [convolutional] 160 | batch_normalize=1 161 | filters=256 162 | size=3 163 | stride=1 164 | pad=1 165 | activation=leaky 166 | 167 | [convolutional] 168 | size=1 169 | stride=1 170 | pad=1 171 | filters=255 172 | activation=linear 173 | 174 | [yolo] 175 | mask = 0,1,2 176 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 177 | classes=80 178 | num=6 179 | jitter=.3 180 | ignore_thresh = .7 181 | truth_thresh = 1 182 | random=1 183 | -------------------------------------------------------------------------------- /cfg/yolov3-tiny-prn.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | batch=1 4 | subdivisions=1 5 | # Training 6 | #batch=64 7 | #subdivisions=8 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=16 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | [maxpool] 34 | size=2 35 | stride=2 36 | 37 | [convolutional] 38 | batch_normalize=1 39 | filters=32 40 | size=3 41 | stride=1 42 | pad=1 43 | activation=leaky 44 | 45 | [maxpool] 46 | size=2 47 | stride=2 48 | 49 | [convolutional] 50 | batch_normalize=1 51 | filters=64 52 | size=3 53 | stride=1 54 | pad=1 55 | activation=leaky 56 | 57 | [maxpool] 58 | size=2 59 | stride=2 60 | 61 | [convolutional] 62 | batch_normalize=1 63 | filters=128 64 | size=3 65 | stride=1 66 | pad=1 67 | activation=leaky 68 | 69 | [maxpool] 70 | size=2 71 | stride=2 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=256 76 | size=3 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [maxpool] 82 | size=2 83 | stride=2 84 | 85 | [convolutional] 86 | batch_normalize=1 87 | filters=512 88 | size=3 89 | stride=1 90 | pad=1 91 | activation=leaky 92 | 93 | [maxpool] 94 | size=2 95 | stride=1 96 | 97 | [convolutional] 98 | batch_normalize=1 99 | filters=512 100 | size=3 101 | stride=1 102 | pad=1 103 | activation=leaky 104 | 105 | [shortcut] 106 | activation=leaky 107 | from=-3 108 | 109 | ########### 110 | 111 | [convolutional] 112 | batch_normalize=1 113 | filters=256 114 | size=1 115 | stride=1 116 | pad=1 117 | activation=leaky 118 | 119 | [convolutional] 120 | batch_normalize=1 121 | filters=256 122 | size=3 123 | stride=1 124 | pad=1 125 | activation=leaky 126 | 127 | [shortcut] 128 | activation=leaky 129 | from=-2 130 | 131 | [convolutional] 132 | size=1 133 | stride=1 134 | pad=1 135 | filters=255 136 | activation=linear 137 | 138 | 139 | 140 | [yolo] 141 | mask = 3,4,5 142 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 143 | classes=80 144 | num=6 145 | jitter=.3 146 | ignore_thresh = .7 147 | truth_thresh = 1 148 | random=1 149 | 150 | [route] 151 | layers = -4 152 | 153 | [convolutional] 154 | batch_normalize=1 155 | filters=128 156 | size=1 157 | stride=1 158 | pad=1 159 | activation=leaky 160 | 161 | [upsample] 162 | stride=2 163 | 164 | [shortcut] 165 | activation=leaky 166 | from=8 167 | 168 | [convolutional] 169 | batch_normalize=1 170 | filters=128 171 | size=3 172 | stride=1 173 | pad=1 174 | activation=leaky 175 | 176 | [shortcut] 177 | activation=leaky 178 | from=-3 179 | 180 | [shortcut] 181 | activation=leaky 182 | from=8 183 | 184 | [convolutional] 185 | size=1 186 | stride=1 187 | pad=1 188 | filters=255 189 | activation=linear 190 | 191 | [yolo] 192 | mask = 1,2,3 193 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 194 | classes=80 195 | num=6 196 | jitter=.3 197 | ignore_thresh = .7 198 | truth_thresh = 1 199 | random=1 -------------------------------------------------------------------------------- /cfg/darknet19.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Training 3 | #batch=128 4 | #subdivisions=2 5 | 6 | # Testing 7 | batch=1 8 | subdivisions=1 9 | 10 | height=256 11 | width=256 12 | min_crop=128 13 | max_crop=448 14 | channels=3 15 | momentum=0.9 16 | decay=0.0005 17 | 18 | burn_in=1000 19 | learning_rate=0.1 20 | policy=poly 21 | power=4 22 | max_batches=800000 23 | 24 | angle=7 25 | hue=.1 26 | saturation=.75 27 | exposure=.75 28 | aspect=.75 29 | 30 | [convolutional] 31 | batch_normalize=1 32 | filters=32 33 | size=3 34 | stride=1 35 | pad=1 36 | activation=leaky 37 | 38 | [maxpool] 39 | size=2 40 | stride=2 41 | 42 | [convolutional] 43 | batch_normalize=1 44 | filters=64 45 | size=3 46 | stride=1 47 | pad=1 48 | activation=leaky 49 | 50 | [maxpool] 51 | size=2 52 | stride=2 53 | 54 | [convolutional] 55 | batch_normalize=1 56 | filters=128 57 | size=3 58 | stride=1 59 | pad=1 60 | activation=leaky 61 | 62 | [convolutional] 63 | batch_normalize=1 64 | filters=64 65 | size=1 66 | stride=1 67 | pad=1 68 | activation=leaky 69 | 70 | [convolutional] 71 | batch_normalize=1 72 | filters=128 73 | size=3 74 | stride=1 75 | pad=1 76 | activation=leaky 77 | 78 | [maxpool] 79 | size=2 80 | stride=2 81 | 82 | [convolutional] 83 | batch_normalize=1 84 | filters=256 85 | size=3 86 | stride=1 87 | pad=1 88 | activation=leaky 89 | 90 | [convolutional] 91 | batch_normalize=1 92 | filters=128 93 | size=1 94 | stride=1 95 | pad=1 96 | activation=leaky 97 | 98 | [convolutional] 99 | batch_normalize=1 100 | filters=256 101 | size=3 102 | stride=1 103 | pad=1 104 | activation=leaky 105 | 106 | [maxpool] 107 | size=2 108 | stride=2 109 | 110 | [convolutional] 111 | batch_normalize=1 112 | filters=512 113 | size=3 114 | stride=1 115 | pad=1 116 | activation=leaky 117 | 118 | [convolutional] 119 | batch_normalize=1 120 | filters=256 121 | size=1 122 | stride=1 123 | pad=1 124 | activation=leaky 125 | 126 | [convolutional] 127 | batch_normalize=1 128 | filters=512 129 | size=3 130 | stride=1 131 | pad=1 132 | activation=leaky 133 | 134 | [convolutional] 135 | batch_normalize=1 136 | filters=256 137 | size=1 138 | stride=1 139 | pad=1 140 | activation=leaky 141 | 142 | [convolutional] 143 | batch_normalize=1 144 | filters=512 145 | size=3 146 | stride=1 147 | pad=1 148 | activation=leaky 149 | 150 | [maxpool] 151 | size=2 152 | stride=2 153 | 154 | [convolutional] 155 | batch_normalize=1 156 | filters=1024 157 | size=3 158 | stride=1 159 | pad=1 160 | activation=leaky 161 | 162 | [convolutional] 163 | batch_normalize=1 164 | filters=512 165 | size=1 166 | stride=1 167 | pad=1 168 | activation=leaky 169 | 170 | [convolutional] 171 | batch_normalize=1 172 | filters=1024 173 | size=3 174 | stride=1 175 | pad=1 176 | activation=leaky 177 | 178 | [convolutional] 179 | batch_normalize=1 180 | filters=512 181 | size=1 182 | stride=1 183 | pad=1 184 | activation=leaky 185 | 186 | [convolutional] 187 | batch_normalize=1 188 | filters=1024 189 | size=3 190 | stride=1 191 | pad=1 192 | activation=leaky 193 | 194 | [convolutional] 195 | filters=1000 196 | size=1 197 | stride=1 198 | pad=1 199 | activation=linear 200 | 201 | [avgpool] 202 | 203 | [softmax] 204 | groups=1 205 | 206 | -------------------------------------------------------------------------------- /CustomLayers/yolov3Layer.m: -------------------------------------------------------------------------------- 1 | classdef yolov3Layer < nnet.layer.Layer 2 | % 该自定义类仍有很大不灵活性,表现在1、predict函数输出不能自由控制;2、类属性在predict函数里面无法改变;3、训练阶段forward函数不执行 3 | % 4、该类无法自定义其他普通成员函数。 4 | % 参考官方文档:Define Custom Deep Learning Layers 5 | properties 6 | mask % 如当前yolov3层mask为[1,2,3],matlab中从1开始,对应cfg文件中以0开始的mask 7 | anchors % 所有的anchors,形如[width1,height1; weight2,height2; ...],对应cfg文件中的anchors,大小为allnumAnchors*2 8 | num % total number of anchors,所有anchors的数量,对应cfg文件中的num 9 | ignore_thresh % keeps duplicated detections if IoU(detect, truth) >ignore_thresh, which will be fused during NMS (is used for training only) 10 | truth_thresh % adjusts duplicated detections if IoU(detect, truth) > truth_thresh, which will be fused during NMS (is used for training only) 11 | jitter % randomly crops and resizes images with changing aspect ratio from x(1 - 2*jitter) to x(1 + 2*jitter) (data augmentation parameter is used only from the last layer) 12 | random % randomly resizes network for each 10 iterations from 1/1.4 to 1.4(data augmentation parameter is used only from the last layer) 13 | classes % 目标检测总共类别数量,对应cfg文件中的classes 14 | 15 | anchorsUse %当前yolov3层的anchors,n*2大小,[width, height],宽高为相对输入原图大小,注意这个与matlab官网estimateAnchorBoxes的宽高顺序相反 16 | nAnchors % 当前yolov3层使用anchors的数量,一般为3 17 | numX % 传入到该yolov3层特征图的宽,像素 18 | numY % 传入到该yolov3层特征图的宽,像素 19 | imageSize % 网络输入图像大小,[imageHeight,imageWidth] 20 | arc % 方式,取'default'、'uCE'、'uBCE'中的一种 21 | stride % 传入到该yolov3层特征下采样率,[w,h],如输入网络大小是416*416宽乘高,该特征层为13*13,则stride = 32 22 | end 23 | 24 | methods 25 | function layer = yolov3Layer(name, mask,allAnchors,nClasses,yoloIndex,imageSize,arc) 26 | % 输入参数: 27 | % name: 字符向量或字符串,层名字 28 | % mask: 见上面properties说明 29 | % allAnchors:同上面properties之anchors说明 30 | % nClasses: 1*1 标量,检测的类别数量 31 | % imageSize:[imageHeight,imageWidth],输入网络的图像大小 32 | % yoloIndex:1*1标量,从1开始的索引,输出yolo检测层的序号 33 | % arc:字符向量或字符串,计算损失的方式 34 | % 35 | % cuixingxing150@gmail.com 36 | % 2020.4.20 37 | % 38 | assert(size(allAnchors,2)==2,'allAnchors must have n*2 shape!');% nAchors*2,形如[width,height] 39 | 40 | layer.mask = mask; 41 | layer.anchors = allAnchors; 42 | layer.num = numel(allAnchors)/2; 43 | layer.classes = nClasses; 44 | layer.ignore_thresh = .7; 45 | layer.truth_thresh = 1; 46 | layer.jitter = .3; 47 | layer.random = 1; 48 | 49 | anchorsUse = allAnchors(mask,:);% na*2, 注意matlab中mask是从1开始的索引 50 | layer.Name = name; 51 | text = ['all number classes:', num2str(nClasses),... 52 | ',used anchor box:',mat2str(round(anchorsUse)),... 53 | ', yoloLayerID:',num2str(yoloIndex),... 54 | ', arc:',arc]; 55 | layer.Description = text; 56 | layer.Type = 'yoloV3Layer'; 57 | 58 | layer.numY = 1; 59 | layer.numX = 1; 60 | layer.stride =1; 61 | 62 | layer.anchorsUse = anchorsUse; 63 | layer.nAnchors = size(anchorsUse,1); 64 | layer.imageSize = imageSize; 65 | layer.arc = arc; 66 | end 67 | 68 | function Z = predict(layer, X) % training 69 | % matlab中上一层输入的特征X为H*W*C*N,即h*w*c*bs 70 | X = dlarray(X); 71 | layer.numY = size(X,1); 72 | layer.numX = size(X,2); 73 | bs = size(X,4); 74 | layer.stride = max(layer.imageSize)./max(layer.numX,layer.numY); 75 | 76 | Z = X; 77 | % 2020.4.23 实际写下面2行的话,待整个yolov3网络predict时候报错!!!故移到外面写 78 | % Z = X.reshape(layer.numY,layer.numX,layer.nAnchors,(5+layer.nClasses),bs); 79 | % Z = permute(Z,[5,3,1,2,4]);% 输出特征图,Z=bs*na*h*w*(5+nc), 80 | end 81 | 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /cfg/yolov4-tiny.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | #batch=1 4 | #subdivisions=1 5 | # Training 6 | batch=64 7 | subdivisions=1 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.00261 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=32 28 | size=3 29 | stride=2 30 | pad=1 31 | activation=leaky 32 | 33 | [convolutional] 34 | batch_normalize=1 35 | filters=64 36 | size=3 37 | stride=2 38 | pad=1 39 | activation=leaky 40 | 41 | [convolutional] 42 | batch_normalize=1 43 | filters=64 44 | size=3 45 | stride=1 46 | pad=1 47 | activation=leaky 48 | 49 | [route] 50 | layers=-1 51 | groups=2 52 | group_id=1 53 | 54 | [convolutional] 55 | batch_normalize=1 56 | filters=32 57 | size=3 58 | stride=1 59 | pad=1 60 | activation=leaky 61 | 62 | [convolutional] 63 | batch_normalize=1 64 | filters=32 65 | size=3 66 | stride=1 67 | pad=1 68 | activation=leaky 69 | 70 | [route] 71 | layers = -1,-2 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=64 76 | size=1 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [route] 82 | layers = -6,-1 83 | 84 | [maxpool] 85 | size=2 86 | stride=2 87 | 88 | [convolutional] 89 | batch_normalize=1 90 | filters=128 91 | size=3 92 | stride=1 93 | pad=1 94 | activation=leaky 95 | 96 | [route] 97 | layers=-1 98 | groups=2 99 | group_id=1 100 | 101 | [convolutional] 102 | batch_normalize=1 103 | filters=64 104 | size=3 105 | stride=1 106 | pad=1 107 | activation=leaky 108 | 109 | [convolutional] 110 | batch_normalize=1 111 | filters=64 112 | size=3 113 | stride=1 114 | pad=1 115 | activation=leaky 116 | 117 | [route] 118 | layers = -1,-2 119 | 120 | [convolutional] 121 | batch_normalize=1 122 | filters=128 123 | size=1 124 | stride=1 125 | pad=1 126 | activation=leaky 127 | 128 | [route] 129 | layers = -6,-1 130 | 131 | [maxpool] 132 | size=2 133 | stride=2 134 | 135 | [convolutional] 136 | batch_normalize=1 137 | filters=256 138 | size=3 139 | stride=1 140 | pad=1 141 | activation=leaky 142 | 143 | [route] 144 | layers=-1 145 | groups=2 146 | group_id=1 147 | 148 | [convolutional] 149 | batch_normalize=1 150 | filters=128 151 | size=3 152 | stride=1 153 | pad=1 154 | activation=leaky 155 | 156 | [convolutional] 157 | batch_normalize=1 158 | filters=128 159 | size=3 160 | stride=1 161 | pad=1 162 | activation=leaky 163 | 164 | [route] 165 | layers = -1,-2 166 | 167 | [convolutional] 168 | batch_normalize=1 169 | filters=256 170 | size=1 171 | stride=1 172 | pad=1 173 | activation=leaky 174 | 175 | [route] 176 | layers = -6,-1 177 | 178 | [maxpool] 179 | size=2 180 | stride=2 181 | 182 | [convolutional] 183 | batch_normalize=1 184 | filters=512 185 | size=3 186 | stride=1 187 | pad=1 188 | activation=leaky 189 | 190 | ################################## 191 | 192 | [convolutional] 193 | batch_normalize=1 194 | filters=256 195 | size=1 196 | stride=1 197 | pad=1 198 | activation=leaky 199 | 200 | [convolutional] 201 | batch_normalize=1 202 | filters=512 203 | size=3 204 | stride=1 205 | pad=1 206 | activation=leaky 207 | 208 | [convolutional] 209 | size=1 210 | stride=1 211 | pad=1 212 | filters=255 213 | activation=linear 214 | 215 | 216 | 217 | [yolo] 218 | mask = 3,4,5 219 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 220 | classes=80 221 | num=6 222 | jitter=.3 223 | scale_x_y = 1.05 224 | cls_normalizer=1.0 225 | iou_normalizer=0.07 226 | iou_loss=ciou 227 | ignore_thresh = .7 228 | truth_thresh = 1 229 | random=0 230 | resize=1.5 231 | nms_kind=greedynms 232 | beta_nms=0.6 233 | 234 | [route] 235 | layers = -4 236 | 237 | [convolutional] 238 | batch_normalize=1 239 | filters=128 240 | size=1 241 | stride=1 242 | pad=1 243 | activation=leaky 244 | 245 | [upsample] 246 | stride=2 247 | 248 | [route] 249 | layers = -1, 23 250 | 251 | [convolutional] 252 | batch_normalize=1 253 | filters=256 254 | size=3 255 | stride=1 256 | pad=1 257 | activation=leaky 258 | 259 | [convolutional] 260 | size=1 261 | stride=1 262 | pad=1 263 | filters=255 264 | activation=linear 265 | 266 | [yolo] 267 | mask = 1,2,3 268 | anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 269 | classes=80 270 | num=6 271 | jitter=.3 272 | scale_x_y = 1.05 273 | cls_normalizer=1.0 274 | iou_normalizer=0.07 275 | iou_loss=ciou 276 | ignore_thresh = .7 277 | truth_thresh = 1 278 | random=0 279 | resize=1.5 280 | nms_kind=greedynms 281 | beta_nms=0.6 282 | -------------------------------------------------------------------------------- /utils/yolov3v4Predict.m: -------------------------------------------------------------------------------- 1 | function outPutFeatures = yolov3v4Predict(cfg_file,weight_file,image) 2 | % 功能:yolov3快速输出检测特征,同darknet官网输出结果方式保持一致 3 | % 输入: 4 | % cfg_file, 指定的cfg后缀的模型描述文件 5 | % weight_file, 指定的.weights后缀的二进制文件 6 | % image :输入网络的图像数据,单张图像(H*W*C)或者批量图像(H*W*C*bs) 7 | % 输出: 8 | % outPutFeatures: M*(5+nc)或者bs*M*(5+nc)大小 9 | % ,为bs*M*[x,y,w,h,Pobj,p1,p2,...,pn]大小的形式矩阵,如果是单张图像检测,则输出大小为M*(5+nc),否则是bs*M*(5+nc), 10 | % 其中,M为检测框的数量,bs为图片数量,nc为训练网络dlnet类别数量,x,y,w,h分别是输入图片上对应的x,y,width,height,Pobj 11 | % 为物体概率,p1,p2,...,pn分别为对应coco.names类别概率 12 | % 13 | % author: cuixingxing 14 | % email:cuixingxing150@gmail.com 15 | % 2020.4.22创建 16 | % 2020.5.2 修改 17 | % 2020.5.13 minor fix 18 | % 19 | 20 | persistent dlnet yolovLayerArray netInputSize 21 | if isempty(dlnet) 22 | 23 | %% import network and predict 24 | [layerGraphYolo,hyperParams] = importDarknetWeights(cfg_file,weight_file); 25 | dlnet = dlnetwork(layerGraphYolo); % 65秒左右 26 | % analyzeNetwork(layerGraphYolo)% visualize network 27 | % exportDarkNetNetwork(dlnet,hyperParams,'temp.cfg','temp.weights') 28 | 29 | %% get yolo index 30 | yoloIdx = []; 31 | for i = 1:length(dlnet.Layers) 32 | currentLayerType = class(dlnet.Layers(i)); 33 | if strcmpi(currentLayerType,'yoloV3Layer') 34 | yoloIdx = [yoloIdx;i]; 35 | end 36 | end 37 | assert(~isempty(yoloIdx),'输入网络非yolov3/4网络!') 38 | 39 | yolovLayerArray = dlnet.Layers(yoloIdx); 40 | netInputSize = dlnet.Layers(1).InputSize(1:2); 41 | end 42 | 43 | inputSize = [size(image,1),size(image,2)]; 44 | scale = inputSize./netInputSize;% [heightScale,widthScale] 45 | 46 | img = imresize(im2single(image),netInputSize);% [0,1]数据,保持与训练时候同大小和类型 47 | dlX = dlarray(img,'SSCB');% 大小为h*w*c*bs,注意是否归一化要看与训练时候图像一致 48 | if(canUseGPU()) 49 | dlX = gpuArray(dlX);% 推送到GPU上 50 | end 51 | 52 | numsYOLO = length(yolovLayerArray); 53 | outFeatureMaps = cell(numsYOLO,1); 54 | [outFeatureMaps{:}] = predict(dlnet,dlX,'Outputs',dlnet.OutputNames);% h*w*c*bs,matlab输出方式排列 55 | outPutFeatures = []; 56 | for i = 1:numsYOLO 57 | currentYOLOLayer = yolovLayerArray(i); 58 | currentFeatureMap = outFeatureMaps{i}; 59 | 60 | % 由于yolov3Layer类里面predict函数未改变类属性,故重新给属性赋值 61 | currentYOLOLayer.numY = size(currentFeatureMap,1); 62 | currentYOLOLayer.numX = size(currentFeatureMap,2); 63 | currentYOLOLayer.stride = max(currentYOLOLayer.imageSize)./max(currentYOLOLayer.numX,... 64 | currentYOLOLayer.numY); 65 | 66 | % reshape currentFeatureMap到有意义的维度,h*w*c*bs --> h*w*(5+nc)*na*bs 67 | % --> bs*na*h*w*(5+nc),最终的维度方式与darknet官网兼容 68 | bs = size(currentFeatureMap,4); 69 | h = currentYOLOLayer.numY; 70 | w = currentYOLOLayer.numX; 71 | na = currentYOLOLayer.nAnchors; 72 | nc = currentYOLOLayer.classes; 73 | currentFeatureMap = reshape(currentFeatureMap,h,w,5+nc,na,bs);% h*w*(5+nc)*na*bs 74 | currentFeatureMap = permute(currentFeatureMap,[5,4,1,2,3]);% bs*na*h*w*(5+nc) 75 | 76 | [~,~,yv,xv] = ndgrid(1:bs,1:na,0:h-1,0:w-1);% yv,xv大小都为bs*na*h*w,注意顺序,后面做加法维度标签要对应 77 | gridXY = cat(5,xv,yv);% 第5维上扩展,大小为bs*na*h*w*2, x,y从1开始的索引 78 | currentFeatureMap(:,:,:,:,1:2) = sigmoid(currentFeatureMap(:,:,:,:,1:2)) + gridXY; % 大小为bs*na*h*w*2,预测对应xy 79 | anchor_grid = currentYOLOLayer.anchorsUse/currentYOLOLayer.stride; % 此处anchor_grid大小为na*2 80 | anchor_grid = reshape(anchor_grid,1,currentYOLOLayer.nAnchors,1,1,2);% 此处anchor_grid大小为1*na*1*1*2,方便下面相乘 81 | currentFeatureMap(:,:,:,:,3:4) = exp(currentFeatureMap(:,:,:,:,3:4)).*anchor_grid;% 大小为bs*na*h*w*2 82 | currentFeatureMap(:,:,:,:,1:4) = currentFeatureMap(:,:,:,:,1:4)*currentYOLOLayer.stride; % 预测的bboxes 83 | currentFeatureMap(:,:,:,:,5:end) = sigmoid(currentFeatureMap(:,:,:,:,5:end)); % 预测的scores 84 | 85 | if currentYOLOLayer.classes == 1 86 | currentFeatureMap(:,:,:,:,6) = 1; 87 | end 88 | currentFeatureMap = reshape(currentFeatureMap,bs,[],5+currentYOLOLayer.classes);% bs*N*(5+nc) 89 | 90 | if isempty(outPutFeatures) 91 | outPutFeatures = currentFeatureMap; 92 | else 93 | outPutFeatures = cat(2,outPutFeatures,currentFeatureMap);% bs*M*(5+nc) 94 | end 95 | end 96 | 97 | %% 坐标转换到原始图像上 98 | outPutFeatures = extractdata(outPutFeatures);% bs*M*(5+nc) ,为[x_center,y_center,w,h,Pobj,p1,p2,...,pn] 99 | outPutFeatures(:,:,[1,3]) = outPutFeatures(:,:,[1,3])*scale(2);% x_center,width 100 | outPutFeatures(:,:,[2,4]) = outPutFeatures(:,:,[2,4])*scale(1);% y_center,height 101 | outPutFeatures(:,:,1) = outPutFeatures(:,:,1) -outPutFeatures(:,:,3)/2;% x 102 | outPutFeatures(:,:,2) = outPutFeatures(:,:,2) -outPutFeatures(:,:,4)/2; % y 103 | outPutFeatures = squeeze(outPutFeatures); % 如果是单张图像检测,则输出大小为M*(5+nc),否则是bs*M*(5+nc) 104 | if(canUseGPU()) 105 | outPutFeatures = gather(outPutFeatures); % 推送到CPU上 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /utils/importDarknetNetwork.m: -------------------------------------------------------------------------------- 1 | function [net,hyperParams,numsNetParams,FLOPs] = importDarknetNetwork(cfgfile,weightsfile) 2 | % IMPORTDARKNETNETWORK 3 | % 功能:导入指定的cfgfile,weightsfile到matlab中,本函数适合导入darknet分类网络,yolov3/yolov4请使用importDarknetWeights函数 4 | % 输入:cfgfile, 指定的cfg后缀的模型描述文件 5 | % weighfile, 指定的.weights后缀的二进制文件 6 | % 输出:net, matlab深度学习模型 7 | % hyperParams,结构体,超参配置文件 8 | % numsReadParams,权重参数个数 9 | % FLOPs, 模型计算力 10 | % 注意:1、适合2019b版本及以上 11 | % 2、darknet weights保存顺序依次为BN层offset,scale,mean,variance,Conv层的bias,weights 12 | % 特征图输出output Size = (Input Size – ((Filter Size – 1)*Dilation Factor + 1) + 2*Padding)/Stride + 1 13 | % 参考:1、官方文档,Specify Layers of Convolutional Neural Network 14 | % 2、https://www.zhihu.com/question/65305385 15 | % 3、https://github.com/ultralytics/yolov3/blob/master/models.py 16 | % cuixingxing150@gmail.com 17 | % 2019.8.19 18 | % 19 | arguments 20 | cfgfile (1,:) char 21 | weightsfile (1,:) char 22 | end 23 | 24 | [lgraph,hyperParams,numsNetParams,FLOPs,... 25 | moduleTypeList,moduleInfoList,layerToModuleIndex] = importDarkNetLayers(cfgfile); 26 | assert(length(moduleTypeList)==length(moduleInfoList)); 27 | 28 | %% 读取权重参数文件 29 | fid_w = fopen(weightsfile,'rb'); 30 | if fid_w == -1 31 | error('Author:Function:OpenFile', 'Cannot open file: %s', weightsfile); 32 | end 33 | header = fread(fid_w, 3, '*int32'); 34 | if header(2) > 1 35 | header2 = fread(fid_w, 1, '*int64'); % int64占用8个字节 36 | else 37 | header2 = fread(fid_w, 1, '*int32'); % int32占用4个字节 38 | end 39 | fprintf('Major :%d, Minor :%d,Revision :%d,number of images during training:%d,reading params...\n',... 40 | header(1),header(2),header(3),header2); 41 | weights = fread(fid_w,'*single'); 42 | fclose(fid_w); 43 | 44 | numsWeightsParams = numel(weights); 45 | readSize = 1; 46 | numsModule = length(moduleTypeList); 47 | 48 | for i = 1:numsModule 49 | currentModuleType = moduleTypeList{i}; 50 | currentModuleInfo = moduleInfoList{i}; 51 | if strcmp(currentModuleType,'[convolutional]') 52 | currentModule = lgraph.Layers(i==layerToModuleIndex); 53 | filterSize = str2double(currentModuleInfo.size); 54 | numFilters = str2double(currentModuleInfo.filters); 55 | channels_in = moduleInfoList{i-1}.channels; 56 | 57 | if isfield(currentModuleInfo,'batch_normalize') 58 | % bn bias 59 | bn_bias = weights(readSize:readSize+numFilters-1); 60 | bn_bias = reshape(bn_bias,[1,1,numFilters]); 61 | currentModule(2).Offset = bn_bias; 62 | readSize = readSize+numFilters; 63 | % bn weight 64 | bn_weight = weights(readSize:readSize+numFilters-1); 65 | bn_weight = reshape(bn_weight,[1,1,numFilters]); 66 | currentModule(2).Scale = bn_weight; 67 | readSize = readSize+numFilters; 68 | % bn trainedMean 69 | bn_mean = weights(readSize:readSize+numFilters-1); 70 | bn_mean = reshape(bn_mean,[1,1,numFilters]); 71 | currentModule(2).TrainedMean = bn_mean; 72 | readSize = readSize+numFilters; 73 | % bn trainedVariance 74 | bn_var = weights(readSize:readSize+numFilters-1); 75 | bn_var = reshape(bn_var,[1,1,numFilters]); 76 | if any(bn_var<-0.01) 77 | error("方差应该大于0!"); 78 | end 79 | currentModule(2).TrainedVariance = abs(bn_var); % 防止接近于0的数是负数 80 | readSize = readSize+numFilters; 81 | % conv bias 为0 82 | if isfield(currentModuleInfo,'groups') 83 | numGroups = str2double(currentModuleInfo.groups); 84 | numFiltersPerGroup_out = numFilters/numGroups; 85 | currentModule(1).Bias = zeros(1,1,numFiltersPerGroup_out,numGroups,'single'); 86 | else 87 | currentModule(1).Bias = zeros(1,1,numFilters,'single'); 88 | end 89 | else 90 | % load conv bias 91 | conv_bias = weights(readSize:readSize+numFilters-1); 92 | if isfield(currentModuleInfo,'groups') 93 | numGroups = str2double(currentModuleInfo.groups); 94 | numFiltersPerGroup_out = numFilters/numGroups; 95 | conv_bias = reshape(conv_bias,1,1,numFiltersPerGroup_out,numGroups); 96 | else 97 | conv_bias = reshape(conv_bias,1,1,numFilters); 98 | end 99 | currentModule(1).Bias = conv_bias; 100 | readSize = readSize+numFilters; 101 | end % end of is bn 102 | % load conv weights 103 | if isfield(currentModuleInfo,'groups') 104 | numGroups = str2double(currentModuleInfo.groups); 105 | numFiltersPerGroup_out = numFilters/numGroups; 106 | nums_conv_w = filterSize*filterSize*channels_in/numGroups*numFiltersPerGroup_out*numGroups; 107 | conv_weights = weights(readSize:readSize+nums_conv_w-1); 108 | conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in/numGroups,numFiltersPerGroup_out,numGroups); 109 | conv_weights = permute(conv_weights,[2,1,3,4,5]); 110 | currentModule(1).Weights = conv_weights; 111 | readSize = readSize+nums_conv_w; 112 | else 113 | nums_conv_w = filterSize*filterSize*channels_in*numFilters;% weights 114 | conv_weights = weights(readSize:readSize+nums_conv_w-1); 115 | conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in,numFilters); 116 | conv_weights = permute(conv_weights,[2,1,3,4]); 117 | currentModule(1).Weights = conv_weights; 118 | readSize = readSize+nums_conv_w; 119 | end % end of load conv weights 120 | % 更新参数 121 | % lgraph.Layers(i==layerToModuleIndex) = currentModule; 122 | for replaceInd = 1:length(currentModule) 123 | layerName = currentModule(replaceInd).Name; 124 | lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd)); 125 | end 126 | end % end of module '[convolutional]' 127 | 128 | % fullyConnectedLayer 129 | if strcmp(currentModuleType,'[connected]') 130 | currentModule = lgraph.Layers(i==layerToModuleIndex); 131 | numFilters = str2double(currentModuleInfo.output); 132 | % load fc bias 133 | numBias = numFilters; 134 | fl_bias = weights(readSize:readSize+numBias-1); 135 | fl_bias = reshape(fl_bias,numBias,1); 136 | currentModule(1).Bias = fl_bias; 137 | readSize = readSize+numBias; 138 | % load fc weights 139 | input_all_neurons = prod(moduleInfoList{i-1}.mapSize)*moduleInfoList{i-1}.channels; 140 | numWeights = numFilters*input_all_neurons; % help fullyConnectedLayer weights 141 | fl_weights = weights(readSize:readSize+numWeights-1); 142 | fl_weights = reshape(fl_weights,input_all_neurons,numFilters); 143 | fl_weights = permute(fl_weights,[2,1]);% fc不需要permute? 144 | currentModule(1).Weights = fl_weights; 145 | readSize = readSize+numWeights; 146 | % 更新参数 147 | for replaceInd = 1:length(currentModule) 148 | layerName = currentModule(replaceInd).Name; 149 | lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd)); 150 | end 151 | end % end of module '[connected]' 152 | end % end of nums of module 153 | 154 | if isa(lgraph.Layers(end),'nnet.cnn.layer.SoftmaxLayer') 155 | lastLayerName = lgraph.Layers(end).Name; 156 | classifyLayer = classificationLayer('Name','classify'); 157 | lgraph = addLayers(lgraph,classifyLayer); 158 | lgraph = connectLayers(lgraph,lastLayerName,'classify'); 159 | end 160 | 161 | assert(readSize-1==numsWeightsParams); 162 | fprintf('Load parameters succfully! now start to assemble Network...\n') 163 | warning('off'); 164 | net = assembleNetwork(lgraph); 165 | fprintf('Assemble Network succfully!\n') 166 | -------------------------------------------------------------------------------- /utils/importDarknetWeights.m: -------------------------------------------------------------------------------- 1 | function [lgraph,hyperParams,numsNetParams,FLOPs] = importDarknetWeights(cfgfile,weightsfile,cutoffModule) 2 | % IMPORTDARKNETWEIGHTS 功能:指定导入部分module的darknet模型 3 | % 输入:cfgfile, 指定的cfg后缀的模型描述文件 4 | % weighfile, 指定的.weights后缀的二进制文件 5 | % cutoffModule,(可选项)1*1的正整数,(可选项)1*1的正整数,指定导出darknet前cutoffModule个module。以cfg文件中第一个非[net]开始的module为0开始的计数,没有该项则导出整个网络 6 | % 输出:lgraph, matlab深度学习模型计算图 7 | % hyperParams,结构体,超参配置文件 8 | % numsReadParams,权重参数个数 9 | % FLOPs, 模型计算力 10 | % 注意:1、适合2019b版本及以上 11 | % 2、leaky阈值darknet为0.1 12 | % 3、如果某个module中有bn层,则conv的bias为0,因为darknet是这种存储形式 13 | % 4、darknet weights保存顺序依次为BN层offset,scale,mean,variance,Conv层的bias,weights 14 | % 特征图输出output Size = (Input Size – ((Filter Size – 1)*Dilation Factor + 1) + 2*Padding)/Stride + 1 15 | % 参考:1、官方文档,Specify Layers of Convolutional Neural Network 16 | % 2、https://www.zhihu.com/question/65305385 17 | % 3、https://github.com/ultralytics/yolov3/blob/master/models.py 18 | % cuixingxing150@gmail.com 19 | % 2019.8.19 20 | % 2019.9.4修改,由原来的darknet中[net]为0开始的索引改为以cfg文件中第一个非[net]开始的module为0开始的计数的索引 21 | % 2020.4.25修改函数默认输入参数 22 | % 23 | arguments 24 | cfgfile (1,:) char 25 | weightsfile (1,:) char 26 | cutoffModule {mustBeNonnegative} = 0 % 默认导入所有的层 27 | end 28 | 29 | [lgraph,hyperParams,numsNetParams,FLOPs,... 30 | moduleTypeList,moduleInfoList,layerToModuleIndex] = importDarkNetLayers(cfgfile);% only weights需要cutoff,layer都导入 31 | assert(length(moduleTypeList)==length(moduleInfoList)); 32 | 33 | %% 读取权重参数文件 34 | fid_w = fopen(weightsfile,'rb'); 35 | if fid_w == -1 36 | error('Author:Function:OpenFile', 'Cannot open file: %s', weightsfile); 37 | end 38 | header = fread(fid_w, 3, '*int32'); 39 | if header(2) > 1 40 | header2 = fread(fid_w, 1, '*int64'); % int64占用8个字节 41 | else 42 | header2 = fread(fid_w, 1, '*int32'); % int32占用4个字节 43 | end 44 | fprintf('Major :%d, Minor :%d,Revision :%d,number of images during training:%d,reading params...\n',... 45 | header(1),header(2),header(3),header2); 46 | weights = fread(fid_w,'*single'); 47 | fclose(fid_w); 48 | 49 | % numsWeightsParams = numel(weights); 50 | readSize = 1; 51 | numsModule = length(moduleTypeList); 52 | if cutoffModule>0 53 | numsModule = cutoffModule+1;% [net] plus 1 54 | end 55 | 56 | for i = 1:numsModule 57 | currentModuleType = moduleTypeList{i}; 58 | currentModuleInfo = moduleInfoList{i}; 59 | if strcmp(currentModuleType,'[convolutional]') 60 | currentModule = lgraph.Layers(i==layerToModuleIndex); 61 | filterSize = str2double(currentModuleInfo.size); 62 | numFilters = str2double(currentModuleInfo.filters); 63 | channels_in = moduleInfoList{i-1}.channels; 64 | 65 | if isfield(currentModuleInfo,'batch_normalize') 66 | % bn bias 67 | bn_bias = weights(readSize:readSize+numFilters-1); 68 | bn_bias = reshape(bn_bias,[1,1,numFilters]); 69 | currentModule(2).Offset = bn_bias; 70 | readSize = readSize+numFilters; 71 | % bn weight 72 | bn_weight = weights(readSize:readSize+numFilters-1); 73 | bn_weight = reshape(bn_weight,[1,1,numFilters]); 74 | currentModule(2).Scale = bn_weight; 75 | readSize = readSize+numFilters; 76 | % bn trainedMean 77 | bn_mean = weights(readSize:readSize+numFilters-1); 78 | bn_mean = reshape(bn_mean,[1,1,numFilters]); 79 | currentModule(2).TrainedMean = bn_mean; 80 | readSize = readSize+numFilters; 81 | % bn trainedVariance 82 | bn_var = weights(readSize:readSize+numFilters-1); 83 | bn_var = reshape(bn_var,[1,1,numFilters]); 84 | if any(bn_var<-0.01) 85 | error("方差应该大于0!"); 86 | end 87 | currentModule(2).TrainedVariance = abs(bn_var); % 防止接近于0的数是负数 88 | readSize = readSize+numFilters; 89 | % conv bias 为0 90 | if isfield(currentModuleInfo,'groups') 91 | numGroups = str2double(currentModuleInfo.groups); 92 | numFiltersPerGroup_out = numFilters/numGroups; 93 | currentModule(1).Bias = zeros(1,1,numFiltersPerGroup_out,numGroups,'single'); 94 | else 95 | currentModule(1).Bias = zeros(1,1,numFilters,'single'); 96 | end 97 | else 98 | % load conv bias 99 | conv_bias = weights(readSize:readSize+numFilters-1); 100 | if isfield(currentModuleInfo,'groups') 101 | numGroups = str2double(currentModuleInfo.groups); 102 | numFiltersPerGroup_out = numFilters/numGroups; 103 | conv_bias = reshape(conv_bias,1,1,numFiltersPerGroup_out,numGroups); 104 | else 105 | conv_bias = reshape(conv_bias,1,1,numFilters); 106 | end 107 | currentModule(1).Bias = conv_bias; 108 | readSize = readSize+numFilters; 109 | end % end of is bn 110 | % load conv weights 111 | if isfield(currentModuleInfo,'groups') 112 | numGroups = str2double(currentModuleInfo.groups); 113 | numFiltersPerGroup_out = numFilters/numGroups; 114 | nums_conv_w = filterSize*filterSize*channels_in/numGroups*numFiltersPerGroup_out*numGroups; 115 | conv_weights = weights(readSize:readSize+nums_conv_w-1); 116 | conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in/numGroups,numFiltersPerGroup_out,numGroups); 117 | conv_weights = permute(conv_weights,[2,1,3,4,5]); 118 | currentModule(1).Weights = conv_weights; 119 | readSize = readSize+nums_conv_w; 120 | else 121 | nums_conv_w = filterSize*filterSize*channels_in*numFilters;% weights 122 | conv_weights = weights(readSize:readSize+nums_conv_w-1); 123 | conv_weights = reshape(conv_weights,filterSize,filterSize,channels_in,numFilters); 124 | conv_weights = permute(conv_weights,[2,1,3,4]); 125 | currentModule(1).Weights = conv_weights; 126 | readSize = readSize+nums_conv_w; 127 | end % end of load conv weights 128 | % 更新参数 129 | % lgraph.Layers(i==layerToModuleIndex) = currentModule; 130 | for replaceInd = 1:length(currentModule) 131 | layerName = currentModule(replaceInd).Name; 132 | lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd)); 133 | end 134 | end % end of module '[convolutional]' 135 | 136 | % fullyConnectedLayer 137 | if strcmp(currentModuleType,'[connected]') 138 | currentModule = lgraph.Layers(i==layerToModuleIndex); 139 | numFilters = str2double(currentModuleInfo.output); 140 | % load fc bias 141 | numBias = numFilters; 142 | fl_bias = weights(readSize:readSize+numBias-1); 143 | fl_bias = reshape(fl_bias,numBias,1); 144 | currentModule(1).Bias = fl_bias; 145 | readSize = readSize+numBias; 146 | % load fc weights 147 | input_all_neurons = prod(moduleInfoList{i-1}.mapSize)*moduleInfoList{i-1}.channels; 148 | numWeights = numFilters*input_all_neurons; % help fullyConnectedLayer weights 149 | fl_weights = weights(readSize:readSize+numWeights-1); 150 | fl_weights = reshape(fl_weights,input_all_neurons,numFilters); 151 | fl_weights = permute(fl_weights,[2,1]);% fc不需要permute? 152 | currentModule(1).Weights = fl_weights; 153 | readSize = readSize+numWeights; 154 | % 更新参数 155 | for replaceInd = 1:length(currentModule) 156 | layerName = currentModule(replaceInd).Name; 157 | lgraph = replaceLayer(lgraph,layerName,currentModule(replaceInd)); 158 | end 159 | end % end of module '[connected]' 160 | end % end of nums of module 161 | 162 | if isa(lgraph.Layers(end),'nnet.cnn.layer.SoftmaxLayer') 163 | lastLayerName = lgraph.Layers(end).Name; 164 | classifyLayer = classificationLayer('Name','classify'); 165 | lgraph = addLayers(lgraph,classifyLayer); 166 | lgraph = connectLayers(lgraph,lastLayerName,'classify'); 167 | end 168 | 169 | fprintf('Load parameters succfully!\n') 170 | 171 | -------------------------------------------------------------------------------- /cfg/mobilenetv2.cfg: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by MATLAB and may require you to modify it manually 2 | [net] 3 | angle=7 4 | aspect=0.75 5 | batch=64 6 | channels=3 7 | exposure=0.75 8 | height=224 9 | learning_rate=0.01 10 | max_batches=600000 11 | max_crop=256 12 | momentum=0.9 13 | policy=poly 14 | power=4 15 | saturation=0.75 16 | subdivisiions=1 17 | width=224 18 | 19 | # darknet module ID:0 20 | [convolutional] 21 | batch_normalize=1 22 | filters=32 23 | pad=0 24 | size=3 25 | stride=2 26 | activation=relu6 27 | 28 | # darknet module ID:1 29 | [convolutional] 30 | batch_normalize=1 31 | filters=32 32 | groups=32 33 | pad=1 34 | size=3 35 | stride=1 36 | activation=relu6 37 | 38 | # darknet module ID:2 39 | [convolutional] 40 | batch_normalize=1 41 | filters=16 42 | pad=1 43 | size=1 44 | stride=1 45 | activation=linear 46 | 47 | # darknet module ID:3 48 | [convolutional] 49 | batch_normalize=1 50 | filters=96 51 | pad=1 52 | size=1 53 | stride=1 54 | activation=relu6 55 | 56 | # darknet module ID:4 57 | [convolutional] 58 | batch_normalize=1 59 | filters=96 60 | groups=96 61 | pad=0 62 | size=3 63 | stride=2 64 | activation=relu6 65 | 66 | # darknet module ID:5 67 | [convolutional] 68 | batch_normalize=1 69 | filters=24 70 | pad=1 71 | size=1 72 | stride=1 73 | activation=linear 74 | 75 | # darknet module ID:6 76 | [convolutional] 77 | batch_normalize=1 78 | filters=144 79 | pad=1 80 | size=1 81 | stride=1 82 | activation=relu6 83 | 84 | # darknet module ID:7 85 | [convolutional] 86 | batch_normalize=1 87 | filters=144 88 | groups=144 89 | pad=1 90 | size=3 91 | stride=1 92 | activation=relu6 93 | 94 | # darknet module ID:8 95 | [convolutional] 96 | batch_normalize=1 97 | filters=24 98 | pad=1 99 | size=1 100 | stride=1 101 | activation=linear 102 | 103 | # darknet module ID:9 104 | [shortcut] 105 | from=5 106 | activation=linear 107 | 108 | # darknet module ID:10 109 | [convolutional] 110 | batch_normalize=1 111 | filters=144 112 | pad=1 113 | size=1 114 | stride=1 115 | activation=relu6 116 | 117 | # darknet module ID:11 118 | [convolutional] 119 | batch_normalize=1 120 | filters=144 121 | groups=144 122 | pad=0 123 | size=3 124 | stride=2 125 | activation=relu6 126 | 127 | # darknet module ID:12 128 | [convolutional] 129 | batch_normalize=1 130 | filters=32 131 | pad=1 132 | size=1 133 | stride=1 134 | activation=linear 135 | 136 | # darknet module ID:13 137 | [convolutional] 138 | batch_normalize=1 139 | filters=192 140 | pad=1 141 | size=1 142 | stride=1 143 | activation=relu6 144 | 145 | # darknet module ID:14 146 | [convolutional] 147 | batch_normalize=1 148 | filters=192 149 | groups=192 150 | pad=1 151 | size=3 152 | stride=1 153 | activation=relu6 154 | 155 | # darknet module ID:15 156 | [convolutional] 157 | batch_normalize=1 158 | filters=32 159 | pad=1 160 | size=1 161 | stride=1 162 | activation=linear 163 | 164 | # darknet module ID:16 165 | [shortcut] 166 | from=12 167 | activation=linear 168 | 169 | # darknet module ID:17 170 | [convolutional] 171 | batch_normalize=1 172 | filters=192 173 | pad=1 174 | size=1 175 | stride=1 176 | activation=relu6 177 | 178 | # darknet module ID:18 179 | [convolutional] 180 | batch_normalize=1 181 | filters=192 182 | groups=192 183 | pad=1 184 | size=3 185 | stride=1 186 | activation=relu6 187 | 188 | # darknet module ID:19 189 | [convolutional] 190 | batch_normalize=1 191 | filters=32 192 | pad=1 193 | size=1 194 | stride=1 195 | activation=linear 196 | 197 | # darknet module ID:20 198 | [shortcut] 199 | from=16 200 | activation=linear 201 | 202 | # darknet module ID:21 203 | [convolutional] 204 | batch_normalize=1 205 | filters=192 206 | pad=1 207 | size=1 208 | stride=1 209 | activation=relu6 210 | 211 | # darknet module ID:22 212 | [convolutional] 213 | batch_normalize=1 214 | filters=192 215 | groups=192 216 | pad=0 217 | size=3 218 | stride=2 219 | activation=relu6 220 | 221 | # darknet module ID:23 222 | [convolutional] 223 | batch_normalize=1 224 | filters=64 225 | pad=1 226 | size=1 227 | stride=1 228 | activation=linear 229 | 230 | # darknet module ID:24 231 | [convolutional] 232 | batch_normalize=1 233 | filters=384 234 | pad=1 235 | size=1 236 | stride=1 237 | activation=relu6 238 | 239 | # darknet module ID:25 240 | [convolutional] 241 | batch_normalize=1 242 | filters=384 243 | groups=384 244 | pad=1 245 | size=3 246 | stride=1 247 | activation=relu6 248 | 249 | # darknet module ID:26 250 | [convolutional] 251 | batch_normalize=1 252 | filters=64 253 | pad=1 254 | size=1 255 | stride=1 256 | activation=linear 257 | 258 | # darknet module ID:27 259 | [shortcut] 260 | from=23 261 | activation=linear 262 | 263 | # darknet module ID:28 264 | [convolutional] 265 | batch_normalize=1 266 | filters=384 267 | pad=1 268 | size=1 269 | stride=1 270 | activation=relu6 271 | 272 | # darknet module ID:29 273 | [convolutional] 274 | batch_normalize=1 275 | filters=384 276 | groups=384 277 | pad=1 278 | size=3 279 | stride=1 280 | activation=relu6 281 | 282 | # darknet module ID:30 283 | [convolutional] 284 | batch_normalize=1 285 | filters=64 286 | pad=1 287 | size=1 288 | stride=1 289 | activation=linear 290 | 291 | # darknet module ID:31 292 | [shortcut] 293 | from=27 294 | activation=linear 295 | 296 | # darknet module ID:32 297 | [convolutional] 298 | batch_normalize=1 299 | filters=384 300 | pad=1 301 | size=1 302 | stride=1 303 | activation=relu6 304 | 305 | # darknet module ID:33 306 | [convolutional] 307 | batch_normalize=1 308 | filters=384 309 | groups=384 310 | pad=1 311 | size=3 312 | stride=1 313 | activation=relu6 314 | 315 | # darknet module ID:34 316 | [convolutional] 317 | batch_normalize=1 318 | filters=64 319 | pad=1 320 | size=1 321 | stride=1 322 | activation=linear 323 | 324 | # darknet module ID:35 325 | [shortcut] 326 | from=31 327 | activation=linear 328 | 329 | # darknet module ID:36 330 | [convolutional] 331 | batch_normalize=1 332 | filters=384 333 | pad=1 334 | size=1 335 | stride=1 336 | activation=relu6 337 | 338 | # darknet module ID:37 339 | [convolutional] 340 | batch_normalize=1 341 | filters=384 342 | groups=384 343 | pad=1 344 | size=3 345 | stride=1 346 | activation=relu6 347 | 348 | # darknet module ID:38 349 | [convolutional] 350 | batch_normalize=1 351 | filters=96 352 | pad=1 353 | size=1 354 | stride=1 355 | activation=linear 356 | 357 | # darknet module ID:39 358 | [convolutional] 359 | batch_normalize=1 360 | filters=576 361 | pad=1 362 | size=1 363 | stride=1 364 | activation=relu6 365 | 366 | # darknet module ID:40 367 | [convolutional] 368 | batch_normalize=1 369 | filters=576 370 | groups=576 371 | pad=1 372 | size=3 373 | stride=1 374 | activation=relu6 375 | 376 | # darknet module ID:41 377 | [convolutional] 378 | batch_normalize=1 379 | filters=96 380 | pad=1 381 | size=1 382 | stride=1 383 | activation=linear 384 | 385 | # darknet module ID:42 386 | [shortcut] 387 | from=38 388 | activation=linear 389 | 390 | # darknet module ID:43 391 | [convolutional] 392 | batch_normalize=1 393 | filters=576 394 | pad=1 395 | size=1 396 | stride=1 397 | activation=relu6 398 | 399 | # darknet module ID:44 400 | [convolutional] 401 | batch_normalize=1 402 | filters=576 403 | groups=576 404 | pad=1 405 | size=3 406 | stride=1 407 | activation=relu6 408 | 409 | # darknet module ID:45 410 | [convolutional] 411 | batch_normalize=1 412 | filters=96 413 | pad=1 414 | size=1 415 | stride=1 416 | activation=linear 417 | 418 | # darknet module ID:46 419 | [shortcut] 420 | from=42 421 | activation=linear 422 | 423 | # darknet module ID:47 424 | [convolutional] 425 | batch_normalize=1 426 | filters=576 427 | pad=1 428 | size=1 429 | stride=1 430 | activation=relu6 431 | 432 | # darknet module ID:48 433 | [convolutional] 434 | batch_normalize=1 435 | filters=576 436 | groups=576 437 | pad=0 438 | size=3 439 | stride=2 440 | activation=relu6 441 | 442 | # darknet module ID:49 443 | [convolutional] 444 | batch_normalize=1 445 | filters=160 446 | pad=1 447 | size=1 448 | stride=1 449 | activation=linear 450 | 451 | # darknet module ID:50 452 | [convolutional] 453 | batch_normalize=1 454 | filters=960 455 | pad=1 456 | size=1 457 | stride=1 458 | activation=relu6 459 | 460 | # darknet module ID:51 461 | [convolutional] 462 | batch_normalize=1 463 | filters=960 464 | groups=960 465 | pad=1 466 | size=3 467 | stride=1 468 | activation=relu6 469 | 470 | # darknet module ID:52 471 | [convolutional] 472 | batch_normalize=1 473 | filters=160 474 | pad=1 475 | size=1 476 | stride=1 477 | activation=linear 478 | 479 | # darknet module ID:53 480 | [shortcut] 481 | from=49 482 | activation=linear 483 | 484 | # darknet module ID:54 485 | [convolutional] 486 | batch_normalize=1 487 | filters=960 488 | pad=1 489 | size=1 490 | stride=1 491 | activation=relu6 492 | 493 | # darknet module ID:55 494 | [convolutional] 495 | batch_normalize=1 496 | filters=960 497 | groups=960 498 | pad=1 499 | size=3 500 | stride=1 501 | activation=relu6 502 | 503 | # darknet module ID:56 504 | [convolutional] 505 | batch_normalize=1 506 | filters=160 507 | pad=1 508 | size=1 509 | stride=1 510 | activation=linear 511 | 512 | # darknet module ID:57 513 | [shortcut] 514 | from=53 515 | activation=linear 516 | 517 | # darknet module ID:58 518 | [convolutional] 519 | batch_normalize=1 520 | filters=960 521 | pad=1 522 | size=1 523 | stride=1 524 | activation=relu6 525 | 526 | # darknet module ID:59 527 | [convolutional] 528 | batch_normalize=1 529 | filters=960 530 | groups=960 531 | pad=1 532 | size=3 533 | stride=1 534 | activation=relu6 535 | 536 | # darknet module ID:60 537 | [convolutional] 538 | batch_normalize=1 539 | filters=320 540 | pad=1 541 | size=1 542 | stride=1 543 | activation=linear 544 | 545 | # darknet module ID:61 546 | [convolutional] 547 | batch_normalize=1 548 | filters=1280 549 | pad=1 550 | size=1 551 | stride=1 552 | activation=relu6 553 | 554 | # darknet module ID:62 555 | [avgpool] 556 | 557 | # darknet module ID:63 558 | [connected] 559 | output=1000 560 | activation=linear 561 | 562 | # darknet module ID:64 563 | [softmax] 564 | groups=1 565 | 566 | -------------------------------------------------------------------------------- /utils/exportDarkNetNetwork.m: -------------------------------------------------------------------------------- 1 | function exportDarkNetNetwork(net,hyperParams,cfgfileName,weightfileName,cutoffModule) 2 | % EXPORTDARKETNetNetwork 功能:把matlab深度学习模型导出为darknet的模型weights文件 3 | % 输入:net, matlab深度学习模型,SeriesNetwork,DAGNetwork,dlnetwork之一类型 4 | % hyperParams,结构体,超参配置文件,对应cfg文件中的[net]参数 5 | % cutoffModule,(可选项)1*1的正整数,指定导出darknet前cutoffModule个module。cutoffModule是以cfg文件中第一个[convolutional]为0开始的module计数,没有该项则导出整个网络 6 | % 输出: 7 | % cfgfile, 指定的cfg后缀的模型描述文件 8 | % weightfile,制定对应的weights权重文件 9 | % 10 | % 注意:1、relu6用relu激活函数代替,因为clip relu不知道darknet是否实现 11 | % 2、matlab中module以[net]为1开始计数,而darknet中cfg以[convolutional]第一个为0开始计数 12 | % cuixingxing150@gmail.com 13 | % 2019.8.22 14 | % 2019.8.29修改,支持导出relu6 15 | % 2019.9.4修改,由原来的darknet中[net]为0开始的索引改为以cfg文件中第一个非[net]开始的module为0开始的计数的索引 16 | % 2020.4.28修改,加入[yolo]、[upsample]、[route]支持;输入参数限定 17 | % 2020.4.29加入mishLayer导出层支持 18 | % 2020.6.29 加入导出yolov4-tiny支持 19 | % 20 | 21 | arguments 22 | net (1,1) 23 | hyperParams (1,1) struct 24 | cfgfileName (1,:) char 25 | weightfileName (1,:) char 26 | cutoffModule {mustBeNonnegative} = 0 % 默认导出所有的层 27 | end 28 | 29 | %% init 30 | moduleTypeList = []; % cell array,每个cell存储字符向量的模块类型,如'[convolutional]' 31 | moduleInfoList = []; % cell array,每个cell存储结构图的模块信息 32 | layerToModuleIndex = []; % 正整数n*1的vector,每个值代表matlab中从layers映射到module的类别 33 | 34 | %% 1、解析net中模块 35 | module_idx = 1; 36 | layerNames = [];% 字符向量n*1的vector,每个值存储每个层的名字,后面shortcut,route要用到 37 | numsLayers = length(net.Layers); 38 | for i = 1:numsLayers 39 | is_new_module = true;st = struct(); 40 | layerNames = [layerNames;{net.Layers(i).Name}]; 41 | currentLayerType = class(net.Layers(i)); 42 | if strcmpi(currentLayerType,'nnet.cnn.layer.ImageInputLayer') 43 | moduleTypeList = [moduleTypeList;{'[net]'}]; 44 | st = hyperParams; 45 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.Convolution2DLayer') 46 | moduleTypeList = [moduleTypeList;{'[convolutional]'}]; 47 | layer = net.Layers(i); 48 | st = struct('filters',sum(layer.NumFilters),... 49 | 'size',layer.FilterSize(1),... 50 | 'pad',floor(layer.FilterSize(1)/2),...% 2020.5.7修改 51 | 'stride',layer.Stride(1),... 52 | 'activation','linear'); 53 | elseif strcmpi(currentLayerType, 'nnet.cnn.layer.GroupedConvolution2DLayer') 54 | moduleTypeList = [moduleTypeList;{'[convolutional]'}]; 55 | layer = net.Layers(i); 56 | st = struct('groups',layer.NumGroups,... 57 | 'filters',layer.NumGroups*layer.NumFiltersPerGroup,... 58 | 'size',layer.FilterSize(1),... 59 | 'pad',floor(layer.FilterSize(1)/2),...% 2020.5.7修改 60 | 'stride',layer.Stride(1),... 61 | 'activation','linear'); 62 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.FullyConnectedLayer') 63 | moduleTypeList = [moduleTypeList;{'[connected]'}]; 64 | layer = net.Layers(i); 65 | st = struct('output',layer.OutputSize,... 66 | 'activation','linear'); 67 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.BatchNormalizationLayer') 68 | module_idx = module_idx-1; 69 | moduleInfoList{end}.batch_normalize = 1; 70 | is_new_module = false; 71 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.ReLULayer') 72 | module_idx = module_idx-1; 73 | moduleInfoList{end}.activation = 'relu'; 74 | is_new_module = false; 75 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.LeakyReLULayer') 76 | module_idx = module_idx-1; 77 | moduleInfoList{end}.activation = 'leaky'; 78 | is_new_module = false; 79 | elseif strcmpi(currentLayerType,'mishLayer') % 2020.4.29新加入 80 | module_idx = module_idx-1; 81 | moduleInfoList{end}.activation = 'mish'; 82 | is_new_module = false; 83 | elseif strcmpi(currentLayerType,'nnet.onnx.layer.ClipLayer')%当作阈值为6导出 84 | module_idx = module_idx-1; 85 | moduleInfoList{end}.activation = 'relu6'; %实际上类似于matlab的clippedReluLayer,6 86 | is_new_module = false; 87 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.ClippedReLULayer') %当作阈值为6导出 88 | module_idx = module_idx-1; 89 | moduleInfoList{end}.activation = 'relu6'; %实际上类似于matlab的clippedReluLayer,6 90 | is_new_module = false; 91 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.MaxPooling2DLayer') 92 | moduleTypeList = [moduleTypeList;{'[maxpool]'}]; 93 | layer = net.Layers(i); 94 | if i==numsLayers-3||i==numsLayers-2 % 最后一层,留作自动推断特征图大小 95 | st = struct(); 96 | else 97 | if strcmp(layer.PaddingMode,'manual') 98 | st = struct('size',layer.PoolSize(1),... 99 | 'stride',layer.Stride(1),... 100 | 'padding',layer.PaddingSize(1)); 101 | else 102 | st = struct('size',layer.PoolSize(1),... 103 | 'stride',layer.Stride(1)); 104 | end 105 | end 106 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.GlobalMaxPooling2DLayer') 107 | moduleTypeList = [moduleTypeList;{'[maxpool]'}]; 108 | if i==numsLayers-3||i==numsLayers-2% 最后一层,留作自动推断特征图大小 109 | st = struct(); 110 | end 111 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.AveragePooling2DLayer') 112 | moduleTypeList = [moduleTypeList;{'[avgpool]'}]; 113 | layer = net.Layers(i); 114 | if i==numsLayers-3||i==numsLayers-2% 最后一层,留作自动推断特征图大小 115 | st = struct(); 116 | else 117 | if strcmp(layer.PaddingMode,'manual') 118 | st = struct('size',layer.PoolSize(1),... 119 | 'stride',layer.Stride(1),... 120 | 'padding',layer.PaddingSize(1)); 121 | else 122 | st = struct('size',layer.PoolSize(1),... 123 | 'stride',layer.Stride(1)); 124 | end 125 | end 126 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.GlobalAveragePooling2DLayer') 127 | moduleTypeList = [moduleTypeList;{'[avgpool]'}]; 128 | if i==numsLayers-3||i==numsLayers-2% 最后一层,留作自动推断特征图大小 129 | st = struct(); 130 | end 131 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.SoftmaxLayer') 132 | moduleTypeList = [moduleTypeList;{'[softmax]'}]; 133 | st = struct('groups',1); 134 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.AdditionLayer') 135 | moduleTypeList = [moduleTypeList;{'[shortcut]'}]; 136 | st = struct('from',[],'activation','linear'); 137 | layer_name = layerNames{i}; 138 | index_Dlogical = startsWith(net.Connections.Destination,[layer_name,'/']); 139 | source = net.Connections.Source(index_Dlogical); 140 | index_Slogical = contains(layerNames(1:end-1),source); 141 | st.from = layerToModuleIndex(index_Slogical)-2; % -2 darknet module 是以第一个非[net]开始的module为0的计数 142 | st.from = num2str(min(st.from)); % 2019.8.29修改 143 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.DepthConcatenationLayer') 144 | moduleTypeList = [moduleTypeList;{'[route]'}]; 145 | st = struct('layers',[]); 146 | layer_name = layerNames{i}; 147 | index_Dlogical = startsWith(net.Connections.Destination,[layer_name,'/']); 148 | source = net.Connections.Source(index_Dlogical); 149 | index_Slogical = ismember(layerNames(1:end-1),source); % 2020.4.29日contains改为ismember 150 | st.layers = layerToModuleIndex(index_Slogical)-2; % -2 darknet module 是以第一个非[net]开始的module为0的计数 151 | st.layers = join(string(flip(st.layers)),','); % 注意route多个层连接顺序,先连接最近的层,再连接较远的层 152 | elseif strcmpi(currentLayerType,'nnet.cnn.layer.DropoutLayer') 153 | moduleTypeList = [moduleTypeList;{'[dropout]'}]; 154 | layer = net.Layers(i); 155 | st = struct('probability',layer.Probability); 156 | elseif strcmpi(currentLayerType,'upsample2dLayer') 157 | moduleTypeList = [moduleTypeList;{'[upsample]'}]; 158 | layer = net.Layers(i); 159 | st = struct('stride',layer.size); 160 | elseif strcmpi(currentLayerType,'empty2dLayer') 161 | moduleTypeList = [moduleTypeList;{'[route]'}]; 162 | layer = net.Layers(i); 163 | st = struct('layers',[]); 164 | st.layers = layer.connectID; 165 | elseif strcmpi(currentLayerType,'sliceLayer') 166 | moduleTypeList = [moduleTypeList;{'[route]'}]; 167 | layer = net.Layers(i); 168 | st = struct('layers',layer.connectID,... 169 | 'groups',layer.groups,... 170 | 'group_id',layer.group_id-1); 171 | elseif strcmpi(currentLayerType,'yoloV3Layer') 172 | moduleTypeList = [moduleTypeList;{'[yolo]'}]; 173 | layer = net.Layers(i); 174 | anchors = layer.anchors';% 2*n 175 | anchors = reshape(anchors(:),1,[]); % 1*m 176 | st = struct('mask',join(string(layer.mask-1),','),... 177 | 'anchors',join(string(anchors),','),... 178 | 'classes',num2str(layer.classes),... 179 | 'num',num2str(layer.num),... 180 | 'jitter',num2str(layer.jitter),... 181 | 'ignore_thresh',num2str(layer.ignore_thresh),... 182 | 'truth_thresh',num2str(layer.truth_thresh),... 183 | 'random',num2str(layer.random)); 184 | elseif strcmpi(currentLayerType, 'nnet.cnn.layer.ClassificationOutputLayer') 185 | continue; 186 | else 187 | moduleTypeList = [moduleTypeList;{'[unknow]'}];% 这里需要手动在cfg文件中修改 188 | st = struct('error',['unsupported this type:',currentLayerType,... 189 | ',you should manully modify it!']); 190 | end 191 | % 更新 192 | if is_new_module 193 | moduleInfoList = [moduleInfoList;{st}]; 194 | end 195 | layerToModuleIndex = [layerToModuleIndex;module_idx]; 196 | module_idx = module_idx+1; 197 | end % 终止解析 198 | 199 | %% cutoff 200 | if cutoffModule 201 | moduleTypeList(cutoffModule+2:end) = []; 202 | moduleInfoList(cutoffModule+2:end) = []; 203 | end 204 | 205 | %% 2、写入cfg模型描述文件 206 | assert(length(moduleTypeList)==length(moduleInfoList)); 207 | nums_module = length(moduleTypeList); 208 | fid_cfg = fopen(cfgfileName,'w'); 209 | for i = 1:nums_module 210 | currentModuleType = moduleTypeList{i};% currentModuleType是字符向量类型 211 | currentModuleInfo = moduleInfoList{i}; % currentModuleInfo是struct类型 212 | % 逐个module参数写入 213 | if i==1 214 | fprintf(fid_cfg,'%s\n','# This file is automatically generated by MATLAB and may require you to modify it manually');% 注释部分 215 | fprintf(fid_cfg,'%s\n',currentModuleType);% module的名字 216 | else 217 | fprintf(fid_cfg,'%s\n',['# darknet module ID:',num2str(i-2)]); %cfg中正式部分 218 | fprintf(fid_cfg,'%s\n',currentModuleType);% module的名字 219 | end 220 | fields = sort(fieldnames(currentModuleInfo)); 221 | if (~isempty(fields)) && contains(fields{1},'activation') 222 | fields = circshift(fields,-1);% 左移一位,即移到最后 223 | end 224 | for j = 1:length(fields) %写入module的结构体信息 225 | fieldname = fields{j}; 226 | fieldvalue = currentModuleInfo.(fieldname); 227 | fprintf(fid_cfg,'%s=%s\n',fieldname,num2str(fieldvalue));% module的名字 228 | end 229 | fprintf(fid_cfg,'\n'); 230 | end 231 | fclose(fid_cfg); 232 | 233 | %% 3、保存weights权重 234 | fid_weight = fopen(weightfileName,'wb'); 235 | fwrite(fid_weight,[0,2,5],'int32');% version 236 | fwrite(fid_weight,0,'int64'); % number images in train 237 | nums_module = length(moduleTypeList); 238 | for module_index = 1:nums_module 239 | currentModuleType = moduleTypeList{module_index};% 字符向量 240 | currentModuleInfo = moduleInfoList{module_index}; % struct 241 | currentModule = net.Layers(module_index == layerToModuleIndex); 242 | if strcmp(currentModuleType,'[convolutional]')||strcmp(currentModuleType,'[connected]') 243 | conv_layer = currentModule(1); 244 | % 如果该module有BN,首先存储BN的参数 245 | if isfield(currentModuleInfo,'batch_normalize') % darknet一个弊端,丢弃了conv bias的参数 246 | bn_layer = currentModule(2); 247 | bn_bias = bn_layer.Offset; 248 | fwrite(fid_weight,bn_bias(:),'single'); 249 | bn_weights = bn_layer.Scale; 250 | fwrite(fid_weight,bn_weights(:),'single'); 251 | bn_mean = bn_layer.TrainedMean; 252 | fwrite(fid_weight,bn_mean(:),'single'); 253 | bn_var = bn_layer.TrainedVariance; 254 | fwrite(fid_weight,bn_var(:),'single'); 255 | else 256 | % conv bias 257 | conv_bias = conv_layer.Bias; 258 | conv_bias = permute(conv_bias,[2,1,3,4]);% 支持 groupedConvolution2dLayer 259 | fwrite(fid_weight,conv_bias(:),'single'); 260 | end 261 | % conv weights 262 | conv_weights = conv_layer.Weights; 263 | conv_weights = permute(conv_weights,[2,1,3,4,5]);% 支持 groupedConvolution2dLayer 264 | fwrite(fid_weight,conv_weights(:),'single'); 265 | end 266 | end 267 | fclose(fid_weight); 268 | 269 | -------------------------------------------------------------------------------- /cfg/yolov3.cfg: -------------------------------------------------------------------------------- 1 | [net] 2 | # Testing 3 | # batch=1 4 | # subdivisions=1 5 | # Training 6 | batch=64 7 | subdivisions=16 8 | width=416 9 | height=416 10 | channels=3 11 | momentum=0.9 12 | decay=0.0005 13 | angle=0 14 | saturation = 1.5 15 | exposure = 1.5 16 | hue=.1 17 | 18 | learning_rate=0.001 19 | burn_in=1000 20 | max_batches = 500200 21 | policy=steps 22 | steps=400000,450000 23 | scales=.1,.1 24 | 25 | [convolutional] 26 | batch_normalize=1 27 | filters=32 28 | size=3 29 | stride=1 30 | pad=1 31 | activation=leaky 32 | 33 | # Downsample 34 | 35 | [convolutional] 36 | batch_normalize=1 37 | filters=64 38 | size=3 39 | stride=2 40 | pad=1 41 | activation=leaky 42 | 43 | [convolutional] 44 | batch_normalize=1 45 | filters=32 46 | size=1 47 | stride=1 48 | pad=1 49 | activation=leaky 50 | 51 | [convolutional] 52 | batch_normalize=1 53 | filters=64 54 | size=3 55 | stride=1 56 | pad=1 57 | activation=leaky 58 | 59 | [shortcut] 60 | from=-3 61 | activation=linear 62 | 63 | # Downsample 64 | 65 | [convolutional] 66 | batch_normalize=1 67 | filters=128 68 | size=3 69 | stride=2 70 | pad=1 71 | activation=leaky 72 | 73 | [convolutional] 74 | batch_normalize=1 75 | filters=64 76 | size=1 77 | stride=1 78 | pad=1 79 | activation=leaky 80 | 81 | [convolutional] 82 | batch_normalize=1 83 | filters=128 84 | size=3 85 | stride=1 86 | pad=1 87 | activation=leaky 88 | 89 | [shortcut] 90 | from=-3 91 | activation=linear 92 | 93 | [convolutional] 94 | batch_normalize=1 95 | filters=64 96 | size=1 97 | stride=1 98 | pad=1 99 | activation=leaky 100 | 101 | [convolutional] 102 | batch_normalize=1 103 | filters=128 104 | size=3 105 | stride=1 106 | pad=1 107 | activation=leaky 108 | 109 | [shortcut] 110 | from=-3 111 | activation=linear 112 | 113 | # Downsample 114 | 115 | [convolutional] 116 | batch_normalize=1 117 | filters=256 118 | size=3 119 | stride=2 120 | pad=1 121 | activation=leaky 122 | 123 | [convolutional] 124 | batch_normalize=1 125 | filters=128 126 | size=1 127 | stride=1 128 | pad=1 129 | activation=leaky 130 | 131 | [convolutional] 132 | batch_normalize=1 133 | filters=256 134 | size=3 135 | stride=1 136 | pad=1 137 | activation=leaky 138 | 139 | [shortcut] 140 | from=-3 141 | activation=linear 142 | 143 | [convolutional] 144 | batch_normalize=1 145 | filters=128 146 | size=1 147 | stride=1 148 | pad=1 149 | activation=leaky 150 | 151 | [convolutional] 152 | batch_normalize=1 153 | filters=256 154 | size=3 155 | stride=1 156 | pad=1 157 | activation=leaky 158 | 159 | [shortcut] 160 | from=-3 161 | activation=linear 162 | 163 | [convolutional] 164 | batch_normalize=1 165 | filters=128 166 | size=1 167 | stride=1 168 | pad=1 169 | activation=leaky 170 | 171 | [convolutional] 172 | batch_normalize=1 173 | filters=256 174 | size=3 175 | stride=1 176 | pad=1 177 | activation=leaky 178 | 179 | [shortcut] 180 | from=-3 181 | activation=linear 182 | 183 | [convolutional] 184 | batch_normalize=1 185 | filters=128 186 | size=1 187 | stride=1 188 | pad=1 189 | activation=leaky 190 | 191 | [convolutional] 192 | batch_normalize=1 193 | filters=256 194 | size=3 195 | stride=1 196 | pad=1 197 | activation=leaky 198 | 199 | [shortcut] 200 | from=-3 201 | activation=linear 202 | 203 | 204 | [convolutional] 205 | batch_normalize=1 206 | filters=128 207 | size=1 208 | stride=1 209 | pad=1 210 | activation=leaky 211 | 212 | [convolutional] 213 | batch_normalize=1 214 | filters=256 215 | size=3 216 | stride=1 217 | pad=1 218 | activation=leaky 219 | 220 | [shortcut] 221 | from=-3 222 | activation=linear 223 | 224 | [convolutional] 225 | batch_normalize=1 226 | filters=128 227 | size=1 228 | stride=1 229 | pad=1 230 | activation=leaky 231 | 232 | [convolutional] 233 | batch_normalize=1 234 | filters=256 235 | size=3 236 | stride=1 237 | pad=1 238 | activation=leaky 239 | 240 | [shortcut] 241 | from=-3 242 | activation=linear 243 | 244 | [convolutional] 245 | batch_normalize=1 246 | filters=128 247 | size=1 248 | stride=1 249 | pad=1 250 | activation=leaky 251 | 252 | [convolutional] 253 | batch_normalize=1 254 | filters=256 255 | size=3 256 | stride=1 257 | pad=1 258 | activation=leaky 259 | 260 | [shortcut] 261 | from=-3 262 | activation=linear 263 | 264 | [convolutional] 265 | batch_normalize=1 266 | filters=128 267 | size=1 268 | stride=1 269 | pad=1 270 | activation=leaky 271 | 272 | [convolutional] 273 | batch_normalize=1 274 | filters=256 275 | size=3 276 | stride=1 277 | pad=1 278 | activation=leaky 279 | 280 | [shortcut] 281 | from=-3 282 | activation=linear 283 | 284 | # Downsample 285 | 286 | [convolutional] 287 | batch_normalize=1 288 | filters=512 289 | size=3 290 | stride=2 291 | pad=1 292 | activation=leaky 293 | 294 | [convolutional] 295 | batch_normalize=1 296 | filters=256 297 | size=1 298 | stride=1 299 | pad=1 300 | activation=leaky 301 | 302 | [convolutional] 303 | batch_normalize=1 304 | filters=512 305 | size=3 306 | stride=1 307 | pad=1 308 | activation=leaky 309 | 310 | [shortcut] 311 | from=-3 312 | activation=linear 313 | 314 | 315 | [convolutional] 316 | batch_normalize=1 317 | filters=256 318 | size=1 319 | stride=1 320 | pad=1 321 | activation=leaky 322 | 323 | [convolutional] 324 | batch_normalize=1 325 | filters=512 326 | size=3 327 | stride=1 328 | pad=1 329 | activation=leaky 330 | 331 | [shortcut] 332 | from=-3 333 | activation=linear 334 | 335 | 336 | [convolutional] 337 | batch_normalize=1 338 | filters=256 339 | size=1 340 | stride=1 341 | pad=1 342 | activation=leaky 343 | 344 | [convolutional] 345 | batch_normalize=1 346 | filters=512 347 | size=3 348 | stride=1 349 | pad=1 350 | activation=leaky 351 | 352 | [shortcut] 353 | from=-3 354 | activation=linear 355 | 356 | 357 | [convolutional] 358 | batch_normalize=1 359 | filters=256 360 | size=1 361 | stride=1 362 | pad=1 363 | activation=leaky 364 | 365 | [convolutional] 366 | batch_normalize=1 367 | filters=512 368 | size=3 369 | stride=1 370 | pad=1 371 | activation=leaky 372 | 373 | [shortcut] 374 | from=-3 375 | activation=linear 376 | 377 | [convolutional] 378 | batch_normalize=1 379 | filters=256 380 | size=1 381 | stride=1 382 | pad=1 383 | activation=leaky 384 | 385 | [convolutional] 386 | batch_normalize=1 387 | filters=512 388 | size=3 389 | stride=1 390 | pad=1 391 | activation=leaky 392 | 393 | [shortcut] 394 | from=-3 395 | activation=linear 396 | 397 | 398 | [convolutional] 399 | batch_normalize=1 400 | filters=256 401 | size=1 402 | stride=1 403 | pad=1 404 | activation=leaky 405 | 406 | [convolutional] 407 | batch_normalize=1 408 | filters=512 409 | size=3 410 | stride=1 411 | pad=1 412 | activation=leaky 413 | 414 | [shortcut] 415 | from=-3 416 | activation=linear 417 | 418 | 419 | [convolutional] 420 | batch_normalize=1 421 | filters=256 422 | size=1 423 | stride=1 424 | pad=1 425 | activation=leaky 426 | 427 | [convolutional] 428 | batch_normalize=1 429 | filters=512 430 | size=3 431 | stride=1 432 | pad=1 433 | activation=leaky 434 | 435 | [shortcut] 436 | from=-3 437 | activation=linear 438 | 439 | [convolutional] 440 | batch_normalize=1 441 | filters=256 442 | size=1 443 | stride=1 444 | pad=1 445 | activation=leaky 446 | 447 | [convolutional] 448 | batch_normalize=1 449 | filters=512 450 | size=3 451 | stride=1 452 | pad=1 453 | activation=leaky 454 | 455 | [shortcut] 456 | from=-3 457 | activation=linear 458 | 459 | # Downsample 460 | 461 | [convolutional] 462 | batch_normalize=1 463 | filters=1024 464 | size=3 465 | stride=2 466 | pad=1 467 | activation=leaky 468 | 469 | [convolutional] 470 | batch_normalize=1 471 | filters=512 472 | size=1 473 | stride=1 474 | pad=1 475 | activation=leaky 476 | 477 | [convolutional] 478 | batch_normalize=1 479 | filters=1024 480 | size=3 481 | stride=1 482 | pad=1 483 | activation=leaky 484 | 485 | [shortcut] 486 | from=-3 487 | activation=linear 488 | 489 | [convolutional] 490 | batch_normalize=1 491 | filters=512 492 | size=1 493 | stride=1 494 | pad=1 495 | activation=leaky 496 | 497 | [convolutional] 498 | batch_normalize=1 499 | filters=1024 500 | size=3 501 | stride=1 502 | pad=1 503 | activation=leaky 504 | 505 | [shortcut] 506 | from=-3 507 | activation=linear 508 | 509 | [convolutional] 510 | batch_normalize=1 511 | filters=512 512 | size=1 513 | stride=1 514 | pad=1 515 | activation=leaky 516 | 517 | [convolutional] 518 | batch_normalize=1 519 | filters=1024 520 | size=3 521 | stride=1 522 | pad=1 523 | activation=leaky 524 | 525 | [shortcut] 526 | from=-3 527 | activation=linear 528 | 529 | [convolutional] 530 | batch_normalize=1 531 | filters=512 532 | size=1 533 | stride=1 534 | pad=1 535 | activation=leaky 536 | 537 | [convolutional] 538 | batch_normalize=1 539 | filters=1024 540 | size=3 541 | stride=1 542 | pad=1 543 | activation=leaky 544 | 545 | [shortcut] 546 | from=-3 547 | activation=linear 548 | 549 | ###################### 550 | 551 | [convolutional] 552 | batch_normalize=1 553 | filters=512 554 | size=1 555 | stride=1 556 | pad=1 557 | activation=leaky 558 | 559 | [convolutional] 560 | batch_normalize=1 561 | size=3 562 | stride=1 563 | pad=1 564 | filters=1024 565 | activation=leaky 566 | 567 | [convolutional] 568 | batch_normalize=1 569 | filters=512 570 | size=1 571 | stride=1 572 | pad=1 573 | activation=leaky 574 | 575 | [convolutional] 576 | batch_normalize=1 577 | size=3 578 | stride=1 579 | pad=1 580 | filters=1024 581 | activation=leaky 582 | 583 | [convolutional] 584 | batch_normalize=1 585 | filters=512 586 | size=1 587 | stride=1 588 | pad=1 589 | activation=leaky 590 | 591 | [convolutional] 592 | batch_normalize=1 593 | size=3 594 | stride=1 595 | pad=1 596 | filters=1024 597 | activation=leaky 598 | 599 | [convolutional] 600 | size=1 601 | stride=1 602 | pad=1 603 | filters=255 604 | activation=linear 605 | 606 | 607 | [yolo] 608 | mask = 6,7,8 609 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 610 | classes=80 611 | num=9 612 | jitter=.3 613 | ignore_thresh = .7 614 | truth_thresh = 1 615 | random=1 616 | 617 | 618 | [route] 619 | layers = -4 620 | 621 | [convolutional] 622 | batch_normalize=1 623 | filters=256 624 | size=1 625 | stride=1 626 | pad=1 627 | activation=leaky 628 | 629 | [upsample] 630 | stride=2 631 | 632 | [route] 633 | layers = -1, 61 634 | 635 | 636 | 637 | [convolutional] 638 | batch_normalize=1 639 | filters=256 640 | size=1 641 | stride=1 642 | pad=1 643 | activation=leaky 644 | 645 | [convolutional] 646 | batch_normalize=1 647 | size=3 648 | stride=1 649 | pad=1 650 | filters=512 651 | activation=leaky 652 | 653 | [convolutional] 654 | batch_normalize=1 655 | filters=256 656 | size=1 657 | stride=1 658 | pad=1 659 | activation=leaky 660 | 661 | [convolutional] 662 | batch_normalize=1 663 | size=3 664 | stride=1 665 | pad=1 666 | filters=512 667 | activation=leaky 668 | 669 | [convolutional] 670 | batch_normalize=1 671 | filters=256 672 | size=1 673 | stride=1 674 | pad=1 675 | activation=leaky 676 | 677 | [convolutional] 678 | batch_normalize=1 679 | size=3 680 | stride=1 681 | pad=1 682 | filters=512 683 | activation=leaky 684 | 685 | [convolutional] 686 | size=1 687 | stride=1 688 | pad=1 689 | filters=255 690 | activation=linear 691 | 692 | 693 | [yolo] 694 | mask = 3,4,5 695 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 696 | classes=80 697 | num=9 698 | jitter=.3 699 | ignore_thresh = .7 700 | truth_thresh = 1 701 | random=1 702 | 703 | 704 | 705 | [route] 706 | layers = -4 707 | 708 | [convolutional] 709 | batch_normalize=1 710 | filters=128 711 | size=1 712 | stride=1 713 | pad=1 714 | activation=leaky 715 | 716 | [upsample] 717 | stride=2 718 | 719 | [route] 720 | layers = -1, 36 721 | 722 | 723 | 724 | [convolutional] 725 | batch_normalize=1 726 | filters=128 727 | size=1 728 | stride=1 729 | pad=1 730 | activation=leaky 731 | 732 | [convolutional] 733 | batch_normalize=1 734 | size=3 735 | stride=1 736 | pad=1 737 | filters=256 738 | activation=leaky 739 | 740 | [convolutional] 741 | batch_normalize=1 742 | filters=128 743 | size=1 744 | stride=1 745 | pad=1 746 | activation=leaky 747 | 748 | [convolutional] 749 | batch_normalize=1 750 | size=3 751 | stride=1 752 | pad=1 753 | filters=256 754 | activation=leaky 755 | 756 | [convolutional] 757 | batch_normalize=1 758 | filters=128 759 | size=1 760 | stride=1 761 | pad=1 762 | activation=leaky 763 | 764 | [convolutional] 765 | batch_normalize=1 766 | size=3 767 | stride=1 768 | pad=1 769 | filters=256 770 | activation=leaky 771 | 772 | [convolutional] 773 | size=1 774 | stride=1 775 | pad=1 776 | filters=255 777 | activation=linear 778 | 779 | 780 | [yolo] 781 | mask = 0,1,2 782 | anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326 783 | classes=80 784 | num=9 785 | jitter=.3 786 | ignore_thresh = .7 787 | truth_thresh = 1 788 | random=1 -------------------------------------------------------------------------------- /train.m: -------------------------------------------------------------------------------- 1 | addpath('./CustomLayers/','./utils/') 2 | %% 1、准备数据,适合yolov3,yolov4,无需VOC-xml格式 3 | % 数据问题参考,满足以下其一即可: 4 | % 1、matlab中标注参考 https://ww2.mathworks.cn/help/vision/ug/get-started-with-the-image-labeler.html?requestedDomain=cn 5 | % 2、外部标注文件导入到matlab参考 https://github.com/cuixing158/imageLabeler-API.git 6 | load gTruth.mat % 自己bbox标注文件,格式参考上面链接,最终为table类型,看起来直观 7 | cfg_file = './cfg/yolov3-tiny.cfg'; 8 | weight_file = './weights/yolov3-tiny.weights'; %预训练backbone权重,其他类型也OK 9 | annotateImgHeight = 416; % 自己标注的图像原始高度 10 | annotateImgWeight = 416; % 自己标注的图像原始宽度 11 | 12 | % 类别名字和对应的ID序号 13 | classesNames = gTruth.Properties.VariableNames(2:end); 14 | classIDs = (0:length(classesNames)-1);% 从0开始标注,保持与darknet官网一致 15 | numClasses = length(classesNames); 16 | structNamesIDs = struct(); 17 | for i = 1:numClasses 18 | structNamesIDs.(classesNames{i}) = classIDs(i); 19 | end 20 | 21 | % 创建可迭代的数据集 22 | bldsTrain = boxLabelDatastore(gTruth(:, 2:end)); 23 | imdsTrain = imageDatastore(gTruth.imageFilename); 24 | miniBatch = 16; 25 | imdsTrain.ReadSize = miniBatch; 26 | bldsTrain.ReadSize = miniBatch; 27 | trainingData = combine(imdsTrain, bldsTrain); 28 | 29 | %% 设定超参数,导入训练权重或者导入matlab其他官方预训练权重,这里以darknet中的".weight"二进制权重 30 | [lgModel,hyperParams] = importDarknetWeights(cfg_file,weight_file); 31 | % analyzeNetwork(lgModel); 32 | 33 | inputWeight = str2double(hyperParams.width); 34 | inputHeight = str2double(hyperParams.height); 35 | networkInputSize = [inputHeight inputWeight 3]; 36 | preprocessedTrainingData = transform(trainingData,@(data)preprocessTrainData(data,networkInputSize,structNamesIDs)); 37 | 38 | % 预览数据 39 | for k = 1:1 40 | data = read(preprocessedTrainingData); 41 | I = data{1,1}{1}; 42 | bbox = data{1,2}{1}; 43 | annotatedImage = zeros(size(I),'like',I); 44 | for i = 1:size(I,4) 45 | annotatedImage(:,:,:,i) = insertShape(I(:,:,:,i),'Rectangle',bbox{i}(:,1:4)); 46 | end 47 | annotatedImage = imresize(annotatedImage,2); 48 | figure 49 | montage(annotatedImage) 50 | end 51 | 52 | numAnchors = 6; 53 | anchorBoxes = estimateAnchorBoxes(trainingData,numAnchors);% anchorBoxes是networkInputSize上的大小,但是 estimateAnchorBoxes函数输入参数限制太死,无法把preprocessedTrainingData传入 54 | area = anchorBoxes(:, 1).*anchorBoxes(:, 2); 55 | [~, idx] = sort(area, 'descend'); 56 | anchorBoxes = anchorBoxes(idx, :); 57 | anchorBoxes = round(anchorBoxes); 58 | anchorBoxMasks = {[1,2,3],[4,5,6]};% 面积大的anchor结合特征图较小的yolov3层,面积小的anchor结合特征图较大的yolov3层 59 | 60 | 61 | %% 2,搭建darknet网络,加入yolov3Layer 62 | anchorBoxes(:,[2,1]) = anchorBoxes(:,[1,2]);% anchorBoxes现在是宽高,与darknet官网保持一致 63 | imageSize = lgModel.Layers(1).InputSize(1:2); 64 | yoloModule1 = [convolution2dLayer(1,length(anchorBoxMasks{1})*(5+numClasses),'Name','yoloconv1'); 65 | yolov3Layer('yolov3layer1',anchorBoxMasks{1},anchorBoxes,numClasses,1,imageSize)]; 66 | yoloModule2 = [convolution2dLayer(1,length(anchorBoxMasks{2})*(5+numClasses),'Name','yoloconv2'); 67 | yolov3Layer('yolov3layer2',anchorBoxMasks{2},anchorBoxes,numClasses,2,imageSize)]; 68 | lgModel = removeLayers(lgModel,{'yolo_v3_id1','yolo_v3_id2'}); 69 | lgModel = replaceLayer(lgModel,'conv_17',yoloModule1); 70 | lgModel = replaceLayer(lgModel,'conv_24',yoloModule2); 71 | 72 | analyzeNetwork(lgModel); 73 | yoloLayerNumber = [36,47];% yolov3层在layers数组中的位置,看模型图得出!!! 74 | model = dlnetwork(lgModel); % dlnetwork函数耗时过长!一个转换操作而已 75 | 76 | %% 3,for loop循环迭代更新模型 77 | % 训练选项 78 | learningRate = 0.001; 79 | scheduler = @(epoch,epochs)0.5*(1+cos(epoch*pi/epochs));% cosine https://arxiv.org/pdf/1812.01187.pdf 80 | l2Regularization = 0.0005; 81 | velocity = []; 82 | 83 | executionEnvironment = "auto"; 84 | figure; 85 | ax1 = subplot(211); 86 | ax2 = subplot(212); 87 | lossPlotter = animatedline(ax1); 88 | learningRatePlotter = animatedline(ax2); 89 | 90 | nEpochs = 10; 91 | allIteration = 0; 92 | cumLoss = 0; 93 | meanLoss = 0; 94 | for numEpoch = 1:nEpochs 95 | reset(preprocessedTrainingData);% Reset datastore. 96 | iteration = 0; 97 | while hasdata(preprocessedTrainingData) 98 | t_start = tic; 99 | % Custom training loop. 100 | % Read batch of data and create batch of images and 101 | % ground truths. 102 | outDataTable = read(preprocessedTrainingData); 103 | XTrain = outDataTable{1,1}{1}; 104 | YTrain = outDataTable{1,2}{1}; 105 | if isempty(YTrain) 106 | continue; 107 | end 108 | 109 | % Convert mini-batch of data to dlarray. 110 | XTrain = dlarray(single(XTrain),'SSCB'); 111 | 112 | % If training on a GPU, then convert data to gpuArray. 113 | if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" 114 | XTrain = gpuArray(XTrain); 115 | end 116 | 117 | % Evaluate the model gradients and loss using dlfeval and the 118 | % modelGradients function. 119 | [gradients,boxLoss,objLoss,clsLoss,totalLoss,state] = dlfeval(@modelGradients, model, XTrain, YTrain,yoloLayerNumber); 120 | 121 | % Apply L2 regularization. 122 | gradients = dlupdate(@(g,w) g + l2Regularization*w, gradients, model.Learnables); 123 | 124 | % Update the network learnable parameters using the SGDM optimizer. 125 | [model, velocity] = sgdmupdate(model, gradients, velocity, learningRate); 126 | 127 | % Update the state parameters of dlnetwork. 128 | model.State = state; 129 | fprintf('[%d][%d/%d]\t BatchTime(s):%.2f , LR:%.5f, boxLoss:%-12.3f, objLoss:%-12.3f, clsLoss:%-12.3f, totalLoss:%-12.5f, meanLoss:%-12.5f\n',... 130 | numEpoch,iteration+1,floor(numpartitions(preprocessedTrainingData)/miniBatch),... 131 | toc(t_start),learningRate,boxLoss,objLoss,clsLoss,totalLoss,cumLoss/(allIteration+1)); 132 | if isnan(totalLoss) 133 | fprintf('loss is nan!'); 134 | return 135 | end 136 | 137 | cumLoss = cumLoss+totalLoss; 138 | iteration = iteration +1; 139 | allIteration = allIteration+1; 140 | end 141 | meanLoss = cumLoss/allIteration; 142 | 143 | % save model 144 | if (mod(numEpoch,5)==0) % 设置每5个epoch保存下权重 145 | timeStr = datestr(now,'yyyy_mm_dd_HH_MM_SS'); 146 | matlabModel = fullfile('./save',[timeStr,'.mat']); 147 | save(matlabModel,'model'); 148 | 149 | cfgFile = fullfile('./cfg',[timeStr,'.cfg']); 150 | darknetModel = fullfile('./weights',[timeStr,'.weights']); 151 | exportDarkNetNetwork(model,hyperParams,cfgFile,darknetModel); 152 | end 153 | 154 | % Update training plot with new points. 155 | addpoints(lossPlotter, numEpoch, double(meanLoss)); 156 | 157 | % update scheduler 158 | learningRate = scheduler(numEpoch,nEpochs); 159 | addpoints(learningRatePlotter, numEpoch, learningRate); 160 | drawnow 161 | end 162 | 163 | %% yolov3 损失函数 164 | function [gradients, boxLoss, objLoss, clsLoss, totalLoss, state] = modelGradients(net, XTrain, YTrain,yoloLayerNumber) 165 | % 功能:计算模型梯度,求取损失 166 | % allYoloLayers = net.Layers(yoloLayerNumber); 167 | yolov3layerNames = net.OutputNames; 168 | outFeatureMaps = cell(size(yolov3layerNames)); 169 | [outFeatureMaps{:},state] = forward(net,XTrain,'Outputs',yolov3layerNames); 170 | boxLoss = dlarray(0); 171 | objLoss = dlarray(0); 172 | clsLoss = dlarray(0); 173 | for i = 1:length(outFeatureMaps) 174 | currentYOLOV3Layer = net.Layers(yoloLayerNumber(i)); 175 | currentFeatureMap = outFeatureMaps{i}; 176 | 177 | % 由于yolov3Layer类里面predict函数未改变类属性,故重新给属性赋值 178 | currentYOLOV3Layer.numY = size(currentFeatureMap,1); 179 | currentYOLOV3Layer.numX = size(currentFeatureMap,2); 180 | currentYOLOV3Layer.stride = max(currentYOLOV3Layer.imageSize)./max(currentYOLOV3Layer.numX,... 181 | currentYOLOV3Layer.numY); 182 | 183 | % reshape currentFeatureMap到有意义的维度,h*w*c*bs --> h*w*(5+nc)*na*bs 184 | % --> bs*na*h*w*(5+nc),最终的维度方式与darknet官网兼容 185 | bs = size(currentFeatureMap,4); 186 | h = currentYOLOV3Layer.numY; 187 | w = currentYOLOV3Layer.numX; 188 | na = currentYOLOV3Layer.nAnchors; 189 | nc = currentYOLOV3Layer.classes; 190 | currentFeatureMap = reshape(currentFeatureMap,h,w,5+nc,na,bs);% h*w*(5+nc)*na*bs 191 | currentFeatureMap = permute(currentFeatureMap,[5,4,1,2,3]);% bs*na*h*w*(5+nc) 192 | 193 | % 构建目标值 194 | [tcls,tbox,indices,anchor_grids] = buildTargets(currentYOLOV3Layer,YTrain); 195 | N = size(tcls,1);% N<=na*YTrain中所有检测框的数量,其代表有效的数量 196 | featuresMapSize = size(currentFeatureMap);% bs*na*h*w*(5+nc) 197 | tobj = zeros(featuresMapSize(1:4),'like',currentFeatureMap);% bs*na*h*w 198 | featuresCh = zeros(N,(5+nc),'like',currentFeatureMap); 199 | if N 200 | b = indices(:,1); % N*1 201 | a = indices(:,2); % N*1 202 | gj = indices(:,3); % N*1 203 | gi = indices(:,4); % N*1 204 | for idx = 1:N 205 | featuresChannels = currentFeatureMap(b(idx),a(idx),gj(idx),gi(idx),:);% 1*1*1*1*(5+nc) 206 | featuresChannels = squeeze(featuresChannels);%(5+nc)*1 207 | featuresChannels = featuresChannels';%1*(5+nc) 208 | featuresCh(idx,:) = featuresChannels; % N*(5+nc) 209 | tobj(b(idx),a(idx),gj(idx),gi(idx)) = 1.0; 210 | end 211 | 212 | % mse or GIoU loss 213 | predictXY = sigmoid(featuresCh(:,1:2)); % 大小为N*2,预测对应xy 214 | predictWH = exp(featuresCh(:,3:4)).*anchor_grids;% 大小为N*2 215 | predictBboxs = cat(2,predictXY,predictWH);% 大小为N*4 216 | isUseGIOU = 0; 217 | if isUseGIOU 218 | giouRatio = getGIOU(predictBboxs,tbox);%梯度需要计算,然而反向传播非常耗时 219 | boxLoss = boxLoss+mean(1-giouRatio,'all'); 220 | else 221 | boxLoss = boxLoss+mse(predictBboxs,tbox,'DataFormat','BC'); 222 | end 223 | 224 | if (nc>1) 225 | tcls_ = zeros('like',featuresCh(:,6:end)); 226 | for idx = 1:N 227 | tcls_(idx,tcls+1) = 1.0;% 确保类别标签是从0开始标注的索引,否则这里会超出维度 228 | end 229 | clsLoss = clsLoss + crossentropy(sigmoid(featuresCh(:,6:end)),tcls_,... 230 | 'DataFormat','BC',... 231 | 'TargetCategories','independent'); 232 | end 233 | end 234 | 235 | if N 236 | objLoss = objLoss+crossentropy(sigmoid(currentFeatureMap(:,:,:,:,5)),tobj,... 237 | 'DataFormat','BUSS',... 238 | 'TargetCategories','independent'); 239 | end 240 | end 241 | totalLoss = boxLoss+objLoss+clsLoss; 242 | 243 | % Compute gradients of learnables with regard to loss. 244 | gradients = dlgradient(totalLoss, net.Learnables); 245 | 246 | boxLoss = gather(extractdata(boxLoss)); 247 | objLoss = gather(extractdata(objLoss)); 248 | clsLoss = gather(extractdata(clsLoss)); 249 | totalLoss = gather(extractdata(totalLoss)); 250 | end 251 | 252 | function [tcls,tbox,indices,anchor_grids] = buildTargets(currentYOLOV3Layer,YTrain) 253 | % 功能:构建目标值 254 | % 输入: 255 | % currentYOLOV3Layer:网络中yolo输出层之一 256 | % YTrain:网络目标值,bs*1大小的cell类型,每个cell下包含Mi*[x,y,width,height,classID]大小的矩阵,Mi为第i张图片含有目标的检测数量, 257 | % 注意其存储的坐标值是相对网络输入图像上的坐标,并无归一化 258 | % 输出: 259 | % tcls:目标真实类别classID,N*1大小,每一项存储classID,其中N<=na*sum(Mi),只输出有效数量的类别N 260 | % tbox:目标的boundingBox,存储真实目标在特征图上的位置(除去x,y整数部分,保留小数),N*4大小,每项形式为[Xdecimal,Ydecimal,gw,gh] 261 | % indices:目标检测框在高维数组中的位置,N*4大小,每一项存储检测框的位置,其形式为[bs,na,gy,gx],他们都是从1开始的索引,与Python不同 262 | % anchor_grids:所用有效的在特征图上的anchor,N*2大小,每项形式为[anchor_w,anchor_h] 263 | % 注意: 264 | % 此函数是核心,用于产生各个yolov3损失类型的目标,输出每个参数维度都有意义,顺序要保持一致,总的高维顺序为bs*na*h*w*(5+nc),此顺序为darknet 265 | % 官网的顺序一致,非matlab官方一致 266 | % 267 | % author:cuixingxing 268 | % emalil:cuixingxing150@email.com 269 | % 2020.4.25 270 | % 271 | h = currentYOLOV3Layer.numY; 272 | w = currentYOLOV3Layer.numX; 273 | stride = currentYOLOV3Layer.stride; 274 | bs = size(YTrain,1); 275 | 276 | % 把targets转换成nt*[imageIDs,classIDs,gx,gy,gw,gh]二维矩阵 277 | scalex = w/currentYOLOV3Layer.imageSize(2); 278 | scaley = h/currentYOLOV3Layer.imageSize(1); 279 | gwh = currentYOLOV3Layer.anchorsUse/stride; % 此处anchor_grids大小为na*2 280 | targets = cat(1,YTrain{:}); % nt*5大小矩阵,nt为该bach下目标检测框数量 281 | output = cellfun(@(x)size(x,1),YTrain); 282 | imageIDs = repelem((1:bs)',output); 283 | classIDs = targets(:,5); 284 | targets = [imageIDs,classIDs,targets(:,1:end-1)];% nt*6大小,[imageIDs,classIDs,x,y,w,h] 285 | 286 | % 计算目标检测框在特征图上的大小 287 | targets(:,[3,5]) = targets(:,[3,5]).*scalex;% gx,gw 288 | targets(:,[4,6]) = targets(:,[4,6]).*scaley;% nt*6大小,[imageIDs,classIDs,gx,gy,gw,gh] 289 | 290 | % 分别获取每个anchor每个bbox的target 291 | if ~isempty(targets) 292 | iou = getMaxIOUPredictedWithGroundTruth(gwh,targets(:,5:6)); 293 | iouThresh = 0.1; 294 | 295 | reject = true; 296 | if reject 297 | iou(iou2 162 | error('unsupport more than 2 inputs'); 163 | end 164 | if length(connectID)==1 165 | module_idx1 = i-1; 166 | temp = str2double(connectID); 167 | module_idx2 = getModuleIdx(i,temp); 168 | else 169 | temp1 = str2double(connectID(1));temp2 = str2double(connectID(2)); 170 | module_idx1 = getModuleIdx(i,temp1); 171 | module_idx2 = getModuleIdx(i,temp2); 172 | end 173 | if moduleInfoList{module_idx1}.channels~=moduleInfoList{module_idx2}.channels % yolov3-tiny-prn.cfg https://github.com/WongKinYiu/PartialResidualNetworks 174 | add_layer = prnAdditionLayer(2,['prn_add_',num2str(i)]); 175 | moduleInfoList{i}.channels =min(moduleInfoList{module_idx1}.channels,... 176 | moduleInfoList{module_idx2}.channels); 177 | else 178 | add_layer = additionLayer(2,'Name',['add_',num2str(i)]); 179 | moduleInfoList{i}.channels =moduleInfoList{module_idx1}.channels; 180 | end 181 | moduleInfoList{i}.mapSize = moduleInfoList{module_idx1}.mapSize; 182 | 183 | % 添加relu层 184 | if strcmp(currentModuleInfo.activation,'relu') 185 | relu_layer = reluLayer('Name',['relu_',num2str(i)]); 186 | elseif strcmp(currentModuleInfo.activation,'relu6') 187 | relu_layer = clippedReluLayer(6,'Name',['clipRelu_',num2str(i)]); 188 | elseif strcmp(currentModuleInfo.activation,'leaky') 189 | relu_layer = leakyReluLayer('Name',['leaky_',num2str(i)]); 190 | elseif strcmp(currentModuleInfo.activation,'mish') 191 | relu_layer = mishLayer(['mish_',num2str(i)]); 192 | end 193 | moduleLayers = [add_layer;relu_layer]; 194 | lgraph = addLayers(lgraph,moduleLayers); 195 | lgraph = connectLayers(lgraph,... 196 | lastModuleNames{module_idx1},[moduleLayers(1).Name,'/in1']); 197 | lgraph = connectLayers(lgraph,... 198 | lastModuleNames{module_idx2},[moduleLayers(1).Name,'/in2']); 199 | case '[route]' 200 | moduleLayers = [];depth_layer = []; 201 | connectID = strip(split(currentModuleInfo.layers,',')); 202 | numberCon = length(connectID); 203 | if numberCon==1 % 只有一个连接的时候,可能为empty Layer也可能为yolov4-tiny的分组通道layer,在matlab中自定义sliceLayer 204 | temp = str2double(connectID); 205 | module_idx = getModuleIdx(i,temp); 206 | if all(isfield(currentModuleInfo,{'groups','group_id'})) 207 | numGroups = str2double(currentModuleInfo.groups); 208 | groupID = str2double(currentModuleInfo.group_id); 209 | depth_layer = sliceLayer(['slice_',num2str(i)],module_idx-2,numGroups,groupID+1); 210 | moduleInfoList{i}.channels = moduleInfoList{module_idx}.channels/numGroups; 211 | moduleInfoList{i}.mapSize = moduleInfoList{module_idx}.mapSize; 212 | else % 只有一个连接的时候,并且只有'layers'关键字,另一个不是默认上一层,与shortcut层单个值不同,此时为empty Layer 213 | depth_layer = empty2dLayer(['empty_',num2str(i)],module_idx-2); 214 | moduleInfoList{i}.channels = moduleInfoList{module_idx}.channels; 215 | moduleInfoList{i}.mapSize = moduleInfoList{module_idx}.mapSize; 216 | end 217 | else % 此时为depthConcatenation Layer 218 | depth_layer = depthConcatenationLayer(numberCon,'Name',['concat_',num2str(i)]); 219 | module_idx = ones(numberCon,1); 220 | channels_add = zeros(numberCon,1); 221 | for routeii = 1:numberCon % 注意通道连接有顺序要求!不能搞反 222 | temp = str2double(connectID(routeii)); 223 | module_idx(routeii) = getModuleIdx(i,temp); 224 | channels_add(routeii) = moduleInfoList{module_idx(routeii)}.channels; 225 | end 226 | moduleInfoList{i}.channels = sum(channels_add); 227 | moduleInfoList{i}.mapSize = moduleInfoList{module_idx(1)}.mapSize; 228 | end 229 | 230 | moduleLayers = [depth_layer;]; 231 | lgraph = addLayers(lgraph,moduleLayers); 232 | if numberCon == 1 233 | lgraph = connectLayers(lgraph,... 234 | lastModuleNames{module_idx},moduleLayers(1).Name); 235 | else 236 | for routeii = 1:numberCon 237 | lgraph = connectLayers(lgraph,... 238 | lastModuleNames{module_idx(routeii)},[moduleLayers(1).Name,'/in',num2str(routeii)]); 239 | end 240 | end 241 | case '[avgpool]' 242 | moduleLayers = [];avg_layer = []; 243 | poolsize = moduleInfoList{i-1}.mapSize; 244 | pad =0;stride=1; 245 | if isempty(currentModuleInfo) % 为空时候,自动推断大小,即为上一层特征图大小 246 | avg_layer = averagePooling2dLayer(poolsize,'Padding',pad,... 247 | 'Stride',stride,'Name',['avgPool_',num2str(i)]); 248 | else 249 | poolsize = str2double(currentModuleInfo.size); 250 | stride = str2double(currentModuleInfo.stride); 251 | pad = 'same'; % 确保stride为1时候,特征图大小不变 252 | if isfield(currentModuleInfo,'padding') 253 | pad = str2double(currentModuleInfo.padding); 254 | end 255 | avg_layer = averagePooling2dLayer(poolsize,'Padding',pad,... 256 | 'Stride',stride,'Name',['avgPool_',num2str(i)]); 257 | end 258 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 259 | if ischar(pad)&&stride==1 260 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 261 | elseif ischar(pad) 262 | moduleInfoList{i}.mapSize = ceil(moduleInfoList{i-1}.mapSize/stride); 263 | else 264 | moduleInfoList{i}.mapSize = floor((moduleInfoList{i-1}.mapSize-poolsize+2*pad)/stride+1); 265 | end 266 | 267 | moduleLayers= avg_layer; 268 | lgraph = addLayers(lgraph,moduleLayers); 269 | lgraph = connectLayers(lgraph,... 270 | lastModuleNames{i-1},moduleLayers(1).Name); 271 | case '[maxpool]' 272 | moduleLayers = [];maxp_layer = []; 273 | poolsize = moduleInfoList{i-1}.mapSize; 274 | pad =0;stride=1; 275 | if isempty(currentModuleInfo) % 为空时候,自动推断大小,即为上一层特征图大小 276 | maxp_layer = maxPooling2dLayer(poolsize,'Padding',pad,... 277 | 'Stride',stride,'Name',['avgPool_',num2str(i)]); 278 | else 279 | poolsize = str2double(currentModuleInfo.size); 280 | stride = str2double(currentModuleInfo.stride); 281 | pad = 'same'; % 确保stride为1时候,特征图大小不变 282 | if isfield(currentModuleInfo,'padding') 283 | pad = str2double(currentModuleInfo.padding); 284 | end 285 | maxp_layer = maxPooling2dLayer(poolsize,'Padding',pad,... 286 | 'Stride',stride,'Name',['maxPool_',num2str(i)]); 287 | end 288 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 289 | if ischar(pad)&&stride==1 290 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 291 | elseif ischar(pad) 292 | moduleInfoList{i}.mapSize = ceil(moduleInfoList{i-1}.mapSize/stride); 293 | else 294 | moduleInfoList{i}.mapSize = floor((moduleInfoList{i-1}.mapSize-poolsize+2*pad)/stride+1); 295 | end 296 | 297 | moduleLayers= maxp_layer; 298 | lgraph = addLayers(lgraph,moduleLayers); 299 | lgraph = connectLayers(lgraph,... 300 | lastModuleNames{i-1},moduleLayers(1).Name); 301 | case '[dropout]' 302 | moduleLayers = [];drop_layer = []; 303 | probability = str2double(currentModuleInfo.probability); 304 | drop_layer = dropoutLayer(probability,'Name',['drop_',num2str(i)]); 305 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 306 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 307 | 308 | moduleLayers= drop_layer; 309 | lgraph = addLayers(lgraph,moduleLayers); 310 | lgraph = connectLayers(lgraph,... 311 | lastModuleNames{i-1},moduleLayers(1).Name); 312 | case '[connected]' % 与普通卷积最大区别是输入大小是否固定,保证全连接层参数可乘;其后没有BN 313 | moduleLayers = [];connected_layer = [];relu_layer = []; 314 | output = str2double(currentModuleInfo.output); 315 | connected_layer = fullyConnectedLayer(output,'Name',['fullyCon_',num2str(i)]); 316 | moduleInfoList{i}.channels = output; 317 | moduleInfoList{i}.mapSize = [1,1]; 318 | 319 | % 添加relu层 320 | if strcmp(currentModuleInfo.activation,'relu') 321 | relu_layer = reluLayer('Name',['relu_',num2str(i)]); 322 | elseif strcmp(currentModuleInfo.activation,'relu6') 323 | relu_layer = clippedReluLayer(6,'Name',['clipRelu_',num2str(i)]); 324 | elseif strcmp(currentModuleInfo.activation,'leaky') 325 | relu_layer = leakyReluLayer(0.1,'Name',['leaky_',num2str(i)]); 326 | elseif strcmp(currentModuleInfo.activation,'mish') 327 | relu_layer = mishLayer(['mish_',num2str(i)]); 328 | end 329 | 330 | moduleLayers= [connected_layer;relu_layer]; 331 | lgraph = addLayers(lgraph,moduleLayers); 332 | lgraph = connectLayers(lgraph,... 333 | lastModuleNames{i-1},moduleLayers(1).Name); 334 | case '[softmax]' 335 | moduleLayers = [];soft_layer = []; 336 | soft_layer = softmaxLayer('Name',['softmax_',num2str(i)]); 337 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 338 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 339 | 340 | moduleLayers= soft_layer; 341 | lgraph = addLayers(lgraph,moduleLayers); 342 | lgraph = connectLayers(lgraph,... 343 | lastModuleNames{i-1},moduleLayers(1).Name); 344 | case '[cost]' 345 | moduleLayers = [];clss_layer = []; 346 | clss_layer = classificationLayer('Name',['clss_',num2str(i)]); 347 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 348 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 349 | 350 | moduleLayers= clss_layer; 351 | lgraph = addLayers(lgraph,moduleLayers); 352 | lgraph = connectLayers(lgraph,... 353 | lastModuleNames{i-1},moduleLayers(1).Name); 354 | case '[upsample]' % upsample2dLayer 355 | moduleLayers = [];up_layer = []; 356 | stride = str2double(strip(currentModuleInfo.stride));% 整数标量,一般为2 357 | up_layer = upsample2dLayer(['up2d_',num2str(i)],stride); 358 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 359 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize*stride; 360 | 361 | moduleLayers= up_layer; 362 | lgraph = addLayers(lgraph,moduleLayers); 363 | lgraph = connectLayers(lgraph,... 364 | lastModuleNames{i-1},moduleLayers(1).Name); 365 | case '[yolo]' % yolov3Layer 366 | moduleLayers = [];yolov3_layer = []; 367 | allAnchors = reshape(str2double(strip(split(currentModuleInfo.anchors,','))),2,[])';%[width,height],n*2大小 368 | mask = reshape(str2double(strip(split(currentModuleInfo.mask,','))),1,[])+1;% 1*m大小,注意mask是从0开始,要加1 369 | nClasses = str2double(currentModuleInfo.classes); 370 | imageSize = imageInputSize(1:2); % [imageHeight,imageWidth] 371 | yoloIndex = yoloIndex + 1; 372 | yolov3_layer = yolov3Layer(['yolo_v3_id',num2str(yoloIndex)],... 373 | mask,allAnchors,nClasses,yoloIndex,imageSize); 374 | moduleInfoList{i}.channels = moduleInfoList{i-1}.channels; 375 | moduleInfoList{i}.mapSize = moduleInfoList{i-1}.mapSize; 376 | 377 | moduleLayers= yolov3_layer; 378 | lgraph = addLayers(lgraph,moduleLayers); 379 | lgraph = connectLayers(lgraph,... 380 | lastModuleNames{i-1},moduleLayers(1).Name); 381 | otherwise 382 | error("we currently can't support this layer: "+currentModuleType); 383 | end 384 | 385 | if i==1 386 | fprintf('This module No:%2d %-16s,have #params:%-10d,FLops:%-12d,feature map size:(%-3d*%-3d),channels in:%-12s,channels out:%-12d\n',... 387 | i,currentModuleType,numsNetParams-nums_p,FLOPs_perConv,moduleInfoList{i}.mapSize, '-',moduleInfoList{i}.channels); 388 | else 389 | fprintf('This module No:%2d %-16s,have #params:%-10d,FLops:%-12d,feature map size:(%-3d*%-3d),channels in:%-12d,channels out:%-12d\n',... 390 | i,currentModuleType,numsNetParams-nums_p,FLOPs_perConv,moduleInfoList{i}.mapSize,moduleInfoList{i-1}.channels,moduleInfoList{i}.channels); 391 | end 392 | nums_p=numsNetParams; 393 | FLOPs_perConv = 0; 394 | lastModuleNames{i} = moduleLayers(end).Name; 395 | layerToModuleIndex = [layerToModuleIndex;i*ones(length(moduleLayers),1)]; 396 | end 397 | 398 | function matlab_module_idx = getModuleIdx(current_matlab_ind,cfg_value) 399 | % route,或者shortcut层转换为以1为起始索引的标量值 400 | % 输入:current_matlab_ind,1*1的正整数,读入到当前层module的索引标量(current_matlab_ind中是以[net]以1为起始值),darknet是以第一个非[net]开始的module为0开始的计数的索引 401 | % cfg_value,1*1的整数,shortcut层的from值或者route的layers的某一个值 402 | % 输出:module_idx,连接到上一层module的索引值(正整数,以[net]为起始索引1) 403 | % 404 | % cuixingxing150@gmail.com 405 | % 2019.8.19 406 | % 2019.9.4修改索引 407 | if cfg_value<0 408 | matlab_module_idx = current_matlab_ind+cfg_value; 409 | else 410 | matlab_module_idx = 2+cfg_value; 411 | end 412 | end % end of getModuleIdx 413 | 414 | end % end of importDarknetLayers 415 | -------------------------------------------------------------------------------- /cfg/matlabExportYoloV4.cfg: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by MATLAB and may require you to modify it manually 2 | [net] 3 | angle=0 4 | batch=64 5 | burn_in=1000 6 | channels=3 7 | decay=0.0005 8 | exposure=1.5 9 | height=608 10 | hue=.1 11 | learning_rate=0.00261 12 | max_batches=500500 13 | momentum=0.949 14 | mosaic=1 15 | policy=steps 16 | saturation=1.5 17 | scales=.1,.1 18 | steps=400000,450000 19 | subdivisions=8 20 | width=608 21 | 22 | # darknet module ID:0 23 | [convolutional] 24 | batch_normalize=1 25 | filters=32 26 | pad=1 27 | size=3 28 | stride=1 29 | activation=mish 30 | 31 | # darknet module ID:1 32 | [convolutional] 33 | batch_normalize=1 34 | filters=64 35 | pad=1 36 | size=3 37 | stride=2 38 | activation=mish 39 | 40 | # darknet module ID:2 41 | [convolutional] 42 | batch_normalize=1 43 | filters=64 44 | pad=1 45 | size=1 46 | stride=1 47 | activation=mish 48 | 49 | # darknet module ID:3 50 | [route] 51 | layers=1 52 | 53 | # darknet module ID:4 54 | [convolutional] 55 | batch_normalize=1 56 | filters=64 57 | pad=1 58 | size=1 59 | stride=1 60 | activation=mish 61 | 62 | # darknet module ID:5 63 | [convolutional] 64 | batch_normalize=1 65 | filters=32 66 | pad=1 67 | size=1 68 | stride=1 69 | activation=mish 70 | 71 | # darknet module ID:6 72 | [convolutional] 73 | batch_normalize=1 74 | filters=64 75 | pad=1 76 | size=3 77 | stride=1 78 | activation=mish 79 | 80 | # darknet module ID:7 81 | [shortcut] 82 | from=4 83 | activation=linear 84 | 85 | # darknet module ID:8 86 | [convolutional] 87 | batch_normalize=1 88 | filters=64 89 | pad=1 90 | size=1 91 | stride=1 92 | activation=mish 93 | 94 | # darknet module ID:9 95 | [route] 96 | layers=8,2 97 | 98 | # darknet module ID:10 99 | [convolutional] 100 | batch_normalize=1 101 | filters=64 102 | pad=1 103 | size=1 104 | stride=1 105 | activation=mish 106 | 107 | # darknet module ID:11 108 | [convolutional] 109 | batch_normalize=1 110 | filters=128 111 | pad=1 112 | size=3 113 | stride=2 114 | activation=mish 115 | 116 | # darknet module ID:12 117 | [convolutional] 118 | batch_normalize=1 119 | filters=64 120 | pad=1 121 | size=1 122 | stride=1 123 | activation=mish 124 | 125 | # darknet module ID:13 126 | [route] 127 | layers=11 128 | 129 | # darknet module ID:14 130 | [convolutional] 131 | batch_normalize=1 132 | filters=64 133 | pad=1 134 | size=1 135 | stride=1 136 | activation=mish 137 | 138 | # darknet module ID:15 139 | [convolutional] 140 | batch_normalize=1 141 | filters=64 142 | pad=1 143 | size=1 144 | stride=1 145 | activation=mish 146 | 147 | # darknet module ID:16 148 | [convolutional] 149 | batch_normalize=1 150 | filters=64 151 | pad=1 152 | size=3 153 | stride=1 154 | activation=mish 155 | 156 | # darknet module ID:17 157 | [shortcut] 158 | from=14 159 | activation=linear 160 | 161 | # darknet module ID:18 162 | [convolutional] 163 | batch_normalize=1 164 | filters=64 165 | pad=1 166 | size=1 167 | stride=1 168 | activation=mish 169 | 170 | # darknet module ID:19 171 | [convolutional] 172 | batch_normalize=1 173 | filters=64 174 | pad=1 175 | size=3 176 | stride=1 177 | activation=mish 178 | 179 | # darknet module ID:20 180 | [shortcut] 181 | from=17 182 | activation=linear 183 | 184 | # darknet module ID:21 185 | [convolutional] 186 | batch_normalize=1 187 | filters=64 188 | pad=1 189 | size=1 190 | stride=1 191 | activation=mish 192 | 193 | # darknet module ID:22 194 | [route] 195 | layers=21,12 196 | 197 | # darknet module ID:23 198 | [convolutional] 199 | batch_normalize=1 200 | filters=128 201 | pad=1 202 | size=1 203 | stride=1 204 | activation=mish 205 | 206 | # darknet module ID:24 207 | [convolutional] 208 | batch_normalize=1 209 | filters=256 210 | pad=1 211 | size=3 212 | stride=2 213 | activation=mish 214 | 215 | # darknet module ID:25 216 | [convolutional] 217 | batch_normalize=1 218 | filters=128 219 | pad=1 220 | size=1 221 | stride=1 222 | activation=mish 223 | 224 | # darknet module ID:26 225 | [route] 226 | layers=24 227 | 228 | # darknet module ID:27 229 | [convolutional] 230 | batch_normalize=1 231 | filters=128 232 | pad=1 233 | size=1 234 | stride=1 235 | activation=mish 236 | 237 | # darknet module ID:28 238 | [convolutional] 239 | batch_normalize=1 240 | filters=128 241 | pad=1 242 | size=1 243 | stride=1 244 | activation=mish 245 | 246 | # darknet module ID:29 247 | [convolutional] 248 | batch_normalize=1 249 | filters=128 250 | pad=1 251 | size=3 252 | stride=1 253 | activation=mish 254 | 255 | # darknet module ID:30 256 | [shortcut] 257 | from=27 258 | activation=linear 259 | 260 | # darknet module ID:31 261 | [convolutional] 262 | batch_normalize=1 263 | filters=128 264 | pad=1 265 | size=1 266 | stride=1 267 | activation=mish 268 | 269 | # darknet module ID:32 270 | [convolutional] 271 | batch_normalize=1 272 | filters=128 273 | pad=1 274 | size=3 275 | stride=1 276 | activation=mish 277 | 278 | # darknet module ID:33 279 | [shortcut] 280 | from=30 281 | activation=linear 282 | 283 | # darknet module ID:34 284 | [convolutional] 285 | batch_normalize=1 286 | filters=128 287 | pad=1 288 | size=1 289 | stride=1 290 | activation=mish 291 | 292 | # darknet module ID:35 293 | [convolutional] 294 | batch_normalize=1 295 | filters=128 296 | pad=1 297 | size=3 298 | stride=1 299 | activation=mish 300 | 301 | # darknet module ID:36 302 | [shortcut] 303 | from=33 304 | activation=linear 305 | 306 | # darknet module ID:37 307 | [convolutional] 308 | batch_normalize=1 309 | filters=128 310 | pad=1 311 | size=1 312 | stride=1 313 | activation=mish 314 | 315 | # darknet module ID:38 316 | [convolutional] 317 | batch_normalize=1 318 | filters=128 319 | pad=1 320 | size=3 321 | stride=1 322 | activation=mish 323 | 324 | # darknet module ID:39 325 | [shortcut] 326 | from=36 327 | activation=linear 328 | 329 | # darknet module ID:40 330 | [convolutional] 331 | batch_normalize=1 332 | filters=128 333 | pad=1 334 | size=1 335 | stride=1 336 | activation=mish 337 | 338 | # darknet module ID:41 339 | [convolutional] 340 | batch_normalize=1 341 | filters=128 342 | pad=1 343 | size=3 344 | stride=1 345 | activation=mish 346 | 347 | # darknet module ID:42 348 | [shortcut] 349 | from=39 350 | activation=linear 351 | 352 | # darknet module ID:43 353 | [convolutional] 354 | batch_normalize=1 355 | filters=128 356 | pad=1 357 | size=1 358 | stride=1 359 | activation=mish 360 | 361 | # darknet module ID:44 362 | [convolutional] 363 | batch_normalize=1 364 | filters=128 365 | pad=1 366 | size=3 367 | stride=1 368 | activation=mish 369 | 370 | # darknet module ID:45 371 | [shortcut] 372 | from=42 373 | activation=linear 374 | 375 | # darknet module ID:46 376 | [convolutional] 377 | batch_normalize=1 378 | filters=128 379 | pad=1 380 | size=1 381 | stride=1 382 | activation=mish 383 | 384 | # darknet module ID:47 385 | [convolutional] 386 | batch_normalize=1 387 | filters=128 388 | pad=1 389 | size=3 390 | stride=1 391 | activation=mish 392 | 393 | # darknet module ID:48 394 | [shortcut] 395 | from=45 396 | activation=linear 397 | 398 | # darknet module ID:49 399 | [convolutional] 400 | batch_normalize=1 401 | filters=128 402 | pad=1 403 | size=1 404 | stride=1 405 | activation=mish 406 | 407 | # darknet module ID:50 408 | [convolutional] 409 | batch_normalize=1 410 | filters=128 411 | pad=1 412 | size=3 413 | stride=1 414 | activation=mish 415 | 416 | # darknet module ID:51 417 | [shortcut] 418 | from=48 419 | activation=linear 420 | 421 | # darknet module ID:52 422 | [convolutional] 423 | batch_normalize=1 424 | filters=128 425 | pad=1 426 | size=1 427 | stride=1 428 | activation=mish 429 | 430 | # darknet module ID:53 431 | [route] 432 | layers=52,25 433 | 434 | # darknet module ID:54 435 | [convolutional] 436 | batch_normalize=1 437 | filters=256 438 | pad=1 439 | size=1 440 | stride=1 441 | activation=mish 442 | 443 | # darknet module ID:55 444 | [convolutional] 445 | batch_normalize=1 446 | filters=512 447 | pad=1 448 | size=3 449 | stride=2 450 | activation=mish 451 | 452 | # darknet module ID:56 453 | [convolutional] 454 | batch_normalize=1 455 | filters=256 456 | pad=1 457 | size=1 458 | stride=1 459 | activation=mish 460 | 461 | # darknet module ID:57 462 | [route] 463 | layers=55 464 | 465 | # darknet module ID:58 466 | [convolutional] 467 | batch_normalize=1 468 | filters=256 469 | pad=1 470 | size=1 471 | stride=1 472 | activation=mish 473 | 474 | # darknet module ID:59 475 | [convolutional] 476 | batch_normalize=1 477 | filters=256 478 | pad=1 479 | size=1 480 | stride=1 481 | activation=mish 482 | 483 | # darknet module ID:60 484 | [convolutional] 485 | batch_normalize=1 486 | filters=256 487 | pad=1 488 | size=3 489 | stride=1 490 | activation=mish 491 | 492 | # darknet module ID:61 493 | [shortcut] 494 | from=58 495 | activation=linear 496 | 497 | # darknet module ID:62 498 | [convolutional] 499 | batch_normalize=1 500 | filters=256 501 | pad=1 502 | size=1 503 | stride=1 504 | activation=mish 505 | 506 | # darknet module ID:63 507 | [convolutional] 508 | batch_normalize=1 509 | filters=256 510 | pad=1 511 | size=3 512 | stride=1 513 | activation=mish 514 | 515 | # darknet module ID:64 516 | [shortcut] 517 | from=61 518 | activation=linear 519 | 520 | # darknet module ID:65 521 | [convolutional] 522 | batch_normalize=1 523 | filters=256 524 | pad=1 525 | size=1 526 | stride=1 527 | activation=mish 528 | 529 | # darknet module ID:66 530 | [convolutional] 531 | batch_normalize=1 532 | filters=256 533 | pad=1 534 | size=3 535 | stride=1 536 | activation=mish 537 | 538 | # darknet module ID:67 539 | [shortcut] 540 | from=64 541 | activation=linear 542 | 543 | # darknet module ID:68 544 | [convolutional] 545 | batch_normalize=1 546 | filters=256 547 | pad=1 548 | size=1 549 | stride=1 550 | activation=mish 551 | 552 | # darknet module ID:69 553 | [convolutional] 554 | batch_normalize=1 555 | filters=256 556 | pad=1 557 | size=3 558 | stride=1 559 | activation=mish 560 | 561 | # darknet module ID:70 562 | [shortcut] 563 | from=67 564 | activation=linear 565 | 566 | # darknet module ID:71 567 | [convolutional] 568 | batch_normalize=1 569 | filters=256 570 | pad=1 571 | size=1 572 | stride=1 573 | activation=mish 574 | 575 | # darknet module ID:72 576 | [convolutional] 577 | batch_normalize=1 578 | filters=256 579 | pad=1 580 | size=3 581 | stride=1 582 | activation=mish 583 | 584 | # darknet module ID:73 585 | [shortcut] 586 | from=70 587 | activation=linear 588 | 589 | # darknet module ID:74 590 | [convolutional] 591 | batch_normalize=1 592 | filters=256 593 | pad=1 594 | size=1 595 | stride=1 596 | activation=mish 597 | 598 | # darknet module ID:75 599 | [convolutional] 600 | batch_normalize=1 601 | filters=256 602 | pad=1 603 | size=3 604 | stride=1 605 | activation=mish 606 | 607 | # darknet module ID:76 608 | [shortcut] 609 | from=73 610 | activation=linear 611 | 612 | # darknet module ID:77 613 | [convolutional] 614 | batch_normalize=1 615 | filters=256 616 | pad=1 617 | size=1 618 | stride=1 619 | activation=mish 620 | 621 | # darknet module ID:78 622 | [convolutional] 623 | batch_normalize=1 624 | filters=256 625 | pad=1 626 | size=3 627 | stride=1 628 | activation=mish 629 | 630 | # darknet module ID:79 631 | [shortcut] 632 | from=76 633 | activation=linear 634 | 635 | # darknet module ID:80 636 | [convolutional] 637 | batch_normalize=1 638 | filters=256 639 | pad=1 640 | size=1 641 | stride=1 642 | activation=mish 643 | 644 | # darknet module ID:81 645 | [convolutional] 646 | batch_normalize=1 647 | filters=256 648 | pad=1 649 | size=3 650 | stride=1 651 | activation=mish 652 | 653 | # darknet module ID:82 654 | [shortcut] 655 | from=79 656 | activation=linear 657 | 658 | # darknet module ID:83 659 | [convolutional] 660 | batch_normalize=1 661 | filters=256 662 | pad=1 663 | size=1 664 | stride=1 665 | activation=mish 666 | 667 | # darknet module ID:84 668 | [route] 669 | layers=83,56 670 | 671 | # darknet module ID:85 672 | [convolutional] 673 | batch_normalize=1 674 | filters=512 675 | pad=1 676 | size=1 677 | stride=1 678 | activation=mish 679 | 680 | # darknet module ID:86 681 | [convolutional] 682 | batch_normalize=1 683 | filters=1024 684 | pad=1 685 | size=3 686 | stride=2 687 | activation=mish 688 | 689 | # darknet module ID:87 690 | [convolutional] 691 | batch_normalize=1 692 | filters=512 693 | pad=1 694 | size=1 695 | stride=1 696 | activation=mish 697 | 698 | # darknet module ID:88 699 | [route] 700 | layers=86 701 | 702 | # darknet module ID:89 703 | [convolutional] 704 | batch_normalize=1 705 | filters=512 706 | pad=1 707 | size=1 708 | stride=1 709 | activation=mish 710 | 711 | # darknet module ID:90 712 | [convolutional] 713 | batch_normalize=1 714 | filters=512 715 | pad=1 716 | size=1 717 | stride=1 718 | activation=mish 719 | 720 | # darknet module ID:91 721 | [convolutional] 722 | batch_normalize=1 723 | filters=512 724 | pad=1 725 | size=3 726 | stride=1 727 | activation=mish 728 | 729 | # darknet module ID:92 730 | [shortcut] 731 | from=89 732 | activation=linear 733 | 734 | # darknet module ID:93 735 | [convolutional] 736 | batch_normalize=1 737 | filters=512 738 | pad=1 739 | size=1 740 | stride=1 741 | activation=mish 742 | 743 | # darknet module ID:94 744 | [convolutional] 745 | batch_normalize=1 746 | filters=512 747 | pad=1 748 | size=3 749 | stride=1 750 | activation=mish 751 | 752 | # darknet module ID:95 753 | [shortcut] 754 | from=92 755 | activation=linear 756 | 757 | # darknet module ID:96 758 | [convolutional] 759 | batch_normalize=1 760 | filters=512 761 | pad=1 762 | size=1 763 | stride=1 764 | activation=mish 765 | 766 | # darknet module ID:97 767 | [convolutional] 768 | batch_normalize=1 769 | filters=512 770 | pad=1 771 | size=3 772 | stride=1 773 | activation=mish 774 | 775 | # darknet module ID:98 776 | [shortcut] 777 | from=95 778 | activation=linear 779 | 780 | # darknet module ID:99 781 | [convolutional] 782 | batch_normalize=1 783 | filters=512 784 | pad=1 785 | size=1 786 | stride=1 787 | activation=mish 788 | 789 | # darknet module ID:100 790 | [convolutional] 791 | batch_normalize=1 792 | filters=512 793 | pad=1 794 | size=3 795 | stride=1 796 | activation=mish 797 | 798 | # darknet module ID:101 799 | [shortcut] 800 | from=98 801 | activation=linear 802 | 803 | # darknet module ID:102 804 | [convolutional] 805 | batch_normalize=1 806 | filters=512 807 | pad=1 808 | size=1 809 | stride=1 810 | activation=mish 811 | 812 | # darknet module ID:103 813 | [route] 814 | layers=102,87 815 | 816 | # darknet module ID:104 817 | [convolutional] 818 | batch_normalize=1 819 | filters=1024 820 | pad=1 821 | size=1 822 | stride=1 823 | activation=mish 824 | 825 | # darknet module ID:105 826 | [convolutional] 827 | batch_normalize=1 828 | filters=512 829 | pad=1 830 | size=1 831 | stride=1 832 | activation=leaky 833 | 834 | # darknet module ID:106 835 | [convolutional] 836 | batch_normalize=1 837 | filters=1024 838 | pad=1 839 | size=3 840 | stride=1 841 | activation=leaky 842 | 843 | # darknet module ID:107 844 | [convolutional] 845 | batch_normalize=1 846 | filters=512 847 | pad=1 848 | size=1 849 | stride=1 850 | activation=leaky 851 | 852 | # darknet module ID:108 853 | [maxpool] 854 | size=5 855 | stride=1 856 | 857 | # darknet module ID:109 858 | [route] 859 | layers=107 860 | 861 | # darknet module ID:110 862 | [maxpool] 863 | size=9 864 | stride=1 865 | 866 | # darknet module ID:111 867 | [route] 868 | layers=107 869 | 870 | # darknet module ID:112 871 | [maxpool] 872 | size=13 873 | stride=1 874 | 875 | # darknet module ID:113 876 | [route] 877 | layers=112,110,108,107 878 | 879 | # darknet module ID:114 880 | [convolutional] 881 | batch_normalize=1 882 | filters=512 883 | pad=1 884 | size=1 885 | stride=1 886 | activation=leaky 887 | 888 | # darknet module ID:115 889 | [convolutional] 890 | batch_normalize=1 891 | filters=1024 892 | pad=1 893 | size=3 894 | stride=1 895 | activation=leaky 896 | 897 | # darknet module ID:116 898 | [convolutional] 899 | batch_normalize=1 900 | filters=512 901 | pad=1 902 | size=1 903 | stride=1 904 | activation=leaky 905 | 906 | # darknet module ID:117 907 | [convolutional] 908 | batch_normalize=1 909 | filters=256 910 | pad=1 911 | size=1 912 | stride=1 913 | activation=leaky 914 | 915 | # darknet module ID:118 916 | [upsample] 917 | stride=2 918 | 919 | # darknet module ID:119 920 | [route] 921 | layers=85 922 | 923 | # darknet module ID:120 924 | [convolutional] 925 | batch_normalize=1 926 | filters=256 927 | pad=1 928 | size=1 929 | stride=1 930 | activation=leaky 931 | 932 | # darknet module ID:121 933 | [route] 934 | layers=120,118 935 | 936 | # darknet module ID:122 937 | [convolutional] 938 | batch_normalize=1 939 | filters=256 940 | pad=1 941 | size=1 942 | stride=1 943 | activation=leaky 944 | 945 | # darknet module ID:123 946 | [convolutional] 947 | batch_normalize=1 948 | filters=512 949 | pad=1 950 | size=3 951 | stride=1 952 | activation=leaky 953 | 954 | # darknet module ID:124 955 | [convolutional] 956 | batch_normalize=1 957 | filters=256 958 | pad=1 959 | size=1 960 | stride=1 961 | activation=leaky 962 | 963 | # darknet module ID:125 964 | [convolutional] 965 | batch_normalize=1 966 | filters=512 967 | pad=1 968 | size=3 969 | stride=1 970 | activation=leaky 971 | 972 | # darknet module ID:126 973 | [convolutional] 974 | batch_normalize=1 975 | filters=256 976 | pad=1 977 | size=1 978 | stride=1 979 | activation=leaky 980 | 981 | # darknet module ID:127 982 | [convolutional] 983 | batch_normalize=1 984 | filters=128 985 | pad=1 986 | size=1 987 | stride=1 988 | activation=leaky 989 | 990 | # darknet module ID:128 991 | [upsample] 992 | stride=2 993 | 994 | # darknet module ID:129 995 | [route] 996 | layers=54 997 | 998 | # darknet module ID:130 999 | [convolutional] 1000 | batch_normalize=1 1001 | filters=128 1002 | pad=1 1003 | size=1 1004 | stride=1 1005 | activation=leaky 1006 | 1007 | # darknet module ID:131 1008 | [route] 1009 | layers=130,128 1010 | 1011 | # darknet module ID:132 1012 | [convolutional] 1013 | batch_normalize=1 1014 | filters=128 1015 | pad=1 1016 | size=1 1017 | stride=1 1018 | activation=leaky 1019 | 1020 | # darknet module ID:133 1021 | [convolutional] 1022 | batch_normalize=1 1023 | filters=256 1024 | pad=1 1025 | size=3 1026 | stride=1 1027 | activation=leaky 1028 | 1029 | # darknet module ID:134 1030 | [convolutional] 1031 | batch_normalize=1 1032 | filters=128 1033 | pad=1 1034 | size=1 1035 | stride=1 1036 | activation=leaky 1037 | 1038 | # darknet module ID:135 1039 | [convolutional] 1040 | batch_normalize=1 1041 | filters=256 1042 | pad=1 1043 | size=3 1044 | stride=1 1045 | activation=leaky 1046 | 1047 | # darknet module ID:136 1048 | [convolutional] 1049 | batch_normalize=1 1050 | filters=128 1051 | pad=1 1052 | size=1 1053 | stride=1 1054 | activation=leaky 1055 | 1056 | # darknet module ID:137 1057 | [convolutional] 1058 | batch_normalize=1 1059 | filters=256 1060 | pad=1 1061 | size=3 1062 | stride=1 1063 | activation=leaky 1064 | 1065 | # darknet module ID:138 1066 | [convolutional] 1067 | filters=255 1068 | pad=1 1069 | size=1 1070 | stride=1 1071 | activation=linear 1072 | 1073 | # darknet module ID:139 1074 | [yolo] 1075 | anchors=12,16,19,36,40,28,36,75,76,55,72,146,142,110,192,243,459,401 1076 | classes=80 1077 | ignore_thresh=0.7 1078 | jitter=0.3 1079 | mask=0,1,2 1080 | num=9 1081 | random=1 1082 | truth_thresh=1 1083 | 1084 | # darknet module ID:140 1085 | [route] 1086 | layers=136 1087 | 1088 | # darknet module ID:141 1089 | [convolutional] 1090 | batch_normalize=1 1091 | filters=256 1092 | pad=1 1093 | size=3 1094 | stride=2 1095 | activation=leaky 1096 | 1097 | # darknet module ID:142 1098 | [route] 1099 | layers=141,126 1100 | 1101 | # darknet module ID:143 1102 | [convolutional] 1103 | batch_normalize=1 1104 | filters=256 1105 | pad=1 1106 | size=1 1107 | stride=1 1108 | activation=leaky 1109 | 1110 | # darknet module ID:144 1111 | [convolutional] 1112 | batch_normalize=1 1113 | filters=512 1114 | pad=1 1115 | size=3 1116 | stride=1 1117 | activation=leaky 1118 | 1119 | # darknet module ID:145 1120 | [convolutional] 1121 | batch_normalize=1 1122 | filters=256 1123 | pad=1 1124 | size=1 1125 | stride=1 1126 | activation=leaky 1127 | 1128 | # darknet module ID:146 1129 | [convolutional] 1130 | batch_normalize=1 1131 | filters=512 1132 | pad=1 1133 | size=3 1134 | stride=1 1135 | activation=leaky 1136 | 1137 | # darknet module ID:147 1138 | [convolutional] 1139 | batch_normalize=1 1140 | filters=256 1141 | pad=1 1142 | size=1 1143 | stride=1 1144 | activation=leaky 1145 | 1146 | # darknet module ID:148 1147 | [convolutional] 1148 | batch_normalize=1 1149 | filters=512 1150 | pad=1 1151 | size=3 1152 | stride=1 1153 | activation=leaky 1154 | 1155 | # darknet module ID:149 1156 | [convolutional] 1157 | filters=255 1158 | pad=1 1159 | size=1 1160 | stride=1 1161 | activation=linear 1162 | 1163 | # darknet module ID:150 1164 | [yolo] 1165 | anchors=12,16,19,36,40,28,36,75,76,55,72,146,142,110,192,243,459,401 1166 | classes=80 1167 | ignore_thresh=0.7 1168 | jitter=0.3 1169 | mask=3,4,5 1170 | num=9 1171 | random=1 1172 | truth_thresh=1 1173 | 1174 | # darknet module ID:151 1175 | [route] 1176 | layers=147 1177 | 1178 | # darknet module ID:152 1179 | [convolutional] 1180 | batch_normalize=1 1181 | filters=512 1182 | pad=1 1183 | size=3 1184 | stride=2 1185 | activation=leaky 1186 | 1187 | # darknet module ID:153 1188 | [route] 1189 | layers=152,116 1190 | 1191 | # darknet module ID:154 1192 | [convolutional] 1193 | batch_normalize=1 1194 | filters=512 1195 | pad=1 1196 | size=1 1197 | stride=1 1198 | activation=leaky 1199 | 1200 | # darknet module ID:155 1201 | [convolutional] 1202 | batch_normalize=1 1203 | filters=1024 1204 | pad=1 1205 | size=3 1206 | stride=1 1207 | activation=leaky 1208 | 1209 | # darknet module ID:156 1210 | [convolutional] 1211 | batch_normalize=1 1212 | filters=512 1213 | pad=1 1214 | size=1 1215 | stride=1 1216 | activation=leaky 1217 | 1218 | # darknet module ID:157 1219 | [convolutional] 1220 | batch_normalize=1 1221 | filters=1024 1222 | pad=1 1223 | size=3 1224 | stride=1 1225 | activation=leaky 1226 | 1227 | # darknet module ID:158 1228 | [convolutional] 1229 | batch_normalize=1 1230 | filters=512 1231 | pad=1 1232 | size=1 1233 | stride=1 1234 | activation=leaky 1235 | 1236 | # darknet module ID:159 1237 | [convolutional] 1238 | batch_normalize=1 1239 | filters=1024 1240 | pad=1 1241 | size=3 1242 | stride=1 1243 | activation=leaky 1244 | 1245 | # darknet module ID:160 1246 | [convolutional] 1247 | filters=255 1248 | pad=1 1249 | size=1 1250 | stride=1 1251 | activation=linear 1252 | 1253 | # darknet module ID:161 1254 | [yolo] 1255 | anchors=12,16,19,36,40,28,36,75,76,55,72,146,142,110,192,243,459,401 1256 | classes=80 1257 | ignore_thresh=0.7 1258 | jitter=0.3 1259 | mask=6,7,8 1260 | num=9 1261 | random=1 1262 | truth_thresh=1 1263 | 1264 | -------------------------------------------------------------------------------- /utils/synset_words.txt: -------------------------------------------------------------------------------- 1 | n01440764 tench, Tinca tinca 2 | n01443537 goldfish, Carassius auratus 3 | n01484850 great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias 4 | n01491361 tiger shark, Galeocerdo cuvieri 5 | n01494475 hammerhead, hammerhead shark 6 | n01496331 electric ray, crampfish, numbfish, torpedo 7 | n01498041 stingray 8 | n01514668 cock 9 | n01514859 hen 10 | n01518878 ostrich, Struthio camelus 11 | n01530575 brambling, Fringilla montifringilla 12 | n01531178 goldfinch, Carduelis carduelis 13 | n01532829 house finch, linnet, Carpodacus mexicanus 14 | n01534433 junco, snowbird 15 | n01537544 indigo bunting, indigo finch, indigo bird, Passerina cyanea 16 | n01558993 robin, American robin, Turdus migratorius 17 | n01560419 bulbul 18 | n01580077 jay 19 | n01582220 magpie 20 | n01592084 chickadee 21 | n01601694 water ouzel, dipper 22 | n01608432 kite 23 | n01614925 bald eagle, American eagle, Haliaeetus leucocephalus 24 | n01616318 vulture 25 | n01622779 great grey owl, great gray owl, Strix nebulosa 26 | n01629819 European fire salamander, Salamandra salamandra 27 | n01630670 common newt, Triturus vulgaris 28 | n01631663 eft 29 | n01632458 spotted salamander, Ambystoma maculatum 30 | n01632777 axolotl, mud puppy, Ambystoma mexicanum 31 | n01641577 bullfrog, Rana catesbeiana 32 | n01644373 tree frog, tree-frog 33 | n01644900 tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui 34 | n01664065 loggerhead, loggerhead turtle, Caretta caretta 35 | n01665541 leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea 36 | n01667114 mud turtle 37 | n01667778 terrapin 38 | n01669191 box turtle, box tortoise 39 | n01675722 banded gecko 40 | n01677366 common iguana, iguana, Iguana iguana 41 | n01682714 American chameleon, anole, Anolis carolinensis 42 | n01685808 whiptail, whiptail lizard 43 | n01687978 agama 44 | n01688243 frilled lizard, Chlamydosaurus kingi 45 | n01689811 alligator lizard 46 | n01692333 Gila monster, Heloderma suspectum 47 | n01693334 green lizard, Lacerta viridis 48 | n01694178 African chameleon, Chamaeleo chamaeleon 49 | n01695060 Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis 50 | n01697457 African crocodile, Nile crocodile, Crocodylus niloticus 51 | n01698640 American alligator, Alligator mississipiensis 52 | n01704323 triceratops 53 | n01728572 thunder snake, worm snake, Carphophis amoenus 54 | n01728920 ringneck snake, ring-necked snake, ring snake 55 | n01729322 hognose snake, puff adder, sand viper 56 | n01729977 green snake, grass snake 57 | n01734418 king snake, kingsnake 58 | n01735189 garter snake, grass snake 59 | n01737021 water snake 60 | n01739381 vine snake 61 | n01740131 night snake, Hypsiglena torquata 62 | n01742172 boa constrictor, Constrictor constrictor 63 | n01744401 rock python, rock snake, Python sebae 64 | n01748264 Indian cobra, Naja naja 65 | n01749939 green mamba 66 | n01751748 sea snake 67 | n01753488 horned viper, cerastes, sand viper, horned asp, Cerastes cornutus 68 | n01755581 diamondback, diamondback rattlesnake, Crotalus adamanteus 69 | n01756291 sidewinder, horned rattlesnake, Crotalus cerastes 70 | n01768244 trilobite 71 | n01770081 harvestman, daddy longlegs, Phalangium opilio 72 | n01770393 scorpion 73 | n01773157 black and gold garden spider, Argiope aurantia 74 | n01773549 barn spider, Araneus cavaticus 75 | n01773797 garden spider, Aranea diademata 76 | n01774384 black widow, Latrodectus mactans 77 | n01774750 tarantula 78 | n01775062 wolf spider, hunting spider 79 | n01776313 tick 80 | n01784675 centipede 81 | n01795545 black grouse 82 | n01796340 ptarmigan 83 | n01797886 ruffed grouse, partridge, Bonasa umbellus 84 | n01798484 prairie chicken, prairie grouse, prairie fowl 85 | n01806143 peacock 86 | n01806567 quail 87 | n01807496 partridge 88 | n01817953 African grey, African gray, Psittacus erithacus 89 | n01818515 macaw 90 | n01819313 sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita 91 | n01820546 lorikeet 92 | n01824575 coucal 93 | n01828970 bee eater 94 | n01829413 hornbill 95 | n01833805 hummingbird 96 | n01843065 jacamar 97 | n01843383 toucan 98 | n01847000 drake 99 | n01855032 red-breasted merganser, Mergus serrator 100 | n01855672 goose 101 | n01860187 black swan, Cygnus atratus 102 | n01871265 tusker 103 | n01872401 echidna, spiny anteater, anteater 104 | n01873310 platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus 105 | n01877812 wallaby, brush kangaroo 106 | n01882714 koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus 107 | n01883070 wombat 108 | n01910747 jellyfish 109 | n01914609 sea anemone, anemone 110 | n01917289 brain coral 111 | n01924916 flatworm, platyhelminth 112 | n01930112 nematode, nematode worm, roundworm 113 | n01943899 conch 114 | n01944390 snail 115 | n01945685 slug 116 | n01950731 sea slug, nudibranch 117 | n01955084 chiton, coat-of-mail shell, sea cradle, polyplacophore 118 | n01968897 chambered nautilus, pearly nautilus, nautilus 119 | n01978287 Dungeness crab, Cancer magister 120 | n01978455 rock crab, Cancer irroratus 121 | n01980166 fiddler crab 122 | n01981276 king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica 123 | n01983481 American lobster, Northern lobster, Maine lobster, Homarus americanus 124 | n01984695 spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish 125 | n01985128 crayfish, crawfish, crawdad, crawdaddy 126 | n01986214 hermit crab 127 | n01990800 isopod 128 | n02002556 white stork, Ciconia ciconia 129 | n02002724 black stork, Ciconia nigra 130 | n02006656 spoonbill 131 | n02007558 flamingo 132 | n02009229 little blue heron, Egretta caerulea 133 | n02009912 American egret, great white heron, Egretta albus 134 | n02011460 bittern 135 | n02012849 crane 136 | n02013706 limpkin, Aramus pictus 137 | n02017213 European gallinule, Porphyrio porphyrio 138 | n02018207 American coot, marsh hen, mud hen, water hen, Fulica americana 139 | n02018795 bustard 140 | n02025239 ruddy turnstone, Arenaria interpres 141 | n02027492 red-backed sandpiper, dunlin, Erolia alpina 142 | n02028035 redshank, Tringa totanus 143 | n02033041 dowitcher 144 | n02037110 oystercatcher, oyster catcher 145 | n02051845 pelican 146 | n02056570 king penguin, Aptenodytes patagonica 147 | n02058221 albatross, mollymawk 148 | n02066245 grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus 149 | n02071294 killer whale, killer, orca, grampus, sea wolf, Orcinus orca 150 | n02074367 dugong, Dugong dugon 151 | n02077923 sea lion 152 | n02085620 Chihuahua 153 | n02085782 Japanese spaniel 154 | n02085936 Maltese dog, Maltese terrier, Maltese 155 | n02086079 Pekinese, Pekingese, Peke 156 | n02086240 Shih-Tzu 157 | n02086646 Blenheim spaniel 158 | n02086910 papillon 159 | n02087046 toy terrier 160 | n02087394 Rhodesian ridgeback 161 | n02088094 Afghan hound, Afghan 162 | n02088238 basset, basset hound 163 | n02088364 beagle 164 | n02088466 bloodhound, sleuthhound 165 | n02088632 bluetick 166 | n02089078 black-and-tan coonhound 167 | n02089867 Walker hound, Walker foxhound 168 | n02089973 English foxhound 169 | n02090379 redbone 170 | n02090622 borzoi, Russian wolfhound 171 | n02090721 Irish wolfhound 172 | n02091032 Italian greyhound 173 | n02091134 whippet 174 | n02091244 Ibizan hound, Ibizan Podenco 175 | n02091467 Norwegian elkhound, elkhound 176 | n02091635 otterhound, otter hound 177 | n02091831 Saluki, gazelle hound 178 | n02092002 Scottish deerhound, deerhound 179 | n02092339 Weimaraner 180 | n02093256 Staffordshire bullterrier, Staffordshire bull terrier 181 | n02093428 American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier 182 | n02093647 Bedlington terrier 183 | n02093754 Border terrier 184 | n02093859 Kerry blue terrier 185 | n02093991 Irish terrier 186 | n02094114 Norfolk terrier 187 | n02094258 Norwich terrier 188 | n02094433 Yorkshire terrier 189 | n02095314 wire-haired fox terrier 190 | n02095570 Lakeland terrier 191 | n02095889 Sealyham terrier, Sealyham 192 | n02096051 Airedale, Airedale terrier 193 | n02096177 cairn, cairn terrier 194 | n02096294 Australian terrier 195 | n02096437 Dandie Dinmont, Dandie Dinmont terrier 196 | n02096585 Boston bull, Boston terrier 197 | n02097047 miniature schnauzer 198 | n02097130 giant schnauzer 199 | n02097209 standard schnauzer 200 | n02097298 Scotch terrier, Scottish terrier, Scottie 201 | n02097474 Tibetan terrier, chrysanthemum dog 202 | n02097658 silky terrier, Sydney silky 203 | n02098105 soft-coated wheaten terrier 204 | n02098286 West Highland white terrier 205 | n02098413 Lhasa, Lhasa apso 206 | n02099267 flat-coated retriever 207 | n02099429 curly-coated retriever 208 | n02099601 golden retriever 209 | n02099712 Labrador retriever 210 | n02099849 Chesapeake Bay retriever 211 | n02100236 German short-haired pointer 212 | n02100583 vizsla, Hungarian pointer 213 | n02100735 English setter 214 | n02100877 Irish setter, red setter 215 | n02101006 Gordon setter 216 | n02101388 Brittany spaniel 217 | n02101556 clumber, clumber spaniel 218 | n02102040 English springer, English springer spaniel 219 | n02102177 Welsh springer spaniel 220 | n02102318 cocker spaniel, English cocker spaniel, cocker 221 | n02102480 Sussex spaniel 222 | n02102973 Irish water spaniel 223 | n02104029 kuvasz 224 | n02104365 schipperke 225 | n02105056 groenendael 226 | n02105162 malinois 227 | n02105251 briard 228 | n02105412 kelpie 229 | n02105505 komondor 230 | n02105641 Old English sheepdog, bobtail 231 | n02105855 Shetland sheepdog, Shetland sheep dog, Shetland 232 | n02106030 collie 233 | n02106166 Border collie 234 | n02106382 Bouvier des Flandres, Bouviers des Flandres 235 | n02106550 Rottweiler 236 | n02106662 German shepherd, German shepherd dog, German police dog, alsatian 237 | n02107142 Doberman, Doberman pinscher 238 | n02107312 miniature pinscher 239 | n02107574 Greater Swiss Mountain dog 240 | n02107683 Bernese mountain dog 241 | n02107908 Appenzeller 242 | n02108000 EntleBucher 243 | n02108089 boxer 244 | n02108422 bull mastiff 245 | n02108551 Tibetan mastiff 246 | n02108915 French bulldog 247 | n02109047 Great Dane 248 | n02109525 Saint Bernard, St Bernard 249 | n02109961 Eskimo dog, husky 250 | n02110063 malamute, malemute, Alaskan malamute 251 | n02110185 Siberian husky 252 | n02110341 dalmatian, coach dog, carriage dog 253 | n02110627 affenpinscher, monkey pinscher, monkey dog 254 | n02110806 basenji 255 | n02110958 pug, pug-dog 256 | n02111129 Leonberg 257 | n02111277 Newfoundland, Newfoundland dog 258 | n02111500 Great Pyrenees 259 | n02111889 Samoyed, Samoyede 260 | n02112018 Pomeranian 261 | n02112137 chow, chow chow 262 | n02112350 keeshond 263 | n02112706 Brabancon griffon 264 | n02113023 Pembroke, Pembroke Welsh corgi 265 | n02113186 Cardigan, Cardigan Welsh corgi 266 | n02113624 toy poodle 267 | n02113712 miniature poodle 268 | n02113799 standard poodle 269 | n02113978 Mexican hairless 270 | n02114367 timber wolf, grey wolf, gray wolf, Canis lupus 271 | n02114548 white wolf, Arctic wolf, Canis lupus tundrarum 272 | n02114712 red wolf, maned wolf, Canis rufus, Canis niger 273 | n02114855 coyote, prairie wolf, brush wolf, Canis latrans 274 | n02115641 dingo, warrigal, warragal, Canis dingo 275 | n02115913 dhole, Cuon alpinus 276 | n02116738 African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus 277 | n02117135 hyena, hyaena 278 | n02119022 red fox, Vulpes vulpes 279 | n02119789 kit fox, Vulpes macrotis 280 | n02120079 Arctic fox, white fox, Alopex lagopus 281 | n02120505 grey fox, gray fox, Urocyon cinereoargenteus 282 | n02123045 tabby, tabby cat 283 | n02123159 tiger cat 284 | n02123394 Persian cat 285 | n02123597 Siamese cat, Siamese 286 | n02124075 Egyptian cat 287 | n02125311 cougar, puma, catamount, mountain lion, painter, panther, Felis concolor 288 | n02127052 lynx, catamount 289 | n02128385 leopard, Panthera pardus 290 | n02128757 snow leopard, ounce, Panthera uncia 291 | n02128925 jaguar, panther, Panthera onca, Felis onca 292 | n02129165 lion, king of beasts, Panthera leo 293 | n02129604 tiger, Panthera tigris 294 | n02130308 cheetah, chetah, Acinonyx jubatus 295 | n02132136 brown bear, bruin, Ursus arctos 296 | n02133161 American black bear, black bear, Ursus americanus, Euarctos americanus 297 | n02134084 ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus 298 | n02134418 sloth bear, Melursus ursinus, Ursus ursinus 299 | n02137549 mongoose 300 | n02138441 meerkat, mierkat 301 | n02165105 tiger beetle 302 | n02165456 ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle 303 | n02167151 ground beetle, carabid beetle 304 | n02168699 long-horned beetle, longicorn, longicorn beetle 305 | n02169497 leaf beetle, chrysomelid 306 | n02172182 dung beetle 307 | n02174001 rhinoceros beetle 308 | n02177972 weevil 309 | n02190166 fly 310 | n02206856 bee 311 | n02219486 ant, emmet, pismire 312 | n02226429 grasshopper, hopper 313 | n02229544 cricket 314 | n02231487 walking stick, walkingstick, stick insect 315 | n02233338 cockroach, roach 316 | n02236044 mantis, mantid 317 | n02256656 cicada, cicala 318 | n02259212 leafhopper 319 | n02264363 lacewing, lacewing fly 320 | n02268443 dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk 321 | n02268853 damselfly 322 | n02276258 admiral 323 | n02277742 ringlet, ringlet butterfly 324 | n02279972 monarch, monarch butterfly, milkweed butterfly, Danaus plexippus 325 | n02280649 cabbage butterfly 326 | n02281406 sulphur butterfly, sulfur butterfly 327 | n02281787 lycaenid, lycaenid butterfly 328 | n02317335 starfish, sea star 329 | n02319095 sea urchin 330 | n02321529 sea cucumber, holothurian 331 | n02325366 wood rabbit, cottontail, cottontail rabbit 332 | n02326432 hare 333 | n02328150 Angora, Angora rabbit 334 | n02342885 hamster 335 | n02346627 porcupine, hedgehog 336 | n02356798 fox squirrel, eastern fox squirrel, Sciurus niger 337 | n02361337 marmot 338 | n02363005 beaver 339 | n02364673 guinea pig, Cavia cobaya 340 | n02389026 sorrel 341 | n02391049 zebra 342 | n02395406 hog, pig, grunter, squealer, Sus scrofa 343 | n02396427 wild boar, boar, Sus scrofa 344 | n02397096 warthog 345 | n02398521 hippopotamus, hippo, river horse, Hippopotamus amphibius 346 | n02403003 ox 347 | n02408429 water buffalo, water ox, Asiatic buffalo, Bubalus bubalis 348 | n02410509 bison 349 | n02412080 ram, tup 350 | n02415577 bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis 351 | n02417914 ibex, Capra ibex 352 | n02422106 hartebeest 353 | n02422699 impala, Aepyceros melampus 354 | n02423022 gazelle 355 | n02437312 Arabian camel, dromedary, Camelus dromedarius 356 | n02437616 llama 357 | n02441942 weasel 358 | n02442845 mink 359 | n02443114 polecat, fitch, foulmart, foumart, Mustela putorius 360 | n02443484 black-footed ferret, ferret, Mustela nigripes 361 | n02444819 otter 362 | n02445715 skunk, polecat, wood pussy 363 | n02447366 badger 364 | n02454379 armadillo 365 | n02457408 three-toed sloth, ai, Bradypus tridactylus 366 | n02480495 orangutan, orang, orangutang, Pongo pygmaeus 367 | n02480855 gorilla, Gorilla gorilla 368 | n02481823 chimpanzee, chimp, Pan troglodytes 369 | n02483362 gibbon, Hylobates lar 370 | n02483708 siamang, Hylobates syndactylus, Symphalangus syndactylus 371 | n02484975 guenon, guenon monkey 372 | n02486261 patas, hussar monkey, Erythrocebus patas 373 | n02486410 baboon 374 | n02487347 macaque 375 | n02488291 langur 376 | n02488702 colobus, colobus monkey 377 | n02489166 proboscis monkey, Nasalis larvatus 378 | n02490219 marmoset 379 | n02492035 capuchin, ringtail, Cebus capucinus 380 | n02492660 howler monkey, howler 381 | n02493509 titi, titi monkey 382 | n02493793 spider monkey, Ateles geoffroyi 383 | n02494079 squirrel monkey, Saimiri sciureus 384 | n02497673 Madagascar cat, ring-tailed lemur, Lemur catta 385 | n02500267 indri, indris, Indri indri, Indri brevicaudatus 386 | n02504013 Indian elephant, Elephas maximus 387 | n02504458 African elephant, Loxodonta africana 388 | n02509815 lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens 389 | n02510455 giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca 390 | n02514041 barracouta, snoek 391 | n02526121 eel 392 | n02536864 coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch 393 | n02606052 rock beauty, Holocanthus tricolor 394 | n02607072 anemone fish 395 | n02640242 sturgeon 396 | n02641379 gar, garfish, garpike, billfish, Lepisosteus osseus 397 | n02643566 lionfish 398 | n02655020 puffer, pufferfish, blowfish, globefish 399 | n02666196 abacus 400 | n02667093 abaya 401 | n02669723 academic gown, academic robe, judge's robe 402 | n02672831 accordion, piano accordion, squeeze box 403 | n02676566 acoustic guitar 404 | n02687172 aircraft carrier, carrier, flattop, attack aircraft carrier 405 | n02690373 airliner 406 | n02692877 airship, dirigible 407 | n02699494 altar 408 | n02701002 ambulance 409 | n02704792 amphibian, amphibious vehicle 410 | n02708093 analog clock 411 | n02727426 apiary, bee house 412 | n02730930 apron 413 | n02747177 ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin 414 | n02749479 assault rifle, assault gun 415 | n02769748 backpack, back pack, knapsack, packsack, rucksack, haversack 416 | n02776631 bakery, bakeshop, bakehouse 417 | n02777292 balance beam, beam 418 | n02782093 balloon 419 | n02783161 ballpoint, ballpoint pen, ballpen, Biro 420 | n02786058 Band Aid 421 | n02787622 banjo 422 | n02788148 bannister, banister, balustrade, balusters, handrail 423 | n02790996 barbell 424 | n02791124 barber chair 425 | n02791270 barbershop 426 | n02793495 barn 427 | n02794156 barometer 428 | n02795169 barrel, cask 429 | n02797295 barrow, garden cart, lawn cart, wheelbarrow 430 | n02799071 baseball 431 | n02802426 basketball 432 | n02804414 bassinet 433 | n02804610 bassoon 434 | n02807133 bathing cap, swimming cap 435 | n02808304 bath towel 436 | n02808440 bathtub, bathing tub, bath, tub 437 | n02814533 beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon 438 | n02814860 beacon, lighthouse, beacon light, pharos 439 | n02815834 beaker 440 | n02817516 bearskin, busby, shako 441 | n02823428 beer bottle 442 | n02823750 beer glass 443 | n02825657 bell cote, bell cot 444 | n02834397 bib 445 | n02835271 bicycle-built-for-two, tandem bicycle, tandem 446 | n02837789 bikini, two-piece 447 | n02840245 binder, ring-binder 448 | n02841315 binoculars, field glasses, opera glasses 449 | n02843684 birdhouse 450 | n02859443 boathouse 451 | n02860847 bobsled, bobsleigh, bob 452 | n02865351 bolo tie, bolo, bola tie, bola 453 | n02869837 bonnet, poke bonnet 454 | n02870880 bookcase 455 | n02871525 bookshop, bookstore, bookstall 456 | n02877765 bottlecap 457 | n02879718 bow 458 | n02883205 bow tie, bow-tie, bowtie 459 | n02892201 brass, memorial tablet, plaque 460 | n02892767 brassiere, bra, bandeau 461 | n02894605 breakwater, groin, groyne, mole, bulwark, seawall, jetty 462 | n02895154 breastplate, aegis, egis 463 | n02906734 broom 464 | n02909870 bucket, pail 465 | n02910353 buckle 466 | n02916936 bulletproof vest 467 | n02917067 bullet train, bullet 468 | n02927161 butcher shop, meat market 469 | n02930766 cab, hack, taxi, taxicab 470 | n02939185 caldron, cauldron 471 | n02948072 candle, taper, wax light 472 | n02950826 cannon 473 | n02951358 canoe 474 | n02951585 can opener, tin opener 475 | n02963159 cardigan 476 | n02965783 car mirror 477 | n02966193 carousel, carrousel, merry-go-round, roundabout, whirligig 478 | n02966687 carpenter's kit, tool kit 479 | n02971356 carton 480 | n02974003 car wheel 481 | n02977058 cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM 482 | n02978881 cassette 483 | n02979186 cassette player 484 | n02980441 castle 485 | n02981792 catamaran 486 | n02988304 CD player 487 | n02992211 cello, violoncello 488 | n02992529 cellular telephone, cellular phone, cellphone, cell, mobile phone 489 | n02999410 chain 490 | n03000134 chainlink fence 491 | n03000247 chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour 492 | n03000684 chain saw, chainsaw 493 | n03014705 chest 494 | n03016953 chiffonier, commode 495 | n03017168 chime, bell, gong 496 | n03018349 china cabinet, china closet 497 | n03026506 Christmas stocking 498 | n03028079 church, church building 499 | n03032252 cinema, movie theater, movie theatre, movie house, picture palace 500 | n03041632 cleaver, meat cleaver, chopper 501 | n03042490 cliff dwelling 502 | n03045698 cloak 503 | n03047690 clog, geta, patten, sabot 504 | n03062245 cocktail shaker 505 | n03063599 coffee mug 506 | n03063689 coffeepot 507 | n03065424 coil, spiral, volute, whorl, helix 508 | n03075370 combination lock 509 | n03085013 computer keyboard, keypad 510 | n03089624 confectionery, confectionary, candy store 511 | n03095699 container ship, containership, container vessel 512 | n03100240 convertible 513 | n03109150 corkscrew, bottle screw 514 | n03110669 cornet, horn, trumpet, trump 515 | n03124043 cowboy boot 516 | n03124170 cowboy hat, ten-gallon hat 517 | n03125729 cradle 518 | n03126707 crane 519 | n03127747 crash helmet 520 | n03127925 crate 521 | n03131574 crib, cot 522 | n03133878 Crock Pot 523 | n03134739 croquet ball 524 | n03141823 crutch 525 | n03146219 cuirass 526 | n03160309 dam, dike, dyke 527 | n03179701 desk 528 | n03180011 desktop computer 529 | n03187595 dial telephone, dial phone 530 | n03188531 diaper, nappy, napkin 531 | n03196217 digital clock 532 | n03197337 digital watch 533 | n03201208 dining table, board 534 | n03207743 dishrag, dishcloth 535 | n03207941 dishwasher, dish washer, dishwashing machine 536 | n03208938 disk brake, disc brake 537 | n03216828 dock, dockage, docking facility 538 | n03218198 dogsled, dog sled, dog sleigh 539 | n03220513 dome 540 | n03223299 doormat, welcome mat 541 | n03240683 drilling platform, offshore rig 542 | n03249569 drum, membranophone, tympan 543 | n03250847 drumstick 544 | n03255030 dumbbell 545 | n03259280 Dutch oven 546 | n03271574 electric fan, blower 547 | n03272010 electric guitar 548 | n03272562 electric locomotive 549 | n03290653 entertainment center 550 | n03291819 envelope 551 | n03297495 espresso maker 552 | n03314780 face powder 553 | n03325584 feather boa, boa 554 | n03337140 file, file cabinet, filing cabinet 555 | n03344393 fireboat 556 | n03345487 fire engine, fire truck 557 | n03347037 fire screen, fireguard 558 | n03355925 flagpole, flagstaff 559 | n03372029 flute, transverse flute 560 | n03376595 folding chair 561 | n03379051 football helmet 562 | n03384352 forklift 563 | n03388043 fountain 564 | n03388183 fountain pen 565 | n03388549 four-poster 566 | n03393912 freight car 567 | n03394916 French horn, horn 568 | n03400231 frying pan, frypan, skillet 569 | n03404251 fur coat 570 | n03417042 garbage truck, dustcart 571 | n03424325 gasmask, respirator, gas helmet 572 | n03425413 gas pump, gasoline pump, petrol pump, island dispenser 573 | n03443371 goblet 574 | n03444034 go-kart 575 | n03445777 golf ball 576 | n03445924 golfcart, golf cart 577 | n03447447 gondola 578 | n03447721 gong, tam-tam 579 | n03450230 gown 580 | n03452741 grand piano, grand 581 | n03457902 greenhouse, nursery, glasshouse 582 | n03459775 grille, radiator grille 583 | n03461385 grocery store, grocery, food market, market 584 | n03467068 guillotine 585 | n03476684 hair slide 586 | n03476991 hair spray 587 | n03478589 half track 588 | n03481172 hammer 589 | n03482405 hamper 590 | n03483316 hand blower, blow dryer, blow drier, hair dryer, hair drier 591 | n03485407 hand-held computer, hand-held microcomputer 592 | n03485794 handkerchief, hankie, hanky, hankey 593 | n03492542 hard disc, hard disk, fixed disk 594 | n03494278 harmonica, mouth organ, harp, mouth harp 595 | n03495258 harp 596 | n03496892 harvester, reaper 597 | n03498962 hatchet 598 | n03527444 holster 599 | n03529860 home theater, home theatre 600 | n03530642 honeycomb 601 | n03532672 hook, claw 602 | n03534580 hoopskirt, crinoline 603 | n03535780 horizontal bar, high bar 604 | n03538406 horse cart, horse-cart 605 | n03544143 hourglass 606 | n03584254 iPod 607 | n03584829 iron, smoothing iron 608 | n03590841 jack-o'-lantern 609 | n03594734 jean, blue jean, denim 610 | n03594945 jeep, landrover 611 | n03595614 jersey, T-shirt, tee shirt 612 | n03598930 jigsaw puzzle 613 | n03599486 jinrikisha, ricksha, rickshaw 614 | n03602883 joystick 615 | n03617480 kimono 616 | n03623198 knee pad 617 | n03627232 knot 618 | n03630383 lab coat, laboratory coat 619 | n03633091 ladle 620 | n03637318 lampshade, lamp shade 621 | n03642806 laptop, laptop computer 622 | n03649909 lawn mower, mower 623 | n03657121 lens cap, lens cover 624 | n03658185 letter opener, paper knife, paperknife 625 | n03661043 library 626 | n03662601 lifeboat 627 | n03666591 lighter, light, igniter, ignitor 628 | n03670208 limousine, limo 629 | n03673027 liner, ocean liner 630 | n03676483 lipstick, lip rouge 631 | n03680355 Loafer 632 | n03690938 lotion 633 | n03691459 loudspeaker, speaker, speaker unit, loudspeaker system, speaker system 634 | n03692522 loupe, jeweler's loupe 635 | n03697007 lumbermill, sawmill 636 | n03706229 magnetic compass 637 | n03709823 mailbag, postbag 638 | n03710193 mailbox, letter box 639 | n03710637 maillot 640 | n03710721 maillot, tank suit 641 | n03717622 manhole cover 642 | n03720891 maraca 643 | n03721384 marimba, xylophone 644 | n03724870 mask 645 | n03729826 matchstick 646 | n03733131 maypole 647 | n03733281 maze, labyrinth 648 | n03733805 measuring cup 649 | n03742115 medicine chest, medicine cabinet 650 | n03743016 megalith, megalithic structure 651 | n03759954 microphone, mike 652 | n03761084 microwave, microwave oven 653 | n03763968 military uniform 654 | n03764736 milk can 655 | n03769881 minibus 656 | n03770439 miniskirt, mini 657 | n03770679 minivan 658 | n03773504 missile 659 | n03775071 mitten 660 | n03775546 mixing bowl 661 | n03776460 mobile home, manufactured home 662 | n03777568 Model T 663 | n03777754 modem 664 | n03781244 monastery 665 | n03782006 monitor 666 | n03785016 moped 667 | n03786901 mortar 668 | n03787032 mortarboard 669 | n03788195 mosque 670 | n03788365 mosquito net 671 | n03791053 motor scooter, scooter 672 | n03792782 mountain bike, all-terrain bike, off-roader 673 | n03792972 mountain tent 674 | n03793489 mouse, computer mouse 675 | n03794056 mousetrap 676 | n03796401 moving van 677 | n03803284 muzzle 678 | n03804744 nail 679 | n03814639 neck brace 680 | n03814906 necklace 681 | n03825788 nipple 682 | n03832673 notebook, notebook computer 683 | n03837869 obelisk 684 | n03838899 oboe, hautboy, hautbois 685 | n03840681 ocarina, sweet potato 686 | n03841143 odometer, hodometer, mileometer, milometer 687 | n03843555 oil filter 688 | n03854065 organ, pipe organ 689 | n03857828 oscilloscope, scope, cathode-ray oscilloscope, CRO 690 | n03866082 overskirt 691 | n03868242 oxcart 692 | n03868863 oxygen mask 693 | n03871628 packet 694 | n03873416 paddle, boat paddle 695 | n03874293 paddlewheel, paddle wheel 696 | n03874599 padlock 697 | n03876231 paintbrush 698 | n03877472 pajama, pyjama, pj's, jammies 699 | n03877845 palace 700 | n03884397 panpipe, pandean pipe, syrinx 701 | n03887697 paper towel 702 | n03888257 parachute, chute 703 | n03888605 parallel bars, bars 704 | n03891251 park bench 705 | n03891332 parking meter 706 | n03895866 passenger car, coach, carriage 707 | n03899768 patio, terrace 708 | n03902125 pay-phone, pay-station 709 | n03903868 pedestal, plinth, footstall 710 | n03908618 pencil box, pencil case 711 | n03908714 pencil sharpener 712 | n03916031 perfume, essence 713 | n03920288 Petri dish 714 | n03924679 photocopier 715 | n03929660 pick, plectrum, plectron 716 | n03929855 pickelhaube 717 | n03930313 picket fence, paling 718 | n03930630 pickup, pickup truck 719 | n03933933 pier 720 | n03935335 piggy bank, penny bank 721 | n03937543 pill bottle 722 | n03938244 pillow 723 | n03942813 ping-pong ball 724 | n03944341 pinwheel 725 | n03947888 pirate, pirate ship 726 | n03950228 pitcher, ewer 727 | n03954731 plane, carpenter's plane, woodworking plane 728 | n03956157 planetarium 729 | n03958227 plastic bag 730 | n03961711 plate rack 731 | n03967562 plow, plough 732 | n03970156 plunger, plumber's helper 733 | n03976467 Polaroid camera, Polaroid Land camera 734 | n03976657 pole 735 | n03977966 police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria 736 | n03980874 poncho 737 | n03982430 pool table, billiard table, snooker table 738 | n03983396 pop bottle, soda bottle 739 | n03991062 pot, flowerpot 740 | n03992509 potter's wheel 741 | n03995372 power drill 742 | n03998194 prayer rug, prayer mat 743 | n04004767 printer 744 | n04005630 prison, prison house 745 | n04008634 projectile, missile 746 | n04009552 projector 747 | n04019541 puck, hockey puck 748 | n04023962 punching bag, punch bag, punching ball, punchball 749 | n04026417 purse 750 | n04033901 quill, quill pen 751 | n04033995 quilt, comforter, comfort, puff 752 | n04037443 racer, race car, racing car 753 | n04039381 racket, racquet 754 | n04040759 radiator 755 | n04041544 radio, wireless 756 | n04044716 radio telescope, radio reflector 757 | n04049303 rain barrel 758 | n04065272 recreational vehicle, RV, R.V. 759 | n04067472 reel 760 | n04069434 reflex camera 761 | n04070727 refrigerator, icebox 762 | n04074963 remote control, remote 763 | n04081281 restaurant, eating house, eating place, eatery 764 | n04086273 revolver, six-gun, six-shooter 765 | n04090263 rifle 766 | n04099969 rocking chair, rocker 767 | n04111531 rotisserie 768 | n04116512 rubber eraser, rubber, pencil eraser 769 | n04118538 rugby ball 770 | n04118776 rule, ruler 771 | n04120489 running shoe 772 | n04125021 safe 773 | n04127249 safety pin 774 | n04131690 saltshaker, salt shaker 775 | n04133789 sandal 776 | n04136333 sarong 777 | n04141076 sax, saxophone 778 | n04141327 scabbard 779 | n04141975 scale, weighing machine 780 | n04146614 school bus 781 | n04147183 schooner 782 | n04149813 scoreboard 783 | n04152593 screen, CRT screen 784 | n04153751 screw 785 | n04154565 screwdriver 786 | n04162706 seat belt, seatbelt 787 | n04179913 sewing machine 788 | n04192698 shield, buckler 789 | n04200800 shoe shop, shoe-shop, shoe store 790 | n04201297 shoji 791 | n04204238 shopping basket 792 | n04204347 shopping cart 793 | n04208210 shovel 794 | n04209133 shower cap 795 | n04209239 shower curtain 796 | n04228054 ski 797 | n04229816 ski mask 798 | n04235860 sleeping bag 799 | n04238763 slide rule, slipstick 800 | n04239074 sliding door 801 | n04243546 slot, one-armed bandit 802 | n04251144 snorkel 803 | n04252077 snowmobile 804 | n04252225 snowplow, snowplough 805 | n04254120 soap dispenser 806 | n04254680 soccer ball 807 | n04254777 sock 808 | n04258138 solar dish, solar collector, solar furnace 809 | n04259630 sombrero 810 | n04263257 soup bowl 811 | n04264628 space bar 812 | n04265275 space heater 813 | n04266014 space shuttle 814 | n04270147 spatula 815 | n04273569 speedboat 816 | n04275548 spider web, spider's web 817 | n04277352 spindle 818 | n04285008 sports car, sport car 819 | n04286575 spotlight, spot 820 | n04296562 stage 821 | n04310018 steam locomotive 822 | n04311004 steel arch bridge 823 | n04311174 steel drum 824 | n04317175 stethoscope 825 | n04325704 stole 826 | n04326547 stone wall 827 | n04328186 stopwatch, stop watch 828 | n04330267 stove 829 | n04332243 strainer 830 | n04335435 streetcar, tram, tramcar, trolley, trolley car 831 | n04336792 stretcher 832 | n04344873 studio couch, day bed 833 | n04346328 stupa, tope 834 | n04347754 submarine, pigboat, sub, U-boat 835 | n04350905 suit, suit of clothes 836 | n04355338 sundial 837 | n04355933 sunglass 838 | n04356056 sunglasses, dark glasses, shades 839 | n04357314 sunscreen, sunblock, sun blocker 840 | n04366367 suspension bridge 841 | n04367480 swab, swob, mop 842 | n04370456 sweatshirt 843 | n04371430 swimming trunks, bathing trunks 844 | n04371774 swing 845 | n04372370 switch, electric switch, electrical switch 846 | n04376876 syringe 847 | n04380533 table lamp 848 | n04389033 tank, army tank, armored combat vehicle, armoured combat vehicle 849 | n04392985 tape player 850 | n04398044 teapot 851 | n04399382 teddy, teddy bear 852 | n04404412 television, television system 853 | n04409515 tennis ball 854 | n04417672 thatch, thatched roof 855 | n04418357 theater curtain, theatre curtain 856 | n04423845 thimble 857 | n04428191 thresher, thrasher, threshing machine 858 | n04429376 throne 859 | n04435653 tile roof 860 | n04442312 toaster 861 | n04443257 tobacco shop, tobacconist shop, tobacconist 862 | n04447861 toilet seat 863 | n04456115 torch 864 | n04458633 totem pole 865 | n04461696 tow truck, tow car, wrecker 866 | n04462240 toyshop 867 | n04465501 tractor 868 | n04467665 trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi 869 | n04476259 tray 870 | n04479046 trench coat 871 | n04482393 tricycle, trike, velocipede 872 | n04483307 trimaran 873 | n04485082 tripod 874 | n04486054 triumphal arch 875 | n04487081 trolleybus, trolley coach, trackless trolley 876 | n04487394 trombone 877 | n04493381 tub, vat 878 | n04501370 turnstile 879 | n04505470 typewriter keyboard 880 | n04507155 umbrella 881 | n04509417 unicycle, monocycle 882 | n04515003 upright, upright piano 883 | n04517823 vacuum, vacuum cleaner 884 | n04522168 vase 885 | n04523525 vault 886 | n04525038 velvet 887 | n04525305 vending machine 888 | n04532106 vestment 889 | n04532670 viaduct 890 | n04536866 violin, fiddle 891 | n04540053 volleyball 892 | n04542943 waffle iron 893 | n04548280 wall clock 894 | n04548362 wallet, billfold, notecase, pocketbook 895 | n04550184 wardrobe, closet, press 896 | n04552348 warplane, military plane 897 | n04553703 washbasin, handbasin, washbowl, lavabo, wash-hand basin 898 | n04554684 washer, automatic washer, washing machine 899 | n04557648 water bottle 900 | n04560804 water jug 901 | n04562935 water tower 902 | n04579145 whiskey jug 903 | n04579432 whistle 904 | n04584207 wig 905 | n04589890 window screen 906 | n04590129 window shade 907 | n04591157 Windsor tie 908 | n04591713 wine bottle 909 | n04592741 wing 910 | n04596742 wok 911 | n04597913 wooden spoon 912 | n04599235 wool, woolen, woollen 913 | n04604644 worm fence, snake fence, snake-rail fence, Virginia fence 914 | n04606251 wreck 915 | n04612504 yawl 916 | n04613696 yurt 917 | n06359193 web site, website, internet site, site 918 | n06596364 comic book 919 | n06785654 crossword puzzle, crossword 920 | n06794110 street sign 921 | n06874185 traffic light, traffic signal, stoplight 922 | n07248320 book jacket, dust cover, dust jacket, dust wrapper 923 | n07565083 menu 924 | n07579787 plate 925 | n07583066 guacamole 926 | n07584110 consomme 927 | n07590611 hot pot, hotpot 928 | n07613480 trifle 929 | n07614500 ice cream, icecream 930 | n07615774 ice lolly, lolly, lollipop, popsicle 931 | n07684084 French loaf 932 | n07693725 bagel, beigel 933 | n07695742 pretzel 934 | n07697313 cheeseburger 935 | n07697537 hotdog, hot dog, red hot 936 | n07711569 mashed potato 937 | n07714571 head cabbage 938 | n07714990 broccoli 939 | n07715103 cauliflower 940 | n07716358 zucchini, courgette 941 | n07716906 spaghetti squash 942 | n07717410 acorn squash 943 | n07717556 butternut squash 944 | n07718472 cucumber, cuke 945 | n07718747 artichoke, globe artichoke 946 | n07720875 bell pepper 947 | n07730033 cardoon 948 | n07734744 mushroom 949 | n07742313 Granny Smith 950 | n07745940 strawberry 951 | n07747607 orange 952 | n07749582 lemon 953 | n07753113 fig 954 | n07753275 pineapple, ananas 955 | n07753592 banana 956 | n07754684 jackfruit, jak, jack 957 | n07760859 custard apple 958 | n07768694 pomegranate 959 | n07802026 hay 960 | n07831146 carbonara 961 | n07836838 chocolate sauce, chocolate syrup 962 | n07860988 dough 963 | n07871810 meat loaf, meatloaf 964 | n07873807 pizza, pizza pie 965 | n07875152 potpie 966 | n07880968 burrito 967 | n07892512 red wine 968 | n07920052 espresso 969 | n07930864 cup 970 | n07932039 eggnog 971 | n09193705 alp 972 | n09229709 bubble 973 | n09246464 cliff, drop, drop-off 974 | n09256479 coral reef 975 | n09288635 geyser 976 | n09332890 lakeside, lakeshore 977 | n09399592 promontory, headland, head, foreland 978 | n09421951 sandbar, sand bar 979 | n09428293 seashore, coast, seacoast, sea-coast 980 | n09468604 valley, vale 981 | n09472597 volcano 982 | n09835506 ballplayer, baseball player 983 | n10148035 groom, bridegroom 984 | n10565667 scuba diver 985 | n11879895 rapeseed 986 | n11939491 daisy 987 | n12057211 yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum 988 | n12144580 corn 989 | n12267677 acorn 990 | n12620546 hip, rose hip, rosehip 991 | n12768682 buckeye, horse chestnut, conker 992 | n12985857 coral fungus 993 | n12998815 agaric 994 | n13037406 gyromitra 995 | n13040303 stinkhorn, carrion fungus 996 | n13044778 earthstar 997 | n13052670 hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa 998 | n13054560 bolete 999 | n13133613 ear, spike, capitulum 1000 | n15075141 toilet tissue, toilet paper, bathroom tissue 1001 | --------------------------------------------------------------------------------