当前位置: 首页 > article >正文

OpenCV实现Kuwahara滤波

Kuwahara滤波是一种非线性的平滑滤波技术,其基本原理在于通过计算图像模板中邻域内的均值和方差,选择图像灰度值较为均匀的区域的均值来替代模板中心像素的灰度值。以下是Kuwahara滤波的详细原理说明:

一、基本思想

Kuwahara滤波的基本思想是基于图像局部区域的均匀性来判断并处理像素值。在图像中,边缘和纹理区域往往灰度值变化较大,而平滑区域则灰度值变化较小。因此,通过计算图像模板中各个子区域的均值和方差,可以选择出灰度值最为均匀的区域,并用该区域的均值来替代模板中心像素的灰度值,从而达到平滑图像的效果,同时保留图像的边缘信息。

二、滤波过程

  1. 定义滤波模板
    • 滤波模板通常是一个正方形区域,其大小可以根据需要进行调整。常见的模板大小有3x3、5x5等。
    • 模板被划分为多个重叠的子区域,每个子区域都包含模板中心像素的一部分邻域。
  2. 计算均值和方差
    • 对于模板中的每一个子区域,计算其灰度值的均值和方差。
    • 均值反映了子区域灰度值的平均水平,而方差则反映了子区域灰度值的波动程度。
  3. 选择均匀区域
    • 比较各个子区域的方差,选择方差最小的子区域作为均匀区域。
    • 由于方差最小的子区域灰度值变化最小,因此可以认为该区域的灰度值最为均匀。
  4. 替代中心像素
    • 用均匀区域的均值替代模板中心像素的灰度值。
    • 这样,模板中心像素的灰度值就被更新为周围最均匀区域的灰度值,从而达到平滑图像的效果。

在这里插入图片描述

上图是一个5x5的kuwahara filter,目标像素的值由这4个黑框包括着的4个area确定,area1~area4 这4个区域中像素点的方差最小的区域是我们的目标区域,方差的计算公式由下面的公式给出,确定目标区域之后,目标像素的值等于目标区域中像素点的平均值。

σ a = 1 ( N − 1 ) ∑ ( i ( x , y ) − μ a ) 2 \sigma_a=\sqrt{\frac{1}{(N-1)}\sum(i(x,y)-\mu_a)^2} σa=(N1)1(i(x,y)μa)2

三、opencv实现

使用opencv计算实现Kuawahara滤波时,为了减小局部均值和标准差的计算量,通常为使用积分图进行加速。实现代码如下:

import cv2 as cv
import numpy as np

def Kuwahara(input, win_size = 3):
    if win_size % 2 == 0:
        raise ValueError("win_size must be odd.")
    half_win_size = win_size // 2
    rows, cols = input.shape
    #计算积分图
    s, sq = cv.integral2(input, sdepth=cv.CV_64F, sqdepth=cv.CV_64F)

    #使用积分图计算win_size x win_size大小窗口的局部均值
    section_sum = s[0:rows - win_size + 1, 0:cols - win_size + 1] + \
                    s[win_size:rows + 1, win_size:cols + 1] - \
                    s[0:rows - win_size + 1, win_size:cols + 1] - \
                    s[win_size:rows + 1, 0:cols - win_size + 1]
    section_mean = section_sum /(win_size * win_size)
    #补边操作
    section_mean = cv.copyMakeBorder(section_mean, half_win_size, half_win_size,
                                     half_win_size, half_win_size,
                                     cv.BORDER_REFLECT)

    #使用积分图计算win_size x win_size大小窗口的局部标准差
    section_sum_sq = sq[0:rows - win_size + 1, 0:cols - win_size + 1] + \
                    sq[win_size:rows + 1, win_size:cols + 1] - \
                    sq[0:rows - win_size + 1, win_size:cols + 1] - \
                    sq[win_size:rows + 1, 0:cols - win_size + 1]
    section_mean_sq = section_sum_sq /(win_size * win_size)
    # 补边操作
    section_mean_sq = cv.copyMakeBorder(section_mean_sq, half_win_size, half_win_size,
                                        half_win_size, half_win_size,cv.BORDER_REFLECT)

    ##方差速算:平方的均值减去均值的平方
    section_var = section_mean_sq - section_mean ** 2

    ##选择最小的方差对应的均值代替中心像素完成滤波
    filter_result = input.copy()
    for r in range(half_win_size, rows - half_win_size):
        for c in range(half_win_size, cols - half_win_size):
            var = [section_var[r - half_win_size, c - half_win_size],
                   section_var[r - half_win_size, c + half_win_size],
                   section_var[r + half_win_size, c - half_win_size],
                   section_var[r + half_win_size, c + half_win_size]]
            mean = [section_mean[r - half_win_size, c - half_win_size],
                   section_mean[r - half_win_size, c + half_win_size],
                   section_mean[r + half_win_size, c - half_win_size],
                   section_mean[r + half_win_size, c + half_win_size]]
            filter_result[r, c] = np.uint8(mean[np.argmin(var)])
    return filter_result


if __name__ == '__main__':
    image = cv.imread("./noise.png", cv.IMREAD_GRAYSCALE)
    result = Kuwahara(image, 7)
    cv.imshow('image', image)
    cv.imshow('kuwa', result)
    result = np.concatenate((image, result), axis=1)
    cv.imwrite('kuwahara2.jpg', result)
    cv.waitKey()

在这里插入图片描述
在这里插入图片描述

四、实际应用

Kuwahara滤波在处理图像时,能够很好地保留图像的边缘信息(强噪声污染的情况下),同时平滑掉图像中的噪声和细节纹理。这使得Kuwahara滤波在图像处理领域具有广泛的应用价值,如图像增强、图像去噪、图像风格化等。
在实际应用中,Kuwahara滤波通常与其他图像处理技术相结合,以达到更好的处理效果。例如,在油画风格化处理中,可以利用Kuwahara滤波来平滑图像并保留边缘信息,从而模拟出油画的特点。此外,在断层特征增强、图像分割等领域,Kuwahara滤波也发挥着重要作用。


http://www.kler.cn/a/502788.html

相关文章:

  • 网络原理(四)—— 网络层、数据链路层 与 DNS
  • 通过外部化 `config.properties` 文件更换数据库配置
  • 【数据可视化-12】数据分析岗位招聘分析
  • MySQL的安装
  • 解决:ubuntu22.04中IsaacGymEnv保存视频报错的问题
  • 大语言模型的稀疏性:提升效率与性能的新方向
  • Redis优化建议详解
  • UE5 使用内置组件进行网格切割
  • 【 PID 算法 】PID 算法基础
  • 云计算的环保性分析:真相与误区
  • 嵌入式岗位面试八股文(篇四 网络编程)
  • 20道Vue.js常见面试题
  • mysql set age=‘0‘ 和 set age=0的区别?
  • 【21天学习AI底层概念】day11 (kaggle新手入门教程)Your First Machine Learning Model
  • qt设置qwidget背景色无效
  • arcgis中用python脚本批量给多个要素类的相同字段赋值
  • HTTP 入门:认识网络通信基础
  • 【WPS】【WORDWORD】【JavaScript】实现微软WORD自动更正的效果
  • Blazor开发复杂信息管理系统的优势
  • 【Linux】编辑器之神vim使用教程
  • 电力场景红外测温图像均压环下的避雷器识别分割数据集labelme格式2436张1类别
  • 8Hive SQL底层执行原理
  • 如何提高自动化测试覆盖率和效率
  • .NET framework、Core和Standard都是什么?
  • Linux IPC:管道与FIFO汇总整理
  • C#,图论与图算法,输出无向图“欧拉路径”的弗勒里(Fleury Algorithm)算法和源程序