OpenCV均值/ SD滤波器

时间:2012-07-12 16:40:32

标签: opencv filter image-segmentation standard-deviation

我把它扔到那里,希望有人会尝试过这种荒谬的事情。我的目标是接收输入图像,并根据每个像素周围的小窗口的标准偏差对其进行分割。基本上,这应该在数学上类似于高斯或盒式滤波器,因为它将应用于围绕每个像素的编译时(或甚至运行时)用户指定的窗口大小,并且目标阵列将包含每个像素处的SD信息,在与原始图像大小相同的图像中。

我们的想法是在HSV空间中的图像上执行此操作,以便我可以轻松找到均匀颜色的区域(即在Hue和Sat平面中具有小的局部SD的区域)并从图像中提取它们以获得更多 - 深度处理。

所以问题是,有没有人曾经建立过这样的自定义过滤器?我不知道如何在一个简单的盒式滤波器内核中使用SD,就像用于高斯和模糊的那样,所以我猜我必须使用FilterEngine结构。另外,我忘了提到我在C ++中这样做。

非常感谢您的建议和思考。

2 个答案:

答案 0 :(得分:32)

维基百科对standard deviation有一个很好的解释,您可以使用它来进行标准偏差过滤。

基本上,它归结为用盒式滤镜模糊图像,用盒式滤镜模糊图像的方形,并取其差异的平方根。

更新:这可能会更好地显示来自维基百科的等式...... enter image description here

您可以将OpenCV blur函数视为代表感兴趣邻域的expected value(即E [X] a.k.a.样本均值)。在这种情况下,随机样本X由局部邻域中的图像像素表示。因此,通过使用上述等价,我们在OpenCV中有sqrt(blur(img^2) - blur(img)^2)之类的东西。这样做可以计算出局部均值和标准偏差。

另外,万一你好奇数学证明。这种等价称为computational formula for variance

以下是在OpenCV中执行此操作的方法:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

Mat mat2gray(const Mat& src)
{
    Mat dst;
    normalize(src, dst, 0.0, 1.0, NORM_MINMAX);
    return dst;
}

int main()
{
    Mat image = imread("coke-can.jpg", 0);

    Mat image32f;
    image.convertTo(image32f, CV_32F);

    Mat mu;
    blur(image32f, mu, Size(3, 3));

    Mat mu2;
    blur(image32f.mul(image32f), mu2, Size(3, 3));

    Mat sigma;
    cv::sqrt(mu2 - mu.mul(mu), sigma);

    imshow("coke", mat2gray(image32f));
    imshow("mu", mat2gray(mu));
    imshow("sigma",mat2gray(sigma));
    waitKey();
    return 0;
}

这会产生以下图像:

原始

enter image description here

平均数

enter image description here

标准偏差

enter image description here

希望有所帮助!

答案 1 :(得分:0)

如果您想以更通用的方式使用它,可以产生nan值

接近零的值有时可能是“负”。

Mat sigma;
cv::sqrt(mu2 - mu.mul(mu), sigma);

正确的方法应该

Mat sigma;
cv::sqrt(cv::abs(mu2 - mu.mul(mu)), sigma);