我把它扔到那里,希望有人会尝试过这种荒谬的事情。我的目标是接收输入图像,并根据每个像素周围的小窗口的标准偏差对其进行分割。基本上,这应该在数学上类似于高斯或盒式滤波器,因为它将应用于围绕每个像素的编译时(或甚至运行时)用户指定的窗口大小,并且目标阵列将包含每个像素处的SD信息,在与原始图像大小相同的图像中。
我们的想法是在HSV空间中的图像上执行此操作,以便我可以轻松找到均匀颜色的区域(即在Hue和Sat平面中具有小的局部SD的区域)并从图像中提取它们以获得更多 - 深度处理。
所以问题是,有没有人曾经建立过这样的自定义过滤器?我不知道如何在一个简单的盒式滤波器内核中使用SD,就像用于高斯和模糊的那样,所以我猜我必须使用FilterEngine结构。另外,我忘了提到我在C ++中这样做。
非常感谢您的建议和思考。
答案 0 :(得分:32)
维基百科对standard deviation有一个很好的解释,您可以使用它来进行标准偏差过滤。
基本上,它归结为用盒式滤镜模糊图像,用盒式滤镜模糊图像的方形,并取其差异的平方根。
更新:这可能会更好地显示来自维基百科的等式......
您可以将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;
}
这会产生以下图像:
希望有所帮助!
答案 1 :(得分:0)
如果您想以更通用的方式使用它,可以产生nan值
接近零的值有时可能是“负”。
Mat sigma;
cv::sqrt(mu2 - mu.mul(mu), sigma);
正确的方法应该
Mat sigma;
cv::sqrt(cv::abs(mu2 - mu.mul(mu)), sigma);