今天在看同事寫的**時,發現乙個「錯誤」:
他的原意是實現以下功能:
cv::mat absdiff;
cv::absdiff(mat1, mat2, absdiff);
其中mat1
和mat2
均為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
物件。在生成過程中,並沒有進行實際的相減操作,而只是儲存了a
和b
,並記錄了它們之間期望進行的操作:相減。實際的相減操作是在型別轉換時進行的:
//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...