OpenCV兩個Mat相減的隱藏秘密

2021-08-20 14:16:49 字數 2250 閱讀 3588

今天在看同事寫的**時,發現乙個「錯誤」:

他的原意是實現以下功能:

cv::mat absdiff;

cv::absdiff(mat1, mat2, absdiff);

其中mat1mat2均為cv_8uc1型別。

但是可能是一時沒想起這個函式,於是他寫成了這個樣子:

cv::mat absdiff = cv::abs(mat1 - mat2);
於是我認真地告訴他,這樣做是錯的。假設mat1[0]mat2[255],那麼mat1 - mat2將會得到[0],因為cv::saturate_cast(0 - 255) == 0。則cv::abs([0])自然就是[0],而他的期望是得到[255]

並且我寫出如下**證明他是錯的:

cv::mat diff = mat1 - mat;
結果diff確實是[0]。那麼cv::mat absdiff = cv::abs(diff);肯定就是[0]了。

但是他堅持讓我用cv::mat absdiff = cv::abs(mat1 - mat2);測試。結果。。。。absdiff竟然真的是[255]!我當時就震驚了,同時隱隱有一種感覺:這其中一定隱藏著乙個天大的秘密。

於是我進入除錯模式,認真觀察每一步,終於明白了玄機所在。

先來分析我的測試**:

cv::mat diff = mat1 - mat;
在我以前的觀念裡,mat1 - mat是兩個cv::mat互相作用,實際上呼叫的是cv::subtract()。但是事實上,mat1 - mat2呼叫的是以下函式:

cv_exports matexpr operator - (const mat& a, const mat& b);

matexpr operator - (const mat& a, const mat& b)

可以看到,mat1 - mat2實際上是生成了乙個matexpr物件。在生成過程中,並沒有進行實際的相減操作,而只是儲存了ab,並記錄了它們之間期望進行的操作:相減。實際的相減操作是在型別轉換時進行的:

//cv::mat diff = mat1 - mat; // 在這裡呼叫了operator mat()

matexpr::operator mat() const

assign中最終呼叫了cv::subtract()。所以mat1 - mat2得到了[0]

再來分析我同事的測試**:

cv::mat absdiff = cv::abs(mat1 - mat2);
從上面我們知道,mat1 - mat2生成了乙個matexpr物件。而cv::abs()呼叫的是

matexpr abs(const matexpr& e)

這個函式再次生成了乙個matexpr物件,其中記錄了操作物件e和期望進行的操作:取絕對值,而並沒有進行實際的運算。然後同上面一樣,它是在賦值給absdiff時呼叫operator mat()進行運算的。神奇的地方來了,它把前面的相減操作與這裡的取絕對值操作組合到了一起(而不是依次運算),最終呼叫的正是cv::absdiff()

於是謎底揭開了,一切的原因都是因為matexpr這個中間物件實現了延遲運算和操作組合。

我還是太年輕!

兩個指標相減

原文 如果兩個指標指向同乙個陣列,它們就可以相減,其結果為兩個指標之間的元素數目。假設我住在廣場路124號,mag住在廣場路142號,每家之間的位址間距是2 在我這一側用連續的偶數作為街道位址 那麼mag家就在我家往前 142 124 2家,也就是說可以得到我們兩家之間相隔8家。也就是說可以利用兩個...

oracle 兩個時間相減

oracle兩個時間相減預設的是天數 oracle 兩個時間相減預設的是天數 24 為相差的小時數 oracle 兩個時間相減預設的是天數 24 60 為相差的分鐘數 oracle 兩個時間相減預設的是天數 24 60 60 為相差的秒數 months between date2,date1 給出d...

oracle 兩個時間相減

oracle兩個時間相減預設的是天數 oracle 兩個時間相減預設的是天數 24 為相差的小時數 oracle 兩個時間相減預設的是天數 24 60 為相差的分鐘數 oracle 兩個時間相減預設的是天數 24 60 60 為相差的秒數 months between date2,date1 給出d...