一种新颖的保边滤波——Sub Window Filtering

本文介绍了2019年CVPR会议上的一篇关于图像滤波的论文,提出了一种名为SideWindowFilter的新方法。传统滤波器在处理边缘像素时可能导致模糊,而SideWindowFilter通过调整滤波窗口边缘与像素点对齐,实现了保边滤波。论文详细比较了BoxFilter和SideWindowBoxFilter在处理阶梯状、斜坡状和屋顶状边缘的效果,并提供了实验证明。通过C++和OpenCV实现的代码展示了该算法如何增强均值滤波的效果。

分享2019 CVPR的一篇图像滤波算法论文。这个算法的新颖之处在于:不管传统的滤波器保不保边,运用了Side Window后都可以保边。

基本思路

经典滤波算法基本都是:以某个像素点为中心,按照滤波半径,把这个包括像素点和其邻域加权线性组合得到输出,一般公式如下:
在这里插入图片描述
Ω是以像素点 i 为中心的滤波窗口,w是滤波权值,q是原图像素值,I’是输出结果。但是这样以一个像素为中心去滤波会导致的问题是,如果一个像素点处在边缘位置(这里的边缘不是指图片的大小边界,而是指图像中物体的边缘)的话,以像素为中心去滤波会导致滤波结果的边缘部分变模糊。
论文中为了分析方便讨论了三种典型的边缘,分别是图中的 (a)阶梯状边缘、(b)斜坡状边缘和©屋顶状边缘。
在这里插入图片描述

根据泰勒展开公式分析,得出结论:如果一个像素点处于图像中的边缘位置,那么滤波的时候就应该把滤波器的边缘和该像素点对齐,而不是把滤波器的中心和该像素点对齐。受此启发,论文作者提出了一个新的保边滤波策略:就是把每个滤波像素点都当成是潜在的边缘点,然后对于每个待滤波的像素点,生成几种不同的滤波子窗口,然后把这些滤波窗口的边缘或者角点位置和该像素点对齐,然后滤波得到结果,最后根据把这些子窗口的滤波之后的最佳重构结果作为最终的滤波结果。
文中提出了8个方向的滤波窗口,分别是上、下,左、右、左上、右上、左下和右下
在这里插入图片描述

side window filter 的核心算法流程如下:
在这里插入图片描述

论文中又详细分析了 box filter 和 side window box filter 对于上面提到的三种经典边缘的滤波之后的保留情况。文中给出分析的图表如下:
在这里插入图片描述

论文中的一些效果图
在这里插入图片描述

代码实现

用C++和OpenCV实现Sub WIndow Filter 与均值滤波的结合算法。对下图进行滤波
在这里插入图片描述
迭代十次的均值滤波
在这里插入图片描述
迭代十次,加了Sub Window Filtering 的均值滤波在这里插入图片描述

需要源代码的,请关注+点赞+留言。

import cv2 as cv import numpy as np from PIL import Image import matplotlib.pyplot as plt # 读取图像并转为灰度图 logo = cv.imread('SAI3.png') gray_image = cv.cvtColor(logo, cv.COLOR_BGR2GRAY) # 展示原始灰度图 plt.figure(figsize=(8,6)) plt.title("Grayscale Image") plt.imshow(gray_image, cmap='gray') plt.axis('off') # 关闭坐标轴 plt.show() def max_filtering(N, image1): """自定义最大值滤波实现(填充边界)""" pad_size = N // 2 # 创建带填充的边界(填充值为-1) wall = np.full((image1.shape[0]+2*pad_size, image1.shape[1]+2*pad_size), -1) wall[pad_size:pad_size+image1.shape[0], pad_size:pad_size+image1.shape[1]] = image1.copy() temp = np.full(wall.shape, -1) for y in range(pad_size, wall.shape[0]-pad_size): for x in range(pad_size, wall.shape[1]-pad_size): window = wall[y-pad_size:y+pad_size+1, x-pad_size:x+pad_size+1] temp[y,x] = np.amax(window) return temp[pad_size:-pad_size, pad_size:-pad_size] def min_filtering(N, image1): """自定义最小值滤波实现(填充边界)""" pad_size = N // 2 # 创建带填充的边界(填充值为300,高于灰度图最大值255) wall_min = np.full((image1.shape[0]+2*pad_size, image1.shape[1]+2*pad_size), 300) wall_min[pad_size:pad_size+image1.shape[0], pad_size:pad_size+image1.shape[1]] = image1.copy() temp_min = np.full(wall_min.shape, 300) for y in range(pad_size, wall_min.shape[0]-pad_size): for x in range(pad_size, wall_min.shape[1]-pad_size): window_min = wall_min[y-pad_size:y+pad_size+1, x-pad_size:x+pad_size+1] temp_min[y,x] = np.amin(window_min) return temp_min[pad_size:-pad_size, pad_size:-pad_size] def background_subtraction(image1, image2): """计算两幅图像差异并归一化""" sub_img = image1 - image2 norm_img = cv.normalize(sub_img, None, 0, 255, norm_type=cv.NORM_MINMAX) return norm_img # 设置滤波器大小 N =35 # 示例使用3x3窗口 # 应用最大值滤波和最小值滤波 max_img = max_filtering(N, gray_image) min_img = min_filtering(N, max_img) # 背景减除处理 r = background_subtraction(gray_image, min_img) # 展示处理后的二值图像 plt.figure(figsize=(8,6)) plt.title("Background Subtraction Result") plt.imshow(r, cmap='binary') plt.axis('off') # 关闭坐标轴 plt.show() # 保存处理后的二值图像 plt.imsave('result_binary.png', r, cmap='binary') 将以上代码改为matlab代码
最新发布
05-29
<think>好的,我现在需要将用户提供的Python图像处理代码转换为MATLAB代码。首先,我要仔细阅读和理解原始代码的功能,然后逐步将其转换为MATLAB的语法和函数。 首先,原始代码的主要步骤包括:1.读取图像并转换为灰度图。2.应用最大值滤波和最小值滤波处理。3.进行背景减除并归一化。4.显示和保存结果图像。接下来,我需要分析每个步骤在Python中使用的函数,并找到MATLAB中的对应方法。**1.读取图像并转为灰度图:**Python中使用的是OpenCV的cv.imread和cv.cvtColor。在MATLAB中,可以使用imread直接读取图像,而灰度转换可以使用rgb2gray函数,前提是图像是RGB格式。需要注意的是,如果图像本身就是灰度图,imread会直接读取为二维矩阵,无需转换。但为了保险起见,可以检查图像通道数。**2.最大值和最小值滤波的实现:** Python中的自定义滤波函数使用numpy进行数组操作,包括边界填充和滑动窗口处理。MATLAB中,处理图像矩阵的方式类似,但语法不同。例如,填充边界可以使用padarray函数,设置填充值为-1或300。然后,使用嵌套循环遍历每个像素,提取邻域窗口并计算最大值或最小值。需要注意的是,MATLAB的数组索引是从1开始的,而Python是从0开始,这会影响循环的起始和结束位置。 **3.背景减除和归一化:** Python中使用的是普通的矩阵减法,然后使用OpenCV的normalize函数进行归一化。MATLAB中可以直接进行矩阵相减,归一化可以使用mat2gray函数,将数据缩放到[0,1]范围,再乘以255得到uint8类型。 **4.显示和保存图像:** Python中使用matplotlib进行显示,而MATLAB可以使用imshow和figure等函数。保存图像可以使用imwrite,注意调整数据类型和范围。接下来,我需要处理每个函数的转换细节:**最大值滤波函数max_filtering:** -在Python中,填充数组为-1,然后对每个像素周围的NxN窗口取最大值。MATLAB中,padarray的填充选项需要正确设置,例如用'both'填充左右上下。循环变量y和x的起始和结束位置需要调整,因为MATLAB数组索引从1开始。例如,原始代码中的pad_size是N//2,假设N是奇数。在MATLAB中,同样计算pad_size为floor(N/2)。循环从pad_size+1到图像尺寸减去pad_size。 **最小值滤波函数min_filtering:**-类似最大值滤波,但填充值为300(高于255),然后取邻域最小值。在MATLAB中,同样使用padarray填充,循环处理每个像素。 **背景减除函数:** -直接相减后归一化。MATLAB中使用mat2gray自动归一化到[0,1],再乘以255转换为uint8。 **显示和保存:** -MATLAB的imshow默认显示灰度图像,二值图像可以使用colormap('binary')。保存时注意数据类型,例如使用imwrite将uint8矩阵保存为PNG。可能的注意事项: -MATLAB的矩阵存储顺序是列优先,而Python是行优先,但在图像处理中通常不会影响,因为像素是按行列处理的。-数据类型转换,例如在Python中使用的是numpy数组,而MATLAB中是double或uint8矩阵,需要注意运算时的类型转换,避免溢出。 -循环效率:MATLAB的循环在处理大图像时可能较慢,但考虑到用户提供的代码是自定义滤波,无法使用内置函数,因此只能使用循环实现。现在,我需要将这些步骤逐步转换为MATLAB代码,并测试每个部分是否正确。例如,填充边界、循环范围是否正确,以及归一化处理是否合适。同时,确保显示和保存的图像与Python代码的结果一致。</think>以下是转换后的MATLAB代码及详细解释: ```matlab % 读取图像并转为灰度图 logo = imread('SAI3.png'); if size(logo,3) == 3 gray_image = rgb2gray(logo); else gray_image = logo; end % 展示原始灰度图 figure; imshow(gray_image); title('Grayscale Image'); axis off; % 最大值滤波函数 function max_img = max_filtering(N, image1) pad_size = floor(N/2); % 创建带填充的边界(填充值为-1) wall = padarray(image1, [pad_size pad_size], -1, 'both'); temp = -ones(size(wall)); [rows, cols] = size(wall); for y = pad_size+1 : rows-pad_size for x = pad_size+1 : cols-pad_size window = wall(y-pad_size:y+pad_size, x-pad_size:x+pad_size); temp(y,x) = max(window(:)); end end max_img = temp(pad_size+1:end-pad_size, pad_size+1:end-pad_size); end % 最小值滤波函数 function min_img = min_filtering(N, image1) pad_size = floor(N/2); % 创建带填充的边界(填充值为300) wall_min = padarray(image1, [pad_size pad_size], 300, 'both'); temp_min = 300*ones(size(wall_min)); [rows, cols] = size(wall_min); for y = pad_size+1 : rows-pad_size for x = pad_size+1 : cols-pad_size window_min = wall_min(y-pad_size:y+pad_size, x-pad_size:x+pad_size); temp_min(y,x) = min(window_min(:)); end end min_img = temp_min(pad_size+1:end-pad_size, pad_size+1:end-pad_size); end % 主程序 N = 35; % 滤波器大小 % 应用最大值滤波和最小值滤波 max_img = max_filtering(N, gray_image); min_img = min_filtering(N, max_img); % 背景减除处理 sub_img = double(gray_image) - double(min_img); norm_img = mat2gray(sub_img); % 自动归一化到[0,1] norm_img = uint8(norm_img * 255); % 转换为uint8 % 展示处理后的二值图像 figure; imshow(norm_img, 'Colormap', gray(2)); title('Background Subtraction Result'); axis off; % 保存处理后的二值图像 imwrite(norm_img, 'result_binary.png'); ``` **代码解释:** 1. **图像读取与灰度转换:** - 使用`imread`读取图像后,通过检查第三个维度判断是否需要转换为灰度图 - `rgb2gray`用于RGB图像的灰度转换 2. **最大值滤波实现:** - `padarray`函数实现边界填充,'both'表示两侧填充 - 双循环遍历每个像素点,`y-pad_size:y+pad_size`获取邻域窗口 - `max(window(:))`获取窗口最大值 3. **最小值滤波实现:** - 填充值为300(超过灰度值范围) - `min(window_min(:))`获取窗口最小值 4. **背景减除处理:** - `double()`转换确保运算精度 - `mat2gray`自动执行归一化到[0,1]范围 - 转换为uint8类型以匹配图像格式要求 5. **结果显示与保存:** - `imshow`的'Colormap'参数设置为gray(2)实现二值显示效果 - `imwrite`直接保存处理结果
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值