darknet parser to be tested on yolo3
This commit is contained in:
+105
-39
@@ -8,27 +8,28 @@ namespace tk { namespace dnn {
|
||||
std::string type = "";
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int channels = 0;
|
||||
int channels = 3;
|
||||
int batch_normalize=0;
|
||||
int groups = 0;
|
||||
int filters=0;
|
||||
int size_x=0;
|
||||
int size_y=0;
|
||||
int stride_x=0;
|
||||
int stride_y=0;
|
||||
int groups = 1;
|
||||
int filters=1;
|
||||
int size_x=1;
|
||||
int size_y=1;
|
||||
int stride_x=1;
|
||||
int stride_y=1;
|
||||
int padding_x = 0;
|
||||
int padding_y = 0;
|
||||
int n_mask = 0;
|
||||
int classes = 0;
|
||||
int num = 0;
|
||||
float scale_xy = 0;
|
||||
int classes = 20;
|
||||
int num = 1;
|
||||
int pad = 0;
|
||||
float scale_xy = 1;
|
||||
std::vector<int> layers;
|
||||
std::string activation = "";
|
||||
std::string activation = "linear";
|
||||
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const darknetFields_t& f){
|
||||
os << f.width << " " << f.height << " " << f.channels << " " << f.batch_normalize<< " " << f.filters << " " << " " << f.activation;
|
||||
os << f.width << " " << f.height << " " << f.channels << " " << f.batch_normalize<< " " << f.filters << " " << f.activation<< " " << f.scale_xy;
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -52,26 +53,68 @@ namespace tk { namespace dnn {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<int> fromStringToIntVec(const std::string& line, const char delimiter){
|
||||
std::stringstream linestream(line);
|
||||
std::string value;
|
||||
std::vector<int> values;
|
||||
|
||||
while(getline(linestream,value,delimiter))
|
||||
values.push_back(std::stoi(value));
|
||||
return values;
|
||||
}
|
||||
|
||||
bool darknetParseFields(const std::string& line, darknetFields_t& fields){
|
||||
|
||||
std::string name,value;
|
||||
if(!divideNameAndValue(line, name, value))
|
||||
return false;
|
||||
//std::cout<<name<<std::endl;
|
||||
//std::cout<<value<<std::endl;
|
||||
if(name == "width")
|
||||
if(name.find("width") != std::string::npos)
|
||||
fields.width = std::stoi(value);
|
||||
else if (name == "height")
|
||||
else if(name.find("height") != std::string::npos)
|
||||
fields.height = std::stoi(value);
|
||||
else if (name == "channels")
|
||||
else if(name.find("channels") != std::string::npos)
|
||||
fields.channels = std::stoi(value);
|
||||
else if (name == "batch_normalize")
|
||||
else if(name.find("batch_normalize") != std::string::npos)
|
||||
fields.batch_normalize = std::stoi(value);
|
||||
else if (name == "filters")
|
||||
else if(name.find("filters") != std::string::npos)
|
||||
fields.filters = std::stoi(value);
|
||||
else if (name == "activation")
|
||||
else if(name.find("activation") != std::string::npos)
|
||||
fields.activation = value;
|
||||
|
||||
else if(name.find("size") != std::string::npos){
|
||||
fields.size_x = std::stoi(value);
|
||||
fields.size_y = std::stoi(value);
|
||||
}
|
||||
else if(name.find("size_x") != std::string::npos)
|
||||
fields.size_x = std::stoi(value);
|
||||
else if(name.find("size_y") != std::string::npos)
|
||||
fields.size_y = std::stoi(value);
|
||||
else if(name.find("stride") != std::string::npos){
|
||||
fields.stride_x = std::stoi(value);
|
||||
fields.stride_y = std::stoi(value);
|
||||
}
|
||||
else if(name.find("stride_x") != std::string::npos)
|
||||
fields.stride_x = std::stoi(value);
|
||||
else if(name.find("stride_y") != std::string::npos)
|
||||
fields.stride_y = std::stoi(value);
|
||||
else if(name.find("pad") != std::string::npos)
|
||||
fields.pad = std::stoi(value);
|
||||
else if(name.find("classes") != std::string::npos)
|
||||
fields.classes = std::stoi(value);
|
||||
else if(name.find("num") != std::string::npos)
|
||||
fields.num = std::stoi(value);
|
||||
else if(name.find("scale_xy") != std::string::npos)
|
||||
fields.scale_xy = std::stof(value);
|
||||
else if(name.find("from") != std::string::npos)
|
||||
fields.layers.push_back(std::stof(value));
|
||||
else if(name.find("mask") != std::string::npos){
|
||||
auto vec = fromStringToIntVec(value, ',');
|
||||
fields.n_mask = vec.size();
|
||||
}
|
||||
else if(name.find("layers") != std::string::npos)
|
||||
fields.layers = fromStringToIntVec(value, ',');
|
||||
|
||||
else
|
||||
std::cout<<"Not supported field: "<<line<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,40 +124,59 @@ namespace tk { namespace dnn {
|
||||
return new tk::dnn::Network(dim);
|
||||
}
|
||||
|
||||
void darknetAddLayer(tk::dnn::Network *net, darknetFields_t &f, std::string wgs_path) {
|
||||
|
||||
void darknetAddLayer(tk::dnn::Network *net, darknetFields_t &f, std::string wgs_path, std::vector<tk::dnn::Layer*> &netLayers) {
|
||||
if(net == nullptr)
|
||||
FatalError("Cant add a layer without a Net\n");
|
||||
|
||||
// padding compute
|
||||
if(f.pad == 1) {
|
||||
f.padding_x = f.padding_y = f.size_x /2;
|
||||
}
|
||||
|
||||
std::cout<<"Add layer: "<<f.type<<"\n";
|
||||
if(f.type == "convolutional") {
|
||||
std::string wgs = wgs_path + "/c" + std::to_string(net->num_layers) + ".bin";
|
||||
std::string wgs = wgs_path + "/c" + std::to_string(netLayers.size()) + ".bin";
|
||||
printf("%d (%d,%d) (%d,%d) (%d,%d) %s %d %d\n", f.filters, f.size_x, f.size_y, f.stride_x, f.stride_y, f.padding_x, f.padding_y, wgs.c_str(), f.batch_normalize, f.groups);
|
||||
new tk::dnn::Conv2d(net, f.filters, f.size_x, f.size_y, f.stride_x,
|
||||
f.stride_y, f.padding_x, f.padding_y, wgs, f.batch_normalize, false, f.groups);
|
||||
|
||||
netLayers.push_back(new tk::dnn::Conv2d(net, f.filters, f.size_x, f.size_y, f.stride_x,
|
||||
f.stride_y, f.padding_x, f.padding_y, wgs, f.batch_normalize, false, f.groups));
|
||||
if(f.activation != "linear") {
|
||||
tkdnnActivationMode_t act;
|
||||
if(f.activation == "relu") act = tkdnnActivationMode_t(CUDNN_ACTIVATION_RELU);
|
||||
else if(f.activation == "leaky") act = tk::dnn::ACTIVATION_LEAKY;
|
||||
else if(f.activation == "mish") act = tk::dnn::ACTIVATION_MISH;
|
||||
else { FatalError("activation not supported: " + f.activation); }
|
||||
new tk::dnn::Activation(net, act);
|
||||
}
|
||||
} else if(f.type == "shortcut") {
|
||||
if(f.layers.size() != 1) FatalError("no layers to shortcut\n");
|
||||
int layerIdx = net->num_layers + f.layers[0];
|
||||
if(layerIdx < 0 || layerIdx >= net->num_layers) FatalError("impossible to shortcut\n");
|
||||
std::cout<<"shortcut to "<<layerIdx<<" "<<net->layers[layerIdx]->getLayerName()<<"\n";
|
||||
new tk::dnn::Shortcut(net, net->layers[layerIdx]);
|
||||
int layerIdx = f.layers[0];
|
||||
if(layerIdx < 0)
|
||||
layerIdx = netLayers.size() + layerIdx;
|
||||
if(layerIdx < 0 || layerIdx >= netLayers.size()) FatalError("impossible to shortcut\n");
|
||||
std::cout<<"shortcut to "<<layerIdx<<" "<<netLayers[layerIdx]->getLayerName()<<"\n";
|
||||
netLayers.push_back(new tk::dnn::Shortcut(net, netLayers[layerIdx]));
|
||||
|
||||
} else if(f.type == "upsample") {
|
||||
new tk::dnn::Upsample(net, f.stride_x);
|
||||
netLayers.push_back(new tk::dnn::Upsample(net, f.stride_x));
|
||||
|
||||
} else if(f.type == "route") {
|
||||
if(f.layers.size() == 0) FatalError("no layers to Route\n");
|
||||
std::vector<tk::dnn::Layer*> layers;
|
||||
for(int i=0; i<f.layers.size(); i++) {
|
||||
int layerIdx = net->num_layers + f.layers[i];
|
||||
if(layerIdx < 0 || layerIdx >= net->num_layers) FatalError("impossible to shortcut\n");
|
||||
layers.push_back(net->layers[layerIdx]);
|
||||
int layerIdx = f.layers[i];
|
||||
if(layerIdx < 0)
|
||||
layerIdx = netLayers.size() + layerIdx;
|
||||
if(layerIdx < 0 || layerIdx >= netLayers.size()) FatalError("impossible to route\n");
|
||||
std::cout<<"Route to "<<layerIdx<<" "<<netLayers[layerIdx]->getLayerName()<<"\n";
|
||||
layers.push_back(netLayers[layerIdx]);
|
||||
}
|
||||
new tk::dnn::Route(net, layers.data(), layers.size());
|
||||
netLayers.push_back(new tk::dnn::Route(net, layers.data(), layers.size()));
|
||||
|
||||
} else if(f.type == "yolo") {
|
||||
std::string wgs = wgs_path + "/g" + std::to_string(net->num_layers) + ".bin";
|
||||
new tk::dnn::Yolo(net, f.classes, f.num, wgs, f.n_mask, f.scale_xy);
|
||||
std::string wgs = wgs_path + "/g" + std::to_string(netLayers.size()) + ".bin";
|
||||
printf("%d %d %s %d %f\n", f.classes, f.num/f.n_mask, wgs.c_str(), f.n_mask, f.scale_xy);
|
||||
netLayers.push_back(new tk::dnn::Yolo(net, f.classes, f.num/f.n_mask, wgs, f.n_mask, f.scale_xy));
|
||||
|
||||
} else{
|
||||
FatalError("layer not supported: " + f.type);
|
||||
@@ -124,6 +186,9 @@ namespace tk { namespace dnn {
|
||||
tk::dnn::Network* darknetParser(std::string cfg_file, std::string wgs_path) {
|
||||
|
||||
tk::dnn::Network *net = nullptr;
|
||||
|
||||
// layers without activations to retrive correct id number
|
||||
std::vector<tk::dnn::Layer*> netLayers;
|
||||
|
||||
std::ifstream if_cfg(cfg_file);
|
||||
if(!if_cfg.is_open())
|
||||
@@ -149,7 +214,7 @@ namespace tk { namespace dnn {
|
||||
if(fields.type == "net")
|
||||
net = darknetAddNet(fields);
|
||||
else
|
||||
darknetAddLayer(net, fields, wgs_path);
|
||||
darknetAddLayer(net, fields, wgs_path, netLayers);
|
||||
}
|
||||
|
||||
// new type
|
||||
@@ -168,12 +233,13 @@ namespace tk { namespace dnn {
|
||||
|
||||
// end of filled type
|
||||
if(fields.type != "") {
|
||||
darknetAddLayer(net, fields, wgs_path);
|
||||
darknetAddLayer(net, fields, wgs_path, netLayers);
|
||||
}
|
||||
|
||||
if(net == nullptr) {
|
||||
FatalError("net not found\n");
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-38
@@ -11,72 +11,52 @@ int main() {
|
||||
|
||||
tk::dnn::Network *net = tk::dnn::darknetParser("../tests/yolo3/yolov3.cfg", "yolo3/layers");
|
||||
net->print();
|
||||
/*
|
||||
int classes = 80;
|
||||
|
||||
|
||||
tk::dnn::Yolo *yolo [3];
|
||||
#include "models/Yolo3.h"
|
||||
|
||||
|
||||
std::vector<tk::dnn::Yolo*> yolo;
|
||||
for(int i=0; i<net->num_layers; i++) {
|
||||
if(net->layers[i]->getLayerType() == tk::dnn::layerType_t::LAYER_YOLO)
|
||||
yolo.push_back((tk::dnn::Yolo*)net->layers[i]);
|
||||
}
|
||||
|
||||
// fill classes names
|
||||
for(int i=0; i<3; i++) {
|
||||
yolo[i]->classesNames = {"person" , "bicycle" , "car" , "motorbike" , "aeroplane" , "bus" , "train" , "truck" , "boat" , "traffic light" , "fire hydrant" , "stop sign" , "parking meter" , "bench" , "bird" , "cat" , "dog" , "horse" , "sheep" , "cow" , "elephant" , "bear" , "zebra" , "giraffe" , "backpack" , "umbrella" , "handbag" , "tie" , "suitcase" , "frisbee" , "skis" , "snowboard" , "sports ball" , "kite" , "baseball bat" , "baseball glove" , "skateboard" , "surfboard" , "tennis racket" , "bottle" , "wine glass" , "cup" , "fork" , "knife" , "spoon" , "bowl" , "banana" , "apple" , "sandwich" , "orange" , "broccoli" , "carrot" , "hot dog" , "pizza" , "donut" , "cake" , "chair" , "sofa" , "pottedplant" , "bed" , "diningtable" , "toilet" , "tvmonitor" , "laptop" , "mouse" , "remote" , "keyboard" , "cell phone" , "microwave" , "oven" , "toaster" , "sink" , "refrigerator" , "book" , "clock" , "vase" , "scissors" , "teddy bear" , "hair drier" , "toothbrush"};
|
||||
}
|
||||
|
||||
std::string input_bin = bin_path + "/layers/input.bin";
|
||||
std::vector<std::string> output_bins = {
|
||||
bin_path + "/debug/layer82_out.bin",
|
||||
bin_path + "/debug/layer94_out.bin",
|
||||
bin_path + "/debug/layer106_out.bin"
|
||||
};
|
||||
|
||||
// Load input
|
||||
dnnType *data;
|
||||
dnnType *input_h;
|
||||
readBinaryFile(input_bin, dim.tot(), &input_h, &data);
|
||||
|
||||
//print network model
|
||||
net.print();
|
||||
readBinaryFile(input_bin, net->input_dim.tot(), &input_h, &data);
|
||||
|
||||
|
||||
//convert network to tensorRT
|
||||
tk::dnn::NetworkRT netRT(&net, net.getNetworkRTName("yolo3"));
|
||||
tk::dnn::NetworkRT netRT(net, net->getNetworkRTName("yolo3"));
|
||||
|
||||
// the network have 3 outputs
|
||||
tk::dnn::dataDim_t out_dim[3];
|
||||
for(int i=0; i<3; i++) out_dim[i] = yolo[i]->output_dim;
|
||||
dnnType *cudnn_out[3], *rt_out[3];
|
||||
|
||||
tk::dnn::dataDim_t dim1 = dim; //input dim
|
||||
tk::dnn::dataDim_t dim1 = net->input_dim; //input dim
|
||||
printCenteredTitle(" CUDNN inference ", '=', 30); {
|
||||
dim1.print();
|
||||
TIMER_START
|
||||
net.infer(dim1, data);
|
||||
net->infer(dim1, data);
|
||||
TIMER_STOP
|
||||
dim1.print();
|
||||
}
|
||||
for(int i=0; i<3; i++) cudnn_out[i] = yolo[i]->dstData;
|
||||
|
||||
printCenteredTitle(" compute detections ", '=', 30);
|
||||
TIMER_START
|
||||
int ndets = 0;
|
||||
tk::dnn::Yolo::detection *dets = tk::dnn::Yolo::allocateDetections(tk::dnn::Yolo::MAX_DETECTIONS, classes);
|
||||
for(int i=0; i<3; i++) yolo[i]->computeDetections(dets, ndets, net.input_dim.w, net.input_dim.h, 0.5);
|
||||
tk::dnn::Yolo::mergeDetections(dets, ndets, classes);
|
||||
|
||||
for(int j=0; j<ndets; j++) {
|
||||
tk::dnn::Yolo::box b = dets[j].bbox;
|
||||
int x0 = (b.x-b.w/2.);
|
||||
int x1 = (b.x+b.w/2.);
|
||||
int y0 = (b.y-b.h/2.);
|
||||
int y1 = (b.y+b.h/2.);
|
||||
|
||||
int cl = 0;
|
||||
for(int c = 0; c < classes; ++c){
|
||||
float prob = dets[j].prob[c];
|
||||
if(prob > 0)
|
||||
cl = c;
|
||||
}
|
||||
std::cout<<cl<<": "<<x0<<" "<<y0<<" "<<x1<<" "<<y1<<"\n";
|
||||
}
|
||||
TIMER_STOP
|
||||
|
||||
tk::dnn::dataDim_t dim2 = dim;
|
||||
tk::dnn::dataDim_t dim2 = net->input_dim;
|
||||
printCenteredTitle(" TENSORRT inference ", '=', 30); {
|
||||
dim2.print();
|
||||
TIMER_START
|
||||
@@ -100,5 +80,5 @@ int main() {
|
||||
ret_cudnn_tensorrt |= checkResult(odim, cudnn_out[i], rt_out[i]) == 0 ? 0 : ERROR_CUDNNvsTENSORRT;
|
||||
}
|
||||
return ret_cudnn | ret_tensorrt | ret_cudnn_tensorrt;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user