Ich versuche mit meinem begrenzten OpenCV-Wissen Wolken aus einem Himmelsbild (welches ich von Kamera/Video erhalte) zu extrahieren.Bild der Himmelsanalyse mit OpenCV
Im folgenden Codebeispiel spalte ich das Bild auf seine Kanäle wie BGR, und ich bekomme Graustufenbild durch blau-roten Kanalunterschied. Dann setze ich den Schwellenwert auf dieses Graustufenbild, um eine Wolkenbereichsmaske zu erstellen (tatsächlich gibt es Himmelsbereiche und ich invertiere sie). Nach diesen Schritten lege ich schließlich die Maske auf das eigentliche Bild, welches die realen Wolkenbereiche gemäß dem Grenzwert zeigt. Es funktioniert wie erwartet für weißliche/gräuliche Wolken, aber nicht für die bläulichen Wolken.
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);
Jede Idee, wie die Technik zu verbessern? In Schritt zwei muss ich auch die Bewegungsrichtung für jede Wolke berechnen.
Hier sind meine Bilder Beispiele.
aktualisieren
Nach einigen zusätzlichen Kontrollen über Himmel Merkmale wie NBRR (Normalized Blau-Rot-Verhältnis), Sättigung, bekam ich bessere Ergebnisse aber noch nicht am besten in meine meinung ... Erweiterter Beispielcode ist unten.
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);
Sie hätten mehr Glück auf dem opencv-Forum - das ist eine sehr breite Frage mit keiner richtigen Antwort – chris