Another way to build yolov5 engines (#416)
* Update yolov5.cpp * Update README.md * Update README.md
This commit is contained in:
parent
37f03a77c5
commit
fec5e618d4
@ -46,7 +46,11 @@ mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
sudo ./yolov5 -s // serialize model to plan file i.e. 'yolov5s.engine'
|
||||
sudo ./yolov5 -s 0.33 0.50 // serialize yolov5s model to plan file i.e. 'yolov5.engine'
|
||||
sudo ./yolov5 -s 0.67 0.75 // serialize yolov5m model to plan file i.e. 'yolov5.engine'
|
||||
sudo ./yolov5 -s 1.0 1.0 // serialize yolov5l model to plan file i.e. 'yolov5.engine'
|
||||
sudo ./yolov5 -s 1.33 1.25 // serialize yolov5x model to plan file i.e. 'yolov5.engine'
|
||||
sudo ./yolov5 -s 0.17 0.25 // serialize your own yolov5 model with depth_multiple and width_multiple which you set in '.yaml' file when training the model. i.e. depth = 0.17, width = 0.25
|
||||
sudo ./yolov5 -d ../samples // deserialize plan file and run inference, the images in samples will be processed.
|
||||
```
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#define NMS_THRESH 0.4
|
||||
#define CONF_THRESH 0.5
|
||||
#define BATCH_SIZE 1
|
||||
#define MODEL "../yolov5.wts"
|
||||
|
||||
#define NET s // s m l x
|
||||
#define NETSTRUCT(str) createEngine_##str
|
||||
@ -26,6 +27,121 @@ static const int OUTPUT_SIZE = Yolo::MAX_OUTPUT_BBOX_COUNT * sizeof(Yolo::Detect
|
||||
const char* INPUT_BLOB_NAME = "data";
|
||||
const char* OUTPUT_BLOB_NAME = "prob";
|
||||
static Logger gLogger;
|
||||
static float gw;
|
||||
static float gd;
|
||||
|
||||
int get_width(int x, int divisor = 8) {
|
||||
//return math.ceil(x / divisor) * divisor
|
||||
if (int(x * gw) % divisor == 0) {
|
||||
return int(x * gw);
|
||||
}
|
||||
return (int(x * gw / divisor) + 1) * divisor;
|
||||
}
|
||||
|
||||
int get_depth(int x) {
|
||||
if (x == 1) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return round(x * gd) > 1 ? round(x * gd) : 1;
|
||||
}
|
||||
}
|
||||
|
||||
ICudaEngine* build_engine(unsigned int maxBatchSize, IBuilder* builder, IBuilderConfig* config, DataType dt) {
|
||||
INetworkDefinition* network = builder->createNetworkV2(0U);
|
||||
|
||||
// Create input tensor of shape {3, INPUT_H, INPUT_W} with name INPUT_BLOB_NAME
|
||||
ITensor* data = network->addInput(INPUT_BLOB_NAME, dt, Dims3{ 3, INPUT_H, INPUT_W });
|
||||
assert(data);
|
||||
|
||||
std::map<std::string, Weights> weightMap = loadWeights(MODEL);
|
||||
Weights emptywts{ DataType::kFLOAT, nullptr, 0 };
|
||||
|
||||
/* ------ yolov5 backbone------ */
|
||||
auto focus0 = focus(network, weightMap, *data, 3, get_width(64), 3, "model.0");
|
||||
auto conv1 = convBlock(network, weightMap, *focus0->getOutput(0), get_width(128), 3, 2, 1, "model.1");
|
||||
auto bottleneck_CSP2 = C3(network, weightMap, *conv1->getOutput(0), get_width(128), get_width(128), get_depth(3), true, 1, 0.5, "model.2");
|
||||
auto conv3 = convBlock(network, weightMap, *bottleneck_CSP2->getOutput(0), get_width(256), 3, 2, 1, "model.3");
|
||||
auto bottleneck_csp4 = C3(network, weightMap, *conv3->getOutput(0), get_width(256), get_width(256), get_depth(9), true, 1, 0.5, "model.4");
|
||||
auto conv5 = convBlock(network, weightMap, *bottleneck_csp4->getOutput(0), get_width(512), 3, 2, 1, "model.5");
|
||||
auto bottleneck_csp6 = C3(network, weightMap, *conv5->getOutput(0), get_width(512), get_width(512), get_depth(9), true, 1, 0.5, "model.6");
|
||||
auto conv7 = convBlock(network, weightMap, *bottleneck_csp6->getOutput(0), get_width(1024), 3, 2, 1, "model.7");
|
||||
auto spp8 = SPP(network, weightMap, *conv7->getOutput(0), get_width(1024), get_width(1024), 5, 9, 13, "model.8");
|
||||
|
||||
/* ------ yolov5 head ------ */
|
||||
auto bottleneck_csp9 = C3(network, weightMap, *spp8->getOutput(0), get_width(1024), get_width(1024), get_depth(3), false, 1, 0.5, "model.9");
|
||||
auto conv10 = convBlock(network, weightMap, *bottleneck_csp9->getOutput(0), get_width(512), 1, 1, 1, "model.10");
|
||||
|
||||
float* deval = reinterpret_cast<float*>(malloc(sizeof(float) * get_width(512) * 2 * 2));
|
||||
for (int i = 0; i < get_width(512) * 2 * 2; i++) {
|
||||
deval[i] = 1.0;
|
||||
}
|
||||
Weights deconvwts11{ DataType::kFLOAT, deval, get_width(512) * 2 * 2 };
|
||||
IDeconvolutionLayer* deconv11 = network->addDeconvolutionNd(*conv10->getOutput(0), get_width(512), DimsHW{ 2, 2 }, deconvwts11, emptywts);
|
||||
deconv11->setStrideNd(DimsHW{ 2, 2 });
|
||||
deconv11->setNbGroups(get_width(512));
|
||||
weightMap["deconv11"] = deconvwts11;
|
||||
|
||||
ITensor* inputTensors12[] = { deconv11->getOutput(0), bottleneck_csp6->getOutput(0) };
|
||||
auto cat12 = network->addConcatenation(inputTensors12, 2);
|
||||
auto bottleneck_csp13 = C3(network, weightMap, *cat12->getOutput(0), get_width(1024), get_width(512), get_depth(3), false, 1, 0.5, "model.13");
|
||||
auto conv14 = convBlock(network, weightMap, *bottleneck_csp13->getOutput(0), get_width(256), 1, 1, 1, "model.14");
|
||||
|
||||
Weights deconvwts15{ DataType::kFLOAT, deval, get_width(256) * 2 * 2 };
|
||||
IDeconvolutionLayer* deconv15 = network->addDeconvolutionNd(*conv14->getOutput(0), get_width(256), DimsHW{ 2, 2 }, deconvwts15, emptywts);
|
||||
deconv15->setStrideNd(DimsHW{ 2, 2 });
|
||||
deconv15->setNbGroups(get_width(256));
|
||||
ITensor* inputTensors16[] = { deconv15->getOutput(0), bottleneck_csp4->getOutput(0) };
|
||||
auto cat16 = network->addConcatenation(inputTensors16, 2);
|
||||
|
||||
auto bottleneck_csp17 = C3(network, weightMap, *cat16->getOutput(0), get_width(512), get_width(256), get_depth(3), false, 1, 0.5, "model.17");
|
||||
|
||||
// yolo layer 0
|
||||
IConvolutionLayer* det0 = network->addConvolutionNd(*bottleneck_csp17->getOutput(0), 3 * (Yolo::CLASS_NUM + 5), DimsHW{ 1, 1 }, weightMap["model.24.m.0.weight"], weightMap["model.24.m.0.bias"]);
|
||||
auto conv18 = convBlock(network, weightMap, *bottleneck_csp17->getOutput(0), get_width(256), 3, 2, 1, "model.18");
|
||||
ITensor* inputTensors19[] = { conv18->getOutput(0), conv14->getOutput(0) };
|
||||
auto cat19 = network->addConcatenation(inputTensors19, 2);
|
||||
auto bottleneck_csp20 = C3(network, weightMap, *cat19->getOutput(0), get_width(512), get_width(512), get_depth(3), false, 1, 0.5, "model.20");
|
||||
//yolo layer 1
|
||||
IConvolutionLayer* det1 = network->addConvolutionNd(*bottleneck_csp20->getOutput(0), 3 * (Yolo::CLASS_NUM + 5), DimsHW{ 1, 1 }, weightMap["model.24.m.1.weight"], weightMap["model.24.m.1.bias"]);
|
||||
auto conv21 = convBlock(network, weightMap, *bottleneck_csp20->getOutput(0), get_width(512), 3, 2, 1, "model.21");
|
||||
ITensor* inputTensors22[] = { conv21->getOutput(0), conv10->getOutput(0) };
|
||||
auto cat22 = network->addConcatenation(inputTensors22, 2);
|
||||
auto bottleneck_csp23 = C3(network, weightMap, *cat22->getOutput(0), get_width(1024), get_width(1024), get_depth(3), false, 1, 0.5, "model.23");
|
||||
IConvolutionLayer* det2 = network->addConvolutionNd(*bottleneck_csp23->getOutput(0), 3 * (Yolo::CLASS_NUM + 5), DimsHW{ 1, 1 }, weightMap["model.24.m.2.weight"], weightMap["model.24.m.2.bias"]);
|
||||
|
||||
auto yolo = addYoLoLayer(network, weightMap, det0, det1, det2);
|
||||
yolo->getOutput(0)->setName(OUTPUT_BLOB_NAME);
|
||||
network->markOutput(*yolo->getOutput(0));
|
||||
|
||||
// Build engine
|
||||
builder->setMaxBatchSize(maxBatchSize);
|
||||
config->setMaxWorkspaceSize(16 * (1 << 20)); // 16MB
|
||||
#if defined(USE_FP16)
|
||||
config->setFlag(BuilderFlag::kFP16);
|
||||
#elif defined(USE_INT8)
|
||||
std::cout << "Your platform support int8: " << (builder->platformHasFastInt8() ? "true" : "false") << std::endl;
|
||||
assert(builder->platformHasFastInt8());
|
||||
config->setFlag(BuilderFlag::kINT8);
|
||||
Int8EntropyCalibrator2* calibrator = new Int8EntropyCalibrator2(1, INPUT_W, INPUT_H, "./coco_calib/", "int8calib.table", INPUT_BLOB_NAME);
|
||||
config->setInt8Calibrator(calibrator);
|
||||
#endif
|
||||
|
||||
std::cout << "Building engine, please wait for a while..." << std::endl;
|
||||
ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config);
|
||||
std::cout << "Build engine successfully!" << std::endl;
|
||||
|
||||
// Don't need the network any more
|
||||
network->destroy();
|
||||
|
||||
// Release host memory
|
||||
for (auto& mem : weightMap)
|
||||
{
|
||||
free((void*)(mem.second.values));
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
// Creat the engine using only the API and not any parser.
|
||||
ICudaEngine* createEngine_s(unsigned int maxBatchSize, IBuilder* builder, IBuilderConfig* config, DataType dt) {
|
||||
@ -421,7 +537,8 @@ void APIToModel(unsigned int maxBatchSize, IHostMemory** modelStream) {
|
||||
IBuilderConfig* config = builder->createBuilderConfig();
|
||||
|
||||
// Create model to populate the network, then set the outputs and create an engine
|
||||
ICudaEngine* engine = (CREATENET(NET))(maxBatchSize, builder, config, DataType::kFLOAT);
|
||||
//ICudaEngine* engine = (CREATENET(NET))(maxBatchSize, builder, config, DataType::kFLOAT);
|
||||
ICudaEngine* engine = build_engine(maxBatchSize, builder, config, DataType::kFLOAT);
|
||||
//ICudaEngine* engine = createEngine(maxBatchSize, builder, config, DataType::kFLOAT);
|
||||
assert(engine != nullptr);
|
||||
|
||||
@ -448,7 +565,10 @@ int main(int argc, char** argv) {
|
||||
size_t size{ 0 };
|
||||
std::string engine_name = STR2(NET);
|
||||
engine_name = "yolov5" + engine_name + ".engine";
|
||||
if (argc == 2 && std::string(argv[1]) == "-s") {
|
||||
if (argc == 4 && std::string(argv[1]) == "-s") {
|
||||
//The third arg is depth and the fourth is width
|
||||
gw = atof(argv[3]);
|
||||
gd = atof(argv[2]);
|
||||
IHostMemory* modelStream{ nullptr };
|
||||
APIToModel(BATCH_SIZE, &modelStream);
|
||||
assert(modelStream != nullptr);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user