使用 OpenCV 进行天空分析的图像 [关闭]

Posted

技术标签:

【中文标题】使用 OpenCV 进行天空分析的图像 [关闭]【英文标题】:Image of the sky analysis with OpenCV [closed] 【发布时间】:2016-03-31 11:44:33 【问题描述】:

我正在尝试用我有限的 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 论坛上会有更好的运气 - 这是一个非常广泛的问题,没有一个正确的答案 【参考方案1】:

我认为通过在渐变上使用阈值可以获得更好的结果。您必须为此保留蓝色通道。我不能给你任何代码示例,因为我不知道如何使用 opencv,但是网上一定有大量的示例。

您是否也尝试过将图像转换为灰度?

【讨论】:

在我的代码示例中,我将图像拆分为 BGR 等通道,并且通过蓝红色通道差异获得灰度图像。然后我在这个灰度图像上设置阈值来创建云区域蒙版(事实上,它给出了天空区域,我将它反转)。经过这些步骤,最后我将遮罩放在实际图像上,根据阈值限制显示真实的云区域。啊,除了蓝色的云区域。 :) 好的,谢谢你的解释。我仍然认为你应该使用渐变而不是简单的阈值,它应该在乌云上给出更好的结果。您还可以在计算梯度之前对图像进行低通滤波,以降低噪声水平,从而获得更清晰的结果。 感谢您的关注。但我不明白如何使用作为阈值的成分?问题是,云的某些部分看起来像天空,具有较高的蓝色密度,所以为什么它们不能在算法中作为云通过。

以上是关于使用 OpenCV 进行天空分析的图像 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在 Raspberry PI 上使用 Python 和 OpenCV 进行图像处理 [关闭]

OpenCV-风景—天空滤镜

模仿OpenCV中的“魔杖”photoshop工具

在opencv 3.0中擦除图像的阴影[关闭]

“智能”滑动滑动窗口? [关闭]

使用Numpy和Opencv完成基本图像的数据分析(Part I)