中值滤波_10-中值滤波

理论

边界补零,滤波框长宽为奇数,取框内中值为当前像素的值

C++实践

  • manual
cv::Mat MedianFilterMaunal(const cv::Mat & src, int ksize = 3)
{
    assert((ksize > 0) && (1 == (ksize % 2)) && (!src.empty()));

    cv::Mat dst = cv::Mat::zeros(src.size(), src.type());

    // 确定核中心点
    int origin = floor(ksize / 2);

    // 滤波操作
    for (int y = 0; y < src.rows; ++y)
    {
        for (int x = 0; x < src.cols; ++x)
        {
            for (int c = 0; c < src.channels(); ++c)
            {
                std::vector<uchar> values(ksize * ksize);
                int index = 0;

                for (int dy = -origin; dy < origin + 1; ++dy)
                {
                    for (int dx = -origin; dx < origin + 1; ++dx)
                    {
                        if (((dx + x) >= 0) && ((dy + y) >= 0))
                        {
                            values[index] = src.at<cv::Vec3b>(y + dy, x + dx)[c];
                        }
						++index;
                    }
                }

                std::sort(values.begin(), values.end()); // 升序
                //std::sort(values.begin(), values.end(), std::greater<uchar>()); // 降序
                //std::sort(values.begin(), values.end(), std::less<uchar>());    // 升序
                dst.at<cv::Vec3b>(y, x)[c] = values[std::floor(values.size() / 2) + 1];
            }
        }
    }

    return dst;
}
  • OpenCV
cv::Mat MedianFilterOpenCV(const cv::Mat & src, int ksize)
{
    assert((ksize > 0) && (1 == (ksize % 2)) && (!src.empty()));

    cv::Mat dst = cv::Mat::zeros(src.size(), src.type());

    cv::medianBlur(src, dst, ksize);

    return dst;
}

Python实践

  • manual
def median_filter_manual(src, k_size=3):
    """

    :param src:
    :param k_size:
    :return:
    """
    if len(src.shape) == 2:
        src = np.expand_dims(src, axis=-1)  # 给灰度图增加一个通道

    h, w, c = src.shape

    # 边界补零
    padding = k_size // 2
    dst = np.zeros((h + padding * 2, w + padding * 2, c), dtype=np.float)
    dst[padding: h + padding, padding: w + padding] = src.copy().astype(np.float)

    # 滤波
    for y in range(h):
        for x in range(w):
            for ch in range(c):
                dst[y, x, ch] = np.median(dst[y: y + k_size, x: x + k_size, ch])

    # 剪切
    dst = dst[: h, :w]

    return dst.astype(np.uint8)
  • OpenCV
def median_filter_opencv(src, ksize=3):
    """

    :param src:
    :param ksize:
    :return:
    """
    return cv.medianBlur(src, ksize)

性能及结果

Python的手动实现超级慢

ec517f8411026897aa2f898537ea4446.png

版权声明:本文为weixin_39662594原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。