diff --git a/modules/dnn/src/onnx/onnx_graph_simplifier.cpp b/modules/dnn/src/onnx/onnx_graph_simplifier.cpp index b51435dd66..01103dfdd3 100644 --- a/modules/dnn/src/onnx/onnx_graph_simplifier.cpp +++ b/modules/dnn/src/onnx/onnx_graph_simplifier.cpp @@ -1728,6 +1728,15 @@ void simplifySubgraphs(opencv_onnx::GraphProto& net) } +static std::string getExternalDataValue(const opencv_onnx::TensorProto& tensor_proto, const std::string& key) +{ + for (const auto& entry : tensor_proto.external_data()) + { + if (entry.key() == key) + return entry.value(); + } + return std::string(); +} static char* getTensorRAWData(const opencv_onnx::TensorProto& tensor_proto, std::vector& tensor_data, const std::string& base_path = "") @@ -1735,24 +1744,31 @@ static char* getTensorRAWData(const opencv_onnx::TensorProto& tensor_proto, if (tensor_proto.has_data_location() && tensor_proto.data_location() == opencv_onnx::TensorProto::EXTERNAL) { #if OPENCV_HAVE_FILESYSTEM_SUPPORT CV_Assert(tensor_proto.has_data_location() && tensor_proto.data_location() == opencv_onnx::TensorProto::EXTERNAL); - auto it_begin = tensor_proto.external_data().begin(); - auto it_end = tensor_proto.external_data().end(); - // file path - auto it = std::find_if(it_begin, it_end,[](const auto& entry) { return entry.key() == "location"; }); - CV_CheckTrue(it != it_end, "External tensor data location is not specified"); + std::string location_path = getExternalDataValue(tensor_proto, "location"); + CV_CheckTrue(!location_path.empty(), "External tensor data location is not specified"); - - std::string location_path = it->value(); std::string full_path = base_path.empty() ? location_path : utils::fs::join(base_path, location_path); std::ifstream file(full_path, std::ios::binary | std::ios::ate); CV_CheckTrue(file.is_open(), "Failed to open external tensor data file"); - size_t size = file.tellg(); - file.seekg(0, std::ios::beg); - tensor_data.resize(divUp((size_t)size, sizeof(int64_t))); + size_t file_size = (size_t)file.tellg(); + size_t offset = 0; + std::string offset_str = getExternalDataValue(tensor_proto, "offset"); + if (!offset_str.empty()) + offset = (size_t)std::stoull(offset_str); - file.read((char*)tensor_data.data(), size); + size_t length = file_size - offset; + std::string length_str = getExternalDataValue(tensor_proto, "length"); + if (!length_str.empty()) + length = (size_t)std::stoull(length_str); + + CV_Check(offset, offset <= file_size, "External data offset exceeds file size"); + CV_Check(length, length <= file_size - offset, "External data length exceeds available bytes"); + + file.seekg(offset, std::ios::beg); + tensor_data.resize(divUp(length, sizeof(int64_t))); + file.read((char*)tensor_data.data(), length); return (char*)tensor_data.data(); #else CV_Error(Error::StsNotImplemented, "External tensor data is not supported without filesystem support"); diff --git a/modules/dnn/src/onnx/onnx_importer2.cpp b/modules/dnn/src/onnx/onnx_importer2.cpp index 369b283398..0762b3188e 100644 --- a/modules/dnn/src/onnx/onnx_importer2.cpp +++ b/modules/dnn/src/onnx/onnx_importer2.cpp @@ -1370,7 +1370,7 @@ void ONNXImporter2::parseConv(LayerParams& layerParams, const opencv_onnx::NodeP int n_inputs = node_proto.input_size(); CV_Assert(2 <= n_inputs && n_inputs <= 3); layerParams.type = "Conv2"; - addLayer(layerParams, node_proto); + addLayer(layerParams, node_proto, n_inputs); } void ONNXImporter2::parseConvTranspose(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto) diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index 625f5fb526..7e1e23067c 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -2563,6 +2563,12 @@ TEST_P(Test_ONNX_nets, MobileNet_v2_FP16) testONNXModels("mobilenetv2_fp16", npy, default_l1, default_lInf, true); } +TEST_P(Test_ONNX_nets, MobileNet_v4) +{ + required = true; + testONNXModels("mobilenetv4", npy, default_l1, default_lInf, true); +} + TEST_P(Test_ONNX_nets, LResNet100E_IR) { applyTestTag(