diff --git a/include/tkDNN/DarknetParser.h b/include/tkDNN/DarknetParser.h index da6cfc1..d92f671 100644 --- a/include/tkDNN/DarknetParser.h +++ b/include/tkDNN/DarknetParser.h @@ -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 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 fromStringToIntVec(const std::string& line, const char delimiter){ + std::stringstream linestream(line); + std::string value; + std::vector 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< &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: "<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 "<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 "<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 layers; for(int i=0; inum_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 "<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 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; } diff --git a/tests/yolo3/yolo3.cpp b/tests/yolo3/yolo3.cpp index 9ca1eeb..70f0b9f 100644 --- a/tests/yolo3/yolo3.cpp +++ b/tests/yolo3/yolo3.cpp @@ -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 yolo; + for(int i=0; inum_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 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 0) - cl = c; - } - std::cout<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; - */ + }