opencv的Mat結構裡需要注意的細節

2021-10-19 12:54:46 字數 1484 閱讀 2533

在使用opencv的dnn模組做深度學習時,經常會遇到乙個疑惑。疑惑是這樣的:用c++編寫的程式,當執行完outs = net.forward()之後,如果outs裡有mat的維數大於2,那麼設斷點除錯的時候,可以看到rows和cols都等於-1,以目標檢測為例,輸出outs裡包含box和score,斷點除錯檢視out_score的資訊如下:

但是最後看程式執行的視覺化結果,是沒問題的。這個疑惑,在opencv原始碼裡可以找到解釋,在mat.hpp檔案,第2559行至2561行,中間的注釋裡說:當矩陣的維數大於2時,rows和columns的值為-1

首先分析,out_score的形狀,如果是基於pytorch框架做目標檢測,那麼它的形狀是(batchsize, num_proposal, num_class)。在使用opencv的dnn模組做深度學習目標檢測時,通常是輸入一張到神經網路裡做前向計算的,因此batchsize這個維度是多餘的。想要避免出現rows和cols都等於-1這種情況,在生成onnx檔案之前,新增對輸出張量的消除batchsize維度的處理,這個在pytorch裡有現成的函式squeeze()滿足這個需求。假如沒有新增這個步驟,那麼在opencv裡也有解決辦法。使用opencv的reshape函式就能達到pytorch或者numpy裡的squeeze()函式消除維數是1的那個維度,示例**:  out_score = out_score.reshape(0, num_proposal);     num_proposal是二維矩陣的行數

之所以需要消除維數是1的那個維度,是因為在接下來計算每乙個proposal的最大類別置信度(也就是求out_score的每一行的最大值)時,可以使用opencv提供的minmaxloc函式來完成,而在呼叫這個函式之前需要提取out_score的一行,示例**: mat scores = out_score.row(idx).colrange(0, num_class);  這時如果out_sxcore的dims大於2,程式就會報錯,因而需要在此之前消除維數是1的維度。呼叫opencv現成函式來求最大類別置信度,這樣就不需要自己手動編寫for迴圈了。當然,如果你自己手動編寫for迴圈求最大類別置信度,那麼前面out_score的dims是否大於2就無關緊要了,這時也就不要消除維數是1的維度。

上面講述的是編寫c++程式呼叫opencv的dnn模組做深度學習時的乙個bug,但是編寫python程式呼叫opencv的dnn模組做深度學習時就不會出現這個問題,因為在python程式裡,當執行完outs = net.forward()之後,返回的是numpy.array這種資料結構,這是與c++程式的乙個區別。

不過,在c++程式裡,當mat的dims>2時,想要訪問mat的高和寬,可以通過size屬性獲取,例如上面的out_score,在程式裡新增   cout就可以列印出out_socre的維度資訊了。

opencv中的Mat結構操作

從檔案中讀入一副影象 mat img imread filename 如果你讀入乙個jpg檔案,預設情況下將建立乙個3通道影象。如果你需要灰度 單通道 影象,使用如下語句 mat img imread filename,0 將影象儲存到乙個檔案 mat img imwrite filename 要獲...

再談OpenCV資料結構Mat詳解

我記得開始接觸opencv就是因為乙個演算法裡面需要2維動態陣列,那時候看core這部分也算是走馬觀花吧,隨著使用的增多,對mat這個結構越來越喜愛,也覺得有必要溫故而知新,於是這次再看看mat。mat最大的優勢跟stl很相似,都是對記憶體進行動態的管理,不需要之前使用者手動的管理記憶體,對於一些大...

opencv中的Mat詳解

1.初始化 mat the basic image container 最最基本的函式,所有在opencv中都是用mat形式來操作的。初始化乙個mat mat a,c a imread ar 1 imread color mat b a 複製a給b c a 賦值運算 mat d a,rect 10,...