2016-03-31 45 views
3

我試圖用我有限的OpenCV知識從天空圖像(我從相機/視頻獲取)實現雲提取。使用OpenCV進行天空分析的圖像

在下面的代碼示例中,我將圖像拆分爲諸如BGR之類的通道,並通過藍色 - 紅色通道差異獲取灰度圖像。然後,我將閾值放在這個灰度圖像上以創建雲區域遮罩(實際上,它給出了天空區域並將其反轉)。經過這些步驟後,最後我將遮罩放在實際圖像上,根據閾值限制顯示真實的雲區域。它按預期爲白色/灰色雲彩起作用,但不適用於藍色雲彩。

cv::Mat ch[3], img_gray, img_element, img_brdiff; 
img_element = getStructuringElement(MORPH_RECT, Size(6, 6), Point(6, 6)); 
img_brdiff = cv::Mat::zeros(img_frame.size(), CV_8UC3); 
cv::split(img_frame, ch); 
cv::absdiff(ch[2], ch[0], img_brdiff); 
cv::threshold(img_brdiff, img_gray, 35, 255, CV_THRESH_BINARY_INV);  
cv::morphologyEx(img_gray, img_gray, cv::MORPH_CLOSE, img_element); 
//cv::medianBlur(img_gray, img_gray, 3); 
img_frame.copyTo(img_final, img_gray); 
cv::imshow("in", img_frame); 
cv::imshow("out", img_final); 

關於如何提高技術的任何想法?另外,在第二步中,我需要計算每個雲的移動方向。

這是我的圖片樣本。

enter image description here

enter image description here

更新

經過約天空等特點,NBRR(歸藍紅比例),飽和一些額外的檢查,我得到更好的結果,但仍然不是最好的我的意見...擴大示例代碼是在下面。

const int BINARY_TH = 35; 
const double SAT_FIX_TH = 0.3; 
const double NBRR_FIX_TH = 0.4; 

cv::Mat ch[3], img_gray, img_element, img_brdiff; 
img_element = getStructuringElement(MORPH_RECT, Size(6, 6), Point(6, 6)); 
img_brdiff = cv::Mat::zeros(img_frame.size(), CV_8UC3); 
cv::split(img_frame, ch); 
cv::absdiff(ch[2], ch[0], img_brdiff); 
cv::threshold(img_brdiff, img_gray, BINARY_TH, 255, CV_THRESH_BINARY_INV);  
cv::morphologyEx(img_gray, img_gray, cv::MORPH_CLOSE, img_element); 

double r, b, g, nbrr, sat; 
for(int y = 0; y < img_frame.rows; y++) 
{ 
    for(int x = 0; x < img_frame.cols; x++) 
    { 
     b = img_frame.at<Vec3b>(y,x)[0]; 
     g = img_frame.at<Vec3b>(y,x)[1]; 
     r = img_frame.at<Vec3b>(y,x)[2]; 

     nbrr = (b - r)/(b + r); 
     sat = 1.0 - (std::min(b, std::min(g, r))/std::max(b, std::max(g, r))); 

     if(nbrr < NBRR_FIX_TH && 
      sat < SAT_FIX_TH 
      ) 
      img_gray.at<uchar>(y, x) = (uchar)255; 
    } 
} 

cv::medianBlur(img_gray, img_gray, 3); 

img_frame.copyTo(img_final, img_gray); 
cv::imshow("in", img_frame); 
cv::imshow("out", img_final); 
+3

你會有更好的運氣在opencv論壇 - 這是一個非常廣泛的問題,沒有人正確的答案 – chris

回答

0

我想你會有更好的結果通過使用漸變閾值。你必須爲此保留藍色通道。我不能給你任何代碼示例,因爲我不知道如何使用opencv,但必須有大量的在線示例。

你是否試過在灰度中變換圖像?

+0

在我的代碼示例中,我將圖像拆分爲它的渠道,如BGR,我得到灰度圖像由藍紅色通道差異。然後,我將閾值放在這個灰度圖像上以創建雲區域遮罩(實際上,它給出了天空區域並將其反轉)。經過這些步驟後,最後我將遮罩放在實際圖像上,根據閾值限制顯示真實的雲區域。啊,除了藍色的雲區。 :) – rca

+0

好的,謝謝你的解釋。我仍然認爲你應該使用漸變而不是簡單的閾值,它應該給黑雲帶來更好的結果。在計算梯度之前,您還可以對圖像進行低通濾波,以降低噪音水平,從而獲得更清晰的結果。 – Antoine

+0

感謝您的關注。但我不明白如何使用gredient作爲閾值?問題在於,雲的某些部分看起來像天空,藍色密度更高,所以爲什麼它們不能像算法中的雲那樣通過。 – rca