提问人:Stef 提问时间:11/17/2023 更新时间:11/17/2023 访问量:26
C++ - 坚持使用YoloV4,ONNX和TensorRT
C++ - Stuck with YoloV4, ONNX and TensorRT
问:
我正在使用 YoloV4/C++/OpenCV 进行一些检测,它运行得很好。 呵呵,为了改善时间消耗,我正在尝试将所有内容都转移到 NVIDIA TensorRT 上,但我在那里感到迷茫。
我使用 TensorRT 工具将 .weights 文件转换为 ONNX,然后将 ONNX 模型转换为 TensorRT 引擎,如下所示:
void ONNXConvert()
{
MyLogger logger;
nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(logger);
nvinfer1::INetworkDefinition* network = builder->createNetworkV2(1U << static_cast<int>(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH));
// Load ONNX model
const auto parser = nvonnxparser::createParser(*network, logger);
// Parse the ONNX model
// Some code here...
std::ifstream onnxFile(onnxModelFile, std::ios::binary);
if (!onnxFile)
{
std::cerr << "Error opening ONNX model file. " << onnxModelFile << std::endl;
return;
}
onnxFile.seekg(0, onnxFile.end);
const size_t modelSize = onnxFile.tellg();
onnxFile.seekg(0, onnxFile.beg);
// Allocate buffer to hold the ONNX model
std::vector<char> onnxModelBuffer(modelSize);
onnxFile.read(onnxModelBuffer.data(), modelSize);
if (!parser->parse(onnxModelBuffer.data(), modelSize))
{
std::cerr << "Error parsing ONNX model." << std::endl;
return;
}
// Create a builder configuration
nvinfer1::IBuilderConfig* config = builder->createBuilderConfig();
// Set configuration options as needed
config->setMemoryPoolLimit(nvinfer1::MemoryPoolType::kWORKSPACE, 1 << 30);
nvinfer1::IHostMemory* serializedEngine = builder->buildSerializedNetwork(*network, *config);
std::cout << "Number of layers in the network: " << network->getNbLayers() << std::endl;
std::ofstream outFile("yolov4.engine", std::ios::binary);
outFile.write(reinterpret_cast<const char*>(serializedEngine->data()), serializedEngine->size());
outFile.close();
builder->destroy();
network->destroy();
serializedEngine->destroy();
}
完成后,我可以加载生成的引擎并执行推理,在我尝试解析检测结果之前,一切似乎都很顺利。
我想知道类概率和边界框坐标,但我所拥有的一切都是不一致的值。
从我的 YoloV4 配置中,我知道我有:
- 20节课
- 输入宽度 = 608
- 输入高度 = 608
- 通道 = 3
- 9 个尺寸为 { 12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401 } 的锚点
推理后,我有 2 个输出缓冲区:
- 一个 1x22743x1x4,我想我会在其中找到边界框坐标
- 一个 1x22743x20,我想我会在其中找到类概率
这就是我迷路的地方。 为什么有 22743 次检测?这个数字是如何计算的? 我必须如何解析检测以正确计算坐标和类概率?
我天真地尝试像这样直接解析输出:
for (int d = 0; d < 22743; d++)
{
float maxProb = -1000.0f;
int classId = -1;
for (int c = 0; c < 20; c++)
{
if (classes[d * 20 + c] > maxProb)
{
maxProb = classes[d * 20 + c];
classId = c;
}
}
if (maxProb > CONFIDENCE_THRESHOLD)
{
float boxX = boxes[d * 4];
float boxY = boxes[d * 4 + 1];
float boxW = boxes[d * 4 + 2];
float boxH = boxes[d * 4 + 3];
}
}
但我得到的都是微小的概率(如< 1E-05),以及微小的、有时是负数的框坐标。
我知道我应该使用我对锚点的了解,但我真的不确定如何。
有人可以帮我谈谈吗?每一个帮助都会不胜感激。
答: 暂无答案
评论
22743 = 3 * (19*19 + 38*38 + 76*76)