使用 opencv 手动应用中值滤波器,与 medianBlur 函数的区别

Apply median filter manually with opencv, differences with medianBlur function

当我像这样应用中值过滤器时:

Mat medianFilter;
medianBlur(histEqu, medianFilter, 3);

如果我应用中值过滤器,我希望得到相同的结果:

Mat manualMedianFiler;
    float factor = 1 / 9.0;
    Mat kernelMedian = (Mat_<float>(3, 3) <<
        factor, factor, factor,
        factor, factor, factor,
        factor, factor, factor);
    filter2D(histEqu, manualMedianFiler, CV_8U, kernelMedian, Point(-1,-1), 0, 4);

结果矩阵相似,但不相等。 难道我做错了什么?应用中值滤波器的正确方法是什么?

您的manualMedianFilter不是中值过滤器,而是均值过滤器并且对应于cv::boxFilter

作为对@Miki 回答的补充,我提醒您,中值滤波器是给定 N 个样本(在本例中取自围绕中心像素的 3x3 正方形)对它们的值进行排序并取中间的一个。所以给定 (1, 7, 2, 2, 1, 9, 22, 4, 5) 排序后你得到 (1, 1, 2, 2, 4, 5, 7, 9, 22) 并且中位数是 4,而平均值是 (1 + 7 + 2 + 2 + 1 + 9 + 22 + 4 + 5) / 9 = 53/9 -> 5.8.

简而言之:中值滤波器不是线性的。

在想要去除尖峰的地方首选中值滤波器。

这里有一个简单的例子:

void MedianFilter()
{
    Mat image= imread("C:\Users\User\Desktop\10.jpg", 1);
    Mat image1;
    cvtColor(image, image1, COLOR_BGR2GRAY);
    imshow("testx", image1);
    uchar * data = image1.data;
    vector<int> values;
    for (auto index = 0; index < (image1.rows*image1.cols); index++)
    {
        for (size_t i = 0; i < 13; i++) \ 13 is the element to get the median from...
        {
            values.push_back(data[index + i]);

        }
        std::sort(values.begin(), values.end());

        image1.data[index] = values[6]; // 6 is the median  of 13 plus the index number (0-6) ...
        values.clear();
    }


    imshow("test", image1);
    waitKey(0);
}