16

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

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

所以问题是,以前有没有人构建过这样的自定义过滤器?我不知道如何在一个简单的盒型过滤器内核中进行 SD,例如用于高斯和模糊的过滤器内核,所以我猜我将不得不使用 FilterEngine 构造。另外,我忘了提到我是用 C++ 做的。

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

4

2 回答 2

46

维基百科对标准偏差有一个很好的解释,您可以将其用于标准偏差过滤器。

基本上,它归结为使用盒式过滤器模糊图像,使用盒式过滤器模糊图像的正方形,并取它们差异的平方根。

更新:这可能用维基百科的等式更好地显示...... 在此处输入图像描述

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

另外,以防万一您对数学证明感到好奇。这种等价性称为方差的计算公式

以下是如何在 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;
}

这会产生以下图像:

原来的

在此处输入图像描述

意思是

在此处输入图像描述

标准差

在此处输入图像描述

希望有帮助!

于 2012-07-12T20:16:04.343 回答
0

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

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

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

正确的方法应该是

Mat sigma;
cv::sqrt(cv::abs(mu2 - mu.mul(mu)), sigma);
于 2020-12-10T20:38:45.030 回答