2013-07-23 57 views
1

這似乎是一個非常簡單的請求,但我發現問題有點微妙。我只想要X和Y衍生物的8位無符號版本。源圖像也是8位無符號的。使用OpenCV計算X和Y衍生物的絕對值

這裏有一個方法我用:

cv::Mat dx, dy; 
    cv::Sobel(img, dx, CV_16S, 1, 0); 
    cv::Sobel(img, dy, CV_16S, 0, 1); 
    dx = cv::abs(dx); 
    dy = cv::abs(dy); 
    cv::normalize(dx, dx8u, 0x00, 0xFF, cv::NORM_MINMAX, CV_8U); 
    cv::normalize(dy, dy8u, 0x00, 0xFF, cv::NORM_MINMAX, CV_8U); 

我不真正喜歡的是使用normalize功能。這似乎是浪費。如果我嘗試直接將Sobel算子計算爲8位圖像(通過將ddepth設置爲-1),它似乎會「切斷」所有負值。如果我嘗試計算絕對值,然後除以8(將Sobel算子的絕對值映射到[0,255]),它仍然是一個16位圖像,我需要將它轉換爲8位,似乎又浪費了。有沒有更好的方法來做到這一點?

我想的問題的一個重要方面是如何執行16位帶符號的圖像的操作和以某種方式具有直接放入一個8位的圖像的結果。這樣,您就不必在事後再進行額外的轉換。

UPDATE:

下面是最終的解決方案:

cv::Mat dx, dy; 
    cv::Sobel(m, dx, CV_16S, 1, 0); 
    cv::Sobel(m, dy, CV_16S, 0, 1); 
    cv::convertScaleAbs(dx/8, dx); 
    cv::convertScaleAbs(dy/8, dy); 
+0

你的結果是否需要歸一化爲[0,255],還是試圖獲得絕對值的人工產物? – Aurelius

+0

@Aurelius對 - 沒有必要在[0,255]之間,它只是我能找到的使用OpenCV函數接近我想要的唯一方法之一。標準化函數在操作時將類型轉換爲8位,因此在這方面看起來相當高效。 – aardvarkk

回答

4

如果你只需要漸變的絕對值,沒有任何標準化,您可以使用cv::convertScaleAbs()。這將找到絕對值並一次轉換爲8位無符號類型。

cv::Mat dx, dy; 
cv::Sobel(img, dx, CV_16S, 1, 0); 
cv::Sobel(img, dy, CV_16S, 0, 1); 
cv::convertScaleAbs(dx, dx); 
cv::convertScaleAbs(dy, dy); 

注意,此方法僅計算衍生物的絕對值,並將結果不正常化[0, 255]

如果你需要一個標準化的結果,那麼你的發佈代碼似乎是最好的辦法。就您的方法看起來「浪費」而言,確保在考慮「浪費」之前進行多次數據傳遞是演示的性能瓶頸。

不幸的是,OpenCV沒有太多的支持來減少數據傳遞的次數。您可以修改源代碼來執行此操作,或者在真正需要時自行實施Sobel操作。但是,除非是已證實的問題,否則不要擔心。

+0

嗯,我喜歡使用這個功能。值大於+/- 255會發生什麼?他們只是截斷了這個價值? – aardvarkk

+0

其實,爲了得到我想要的東西,我想我可以將原始的16位值除以8,然後調用你的函數。我認爲這會做到這一點。 – aardvarkk

+0

是的,它的工作原理,謝謝!查看我的問題以獲得最終答案。 – aardvarkk