如何计算适配skimage.view_as_windows函数的图像目标尺寸?
解决方法:计算适配
view_as_windows的图像目标尺寸 我来帮你梳理通用的计算逻辑,不管步长s是不是等于窗口边长p,都能算出需要调整到的目标图像尺寸。
核心思路与公式
skimage.view_as_windows要求滑动窗口时,最后一个窗口的结束位置不能超出图像边界。换句话说,对于图像的每个维度(高度/宽度),必须满足:
目标维度
D减去窗口大小w后,结果是步长s的非负整数倍,且D >= w
基于这个要求,我们可以推导出通用的目标维度计算公式:
# 对单个维度d(原高度/宽度),窗口大小w,步长s import math if d < w: # 原维度比窗口小,直接扩展到窗口大小 D = w else: # 计算(d - w)需要向上取整到s的倍数,再加窗口大小 num_required_steps = math.ceil((d - w) / s) D = w + num_required_steps * s
或者用更简洁的整数除法写法(等价于向上取整):
D = w + ((d - w + s - 1) // s) * s
公式推导说明
我们的目标是找到大于等于原维度d的最小D,让(D - w)能被s整除:
- 如果原维度
d本身就满足条件(d >=w且(d-w)%s ==0),直接用d即可; - 如果
d <w,必须扩展到w——否则窗口都无法完整放入图像; - 如果
d >=w但(d-w)不是s的倍数,需要补充s - ((d -w) % s)个像素,让(D -w)刚好是s的整数倍。
完整代码实现
这里推荐用np.pad代替img.resize——因为resize会拉伸/压缩像素改变原图内容,而pad只是在边缘补充像素(比如零、镜像),更符合滑动窗口的需求:
import math import numpy as np from skimage.util import view_as_windows def adjust_image_for_windows(img, window_size, step): # 处理单通道/多通道图像的shape if len(img.shape) == 3: height, width, depth = img.shape else: height, width = img.shape depth = None w = window_size s = step # 计算目标高度和宽度 target_h = w + ((height - w + s - 1) // s) * s target_w = w + ((width - w + s - 1) // s) * s # 计算需要补充的像素数,执行补边 pad_h = target_h - height pad_w = target_w - width if pad_h > 0 or pad_w > 0: pad_config = ((0, pad_h), (0, pad_w)) if depth is not None: pad_config += ((0, 0),) # 这里用constant补零,你可以换成reflect/symmetric等补边模式 img_adjusted = np.pad(img, pad_config, mode='constant') return img_adjusted else: return img # 测试你的两个示例 # 示例1:(5,5)图像,window(4,4),step=2 img1 = np.random.rand(5,5) adjusted1 = adjust_image_for_windows(img1, 4, 2) print(f"示例1调整后尺寸:{adjusted1.shape}") # 输出(6,6),符合需求 # 示例2:(5,5)图像,window(3,3),step=2 img2 = np.random.rand(5,5) adjusted2 = adjust_image_for_windows(img2, 3, 2) print(f"示例2调整后尺寸:{adjusted2.shape}") # 输出(5,5),符合需求 # 验证滑动窗口是否正常工作 windows1 = view_as_windows(adjusted1, (4,4), step=2) windows2 = view_as_windows(adjusted2, (3,3), step=2) print(f"示例1窗口shape:{windows1.shape}") # 输出(1,1,4,4) print(f"示例2窗口shape:{windows2.shape}") # 输出(2,2,3,3)
内容的提问来源于stack exchange,提问作者ellamunde




