opencv調用Onnx模型常見問題


以下都是pytorch模型轉換為onnx,然后利用opencv中dnn模塊的readNetFromONNX()函數調用后出現的一些問題, 利用onnxruntime庫已經驗證onnx結果正確。

相關環境

python: 3.7.4
torch: 1.5.0
onnx: 1.10.2
onnxruntime: 1.9.0

一、permute_layer.cpp:138: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size()

出錯原因
opencv版本:4.5.3
在網絡結構中有一層res = xyz.permute(0, 2, 1) # xyz==> (B, N, C)是對三維數據進行維度變換,cv.dnn目前好像不支持。詳細代碼可以參考提的issue#21211
參考#19091說的好像是當前python-opencv會自動把三維輸入的第三維轉換為彩圖的通道數

嘗試解決辦法
考慮先用tensor.view或者tensor.unsqueeze(0)增加一個維度,操作完再用tensor.view或者tensor.squeeze(0)變換為原來的維度。

有興趣的可參考#17272嘗試其他方法

二、Unspecified error: Can't create layer "layer_name" of type "Cast" in function getLayerInstance

出錯原因
opencv版本:4.2.0
不支持Cast算子

解決辦法

  • 升級opencv版本4.3.0以上
  • 自定義算子 參考https://docs.opencv.org/4.x/dc/db1/tutorial_dnn_custom_layers.html

三、Unspecified error: Can't create layer "82" of type "ConstantOfShape" in function 'getLayerInstance'

出錯原因
opencv版本:4.2.0
不支持ConstantOfShape算子

解決辦法

  • 升級opencv版本4.3.0以上
  • 自定義算子 參考https://docs.opencv.org/4.x/dc/db1/tutorial_dnn_custom_layers.html

四、onnx_importer.cpp:2146: error: (-2:Unspecified error)

完整錯誤

cv2.error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-c2l3r8zm\opencv\modules\dnn\src\onnx\onnx_importer.cpp:2146: error: (-2:Unspecified error) in function 'cv::dnn::dnn4_v20210608::ONNXImporter::handleNode'
> Node [ConstantOfShape]:(203) parse error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-c2l3r8zm\opencv\modules\dnn\src\onnx\onnx_importer.cpp:1833: error: (-2:Unspecified error) in function 'void __cdecl cv::dnn::dnn4_v20210608::ONNXImporter::handleNode(const class opencv_onnx::NodeProto &)'
> >  (expected: 'inpShape[i] > 0'), where
> >     'inpShape[i]' is 0
> > must be greater than
> >     '0' is 0
> 

出錯原因
opencv版本:4.5.3
在網絡結構中有一層B, N, C = inputs.shape torch.zeros(B, C, dtype=torch.long, device=device)是根據已有維度B,C生成一個相同維度的全零tensor, cv.dnn調用的時候shape返回的是tensor,在生成的時候本來應該傳入int,這里會導致錯誤。

解決辦法
把維度數加上int(), 強制轉換為int整數。
torch.zeros(int(B), int(C), dtype=torch.long, device=device)

五、Unspecified error: Can't create layer "82" of type "ArgMax" in function 'getLayerInstance'

出錯原因
opencv版本:4.5.3
不支持ArgMax算子

解決辦法

  • 自定義算子 參考https://docs.opencv.org/4.x/dc/db1/tutorial_dnn_custom_layers.html

class ArgMaxLayer(object):
    def __init__(self, params, blobs):
        print("params: ", params)
        self.axis = params["axis"]
        self.dim = None

    # Our layer receives one inputs. We need to find the max
    def getMemoryShapes(self, inputs):
        print("memory shape", inputs)
        out_dim = []
        input_dim = inputs[0]
        for i in range(len(input_dim)):
            if i != self.axis:
                out_dim.append(input_dim[i])
        self.dim = out_dim
        return [out_dim]

    def forward(self, inputs):
        data = inputs[0]
        print("inputs-: ", type(data), data.dtype)
        print("axis: ", self.axis)
        res = np.argmax(data, axis=self.axis)

        # shape = data.shape
        # print("shape: ", shape)
        # res = np.random.randint(0, shape[self.axis], tuple(self.dim), dtype=np.longlong)

        print(res, res.shape, res.dtype)
        return [res.astype(np.float32)]


cv2.dnn_registerLayer('ArgMax', ArgMaxLayer)

六、error: (-215:Assertion failed) pyOutputs[i].size == outputs[i].size in function 'pycvLayer::forward'

我自定義算子時出現過這種情況,首先檢查自定義層中forward函數返回值的維度是否和getMemoryShapes中一致, 則檢查下是否遇到以下巨坑
檢查輸出維度是否為3維,如果是則可以先把輸出(輸入)升維,外部調用獲取結果后再降維

七、error: (-215:Assertion failed) pyOutputs[i].type() == outputs[i].type() in function 'pycvLayer::forward'

我自定義算子時出現過這種情況,自定義層中forward函數返回值類型必須是float32


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM