我試圖用我有限的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);
關於如何提高技術的任何想法?另外,在第二步中,我需要計算每個雲的移動方向。
這是我的圖片樣本。
更新
經過約天空等特點,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);
你會有更好的運氣在opencv論壇 - 這是一個非常廣泛的問題,沒有人正確的答案 – chris