2014-03-25 76 views
3

我有什麼應該是一個簡單的OpenCV練習,但似乎無法讓它工作。我試圖確定圖像的一部分邊緣的密度。這是我遵循的過程: 1.從圖像中拉取子圖像 2.使用Canny在子圖像中查找邊緣 3.用於創建二值圖像的閾值 4.爲二值圖像創建直方圖 5.獲取二值圖像中的像素數(255) 6.計算「邊緣密度」爲numPixelsOn/totalPixels從OpenCV直方圖獲取值

我檢查了上述1,2和3的結果,並且結果看起來不錯。步驟4和5似乎給我帶來麻煩。

這裏是我的計算直方圖代碼:

 int histSize = 256; // bin size 
     float range[] = { 0, 256} ; 
     const float* histRange = { range }; 

     bool uniform = true; 
     bool accumulate = false; 

     Mat hist; 

     /// Compute the histograms: 
     calcHist(&gray, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate); 

這似乎並不奏效。當我調用calcHist後檢查hist時,它沒有數據(即數據== 0)...或者我不明白我在看什麼。

現在爲了訪問直方圖中的「容器」,我嘗試了一些東西。首先,我想這:

uchar* p; 
    p = hist.ptr<uchar>(0); 
    double edgePixels = p[255]; 

我還試圖用:

cvQueryHistValue_1D(hist,255); // #include <opencv2/legacy/compat.hpp> 

這不會編譯。給出2個錯誤:'cv :: Mat'沒有重載成員'operator - >'和'bin':不是'cv :: Mat'的成員

我想我需要一些幫助。

+0

爲什麼你需要一個直方圖?是不是更容易只是遍歷梯度圖像或只是使用sum(I)/ 255來獲取像素數目?最後,使用Canny並不是一個好主意,因爲它非常非線性,因此重複性差。最好使用簡單的Sobel求和sqrt(hor_grad^2 + ver_grad^2)來獲得更好的邊緣度量。 – Vlad

+0

@Vlad - 感謝您的建議。雖然我很欣賞在直方圖上獲得幫助,但您的意見是有道理的。我不完全理解你對如何使用Sobel獲得更好的「邊緣」度量的評論。你是否建議我簡單地使用cv :: Sobel函數而不是cv :: Canny?再次感謝! –

+0

我建議您使用絕對值(平方和的平方或平方)作爲絕對梯度的估計值。它比Canny更快更穩定。後者執行大量的非線性操作,因此如果您需要這些屬性,則不是很好的重複性和匹配性。另一方面,即使對於弱連續邊緣也是敏感的。 – Vlad

回答

4

。在你的第三個參數的錯誤 - 渠道,這應該是一個數組,所以你應該稱呼它

int histSize = 256; // bin size 
float range[] = { 0, 256} ; 
const float* histRange = { range }; 

bool uniform = true; 
bool accumulate = false; 

Mat hist; 

int channels[] = {0}; 

/// Compute the histograms: 
calcHist(&gray, 1, channels, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate); 

你也應該叫:

hist.at<float>(0); 

讓你的價值,OpenCV將它們作爲浮點數存儲,這就是使用uchar時爲0的原因,因爲uchar小於浮點數,並且數字存儲量足夠小以至於無法填充第一個點。

+0

謝謝!完美檢查出來。 –