2015-05-11 184 views
8
// 700 ms 
cv::Mat in(height,width,CV_8UC1); 
in /= 4; 

(opencv rc1)Mat乘法的運算速度比每像素乘法慢20倍?

//40 ms 
cv::Mat in(height,width,CV_8UC1); 
for (int y=0; y < in.rows; ++y) 
{ 
    unsigned char* ptr = in.data + y*in.step1(); 
    for (int x=0; x < in.cols; ++x) 
    { 
     ptr[x] /= 4; 
    } 
} 

替換哪些原因會導致這樣的行爲?是否由於opencv將Mat的「標量乘法」提升爲Mat乘法的Mat,還是因爲arm的特定失敗優化? (NEON已啓用)。

+0

你可以試試* = 1.0f/4.0; ?你沒有初始化元素btw – Micka

+0

浮點乘法的結果與我的測試中對整像素乘法和整像素乘法的整數除法與大約20%的不確定性/差異相同。 –

+0

你可以運行perf嗎? https://perf.wiki.kernel.org/index.php/Main_Page – auselen

回答

1

通過測量CPU時間嘗試相同。

int main() 
{ 
    clock_t startTime; 
    clock_t endTime; 

    int height =1024; 
    int width =1024; 

    // 700 ms 
    cv::Mat in(height,width,CV_8UC1, cv::Scalar(255)); 
    std::cout << "value: " << (int)in.at<unsigned char>(0,0) << std::endl; 

    cv::Mat out(height,width,CV_8UC1); 

    startTime = clock(); 
    out = in/4; 
    endTime = clock(); 
    std::cout << "1: " << (float)(endTime-startTime)/(float)CLOCKS_PER_SEC << std::endl; 
    std::cout << "value: " << (int)out.at<unsigned char>(0,0) << std::endl; 


    startTime = clock(); 
    in /= 4; 
    endTime = clock(); 
    std::cout << "2: " << (float)(endTime-startTime)/(float)CLOCKS_PER_SEC << std::endl; 
    std::cout << "value: " << (int)in.at<unsigned char>(0,0) << std::endl; 

    //40 ms 
    cv::Mat in2(height,width,CV_8UC1, cv::Scalar(255)); 

    startTime = clock(); 
    for (int y=0; y < in2.rows; ++y) 
    { 
     //unsigned char* ptr = in2.data + y*in2.step1(); 
     unsigned char* ptr = in2.ptr(y); 
     for (int x=0; x < in2.cols; ++x) 
     { 
      ptr[x] /= 4; 
     } 
    } 
    std::cout << "value: " << (int)in2.at<unsigned char>(0,0) << std::endl; 

    endTime = clock(); 
    std::cout << "3: " << (float)(endTime-startTime)/(float)CLOCKS_PER_SEC << std::endl; 


    cv::namedWindow("..."); 
    cv::waitKey(0); 
} 

與結果:

value: 255 
1: 0.016 
value: 64 
2: 0.016 
value: 64 
3: 0.003 
value: 63 

你看到的結果不同,可能是因爲mat.divide()不執行浮點除法和舍入到下一個。雖然在更快的版本中使用整數除法,但速度更快但結果不同。

另外,在openCV計算中有一個saturate_cast,但我猜計算負載差別較大的是雙精度分割。

+0

你能添加4:乘以每個元素0.25嗎? IIRC對我來說也是「快速」,表明其他事情正在發生,而不僅僅是觸發器/頂點計算性能。我的機器上的 –

+0

,浮點乘法/除法是無符號char除以4的時間的2倍(這是一個位移btw)。由double加倍和float一樣,我不信任atm :) – Micka

2

這是一個很老的問題(我幾年前曾報道過)很多基本操作都花費了額外的時間。不僅僅是除法,還有加法,abs等等......我不知道這種行爲的真正原因。更奇怪的是,應該花費更多時間的操作,如addWeighted,實際上非常有效。試試這個:

addWeighted(in, 1.0/4, in, 0, 0, in); 

它執行多個操作每個像素,但它運行幾次比任何添加功能和循環實施。

這是我的report錯誤跟蹤器。

+0

對於我的setup和opencv版本來說,addWeighted相當慢,這是另一個問題。 –

+0

這甚至是更奇怪的,因爲我剛剛檢查過,看到addWeighted快得多。你使用的是什麼版本的OpenCV? –

+0

你也可以做一些其他功能的相同的實驗嗎?例如abs()。 –