如何在不改变像素值的情况下对图像数组进行采样
How to down sample image array, without changing pixel values
我有图像分割项目,并且以像素值代表标签的图像形式给出了地面实况标签。我需要调整图像和标签的大小,同时将标签保持在相同的值集中。
我尝试了很多东西,都改变了设置的值。
让我们创建虚拟数据
from skimage.transform import rescale, resize
from scipy import ndimage
from PIL import Image
import cv2
mask = np.zeros((30,20), dtype=np.uint16)
mask[22:26,12:30]=70
mask[25:27,14:17]=30
print('original label', mask.shape, np.unique(mask))
输出:原始标签形状:(30, 20) 原始标签值:[0 30 70]
我需要调整标签大小,所以结果将只有 0、30、70 个值。
我试过的
skimage_resized = resize(mask, (mask.shape[0]//2, mask.shape[1]//2), mode='constant')
print(skimage_resized.shape, np.unique(mask_resized))
skimage_rescale = rescale(mask, 1.0/2.0, mode='constant')
print(skimage_rescale.shape, np.unique(mask_resized))
ndimage_resized = ndimage.interpolation.zoom(mask, 0.5)
print(ndimage_resized.shape, np.unique(mask_resized))
cv2_resized = cv2.resize(mask, (mask.shape[0]//2, mask.shape[1]//2),
interpolation=cv2.INTER_NEAREST)
print(cv2_resized.shape, np.unique(mask_resized))
mask_pil = Image.fromarray(mask, mode=None)
pil_resized = mask_pil.thumbnail((mask.shape[0]//2, mask.shape[1]//2), Image.NEAREST)
print(skimage_resized.shape, np.unique(pil_resized))
输出:
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(10, 15) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [None]
来自 docs(强调我的):
Note that when down-sampling an image, resize and rescale should perform Gaussian smoothing to avoid aliasing artifacts. See the anti_aliasing and anti_aliasing_sigma arguments to these functions.
Downscale serves the purpose of down-sampling an n-dimensional image by integer factors using the local mean on the elements of each block of the size factors given as a parameter to the function.
您的问题的一种可能解决方法是通过 basic slicing:
进行下采样
import numpy as np
dx, dy = 2, 2
mask = np.zeros((30, 20), dtype=np.uint16)
mask[22:26, 12:30] = 70
mask[25:27, 14:17] = 30
downsampled = mask[::dx, ::dy]
print(downsampled.shape, np.unique(downsampled))
上面代码片段的输出是:
(15, 10) [ 0 30 70]
使用 openCV 找到解决方案。
import numpy as np
import cv2
resizeto = 2
small_lable = cv2.resize(mask, (mask.shape[1]//resizeto,
mask.shape[0]//resizeto),
interpolation=cv2.INTER_NEAREST)
small_lable = (np.array(small_lable)).astype('uint8')
print(small_lable.shape, np.unique(small_lable))
plt.imshow(small_lable)
输出:
(15, 10) [ 0 30 70]
我有图像分割项目,并且以像素值代表标签的图像形式给出了地面实况标签。我需要调整图像和标签的大小,同时将标签保持在相同的值集中。
我尝试了很多东西,都改变了设置的值。
让我们创建虚拟数据
from skimage.transform import rescale, resize
from scipy import ndimage
from PIL import Image
import cv2
mask = np.zeros((30,20), dtype=np.uint16)
mask[22:26,12:30]=70
mask[25:27,14:17]=30
print('original label', mask.shape, np.unique(mask))
输出:原始标签形状:(30, 20) 原始标签值:[0 30 70]
我需要调整标签大小,所以结果将只有 0、30、70 个值。
我试过的skimage_resized = resize(mask, (mask.shape[0]//2, mask.shape[1]//2), mode='constant')
print(skimage_resized.shape, np.unique(mask_resized))
skimage_rescale = rescale(mask, 1.0/2.0, mode='constant')
print(skimage_rescale.shape, np.unique(mask_resized))
ndimage_resized = ndimage.interpolation.zoom(mask, 0.5)
print(ndimage_resized.shape, np.unique(mask_resized))
cv2_resized = cv2.resize(mask, (mask.shape[0]//2, mask.shape[1]//2),
interpolation=cv2.INTER_NEAREST)
print(cv2_resized.shape, np.unique(mask_resized))
mask_pil = Image.fromarray(mask, mode=None)
pil_resized = mask_pil.thumbnail((mask.shape[0]//2, mask.shape[1]//2), Image.NEAREST)
print(skimage_resized.shape, np.unique(pil_resized))
输出:
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(10, 15) [ 0 5 6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [None]
来自 docs(强调我的):
Note that when down-sampling an image, resize and rescale should perform Gaussian smoothing to avoid aliasing artifacts. See the anti_aliasing and anti_aliasing_sigma arguments to these functions.
Downscale serves the purpose of down-sampling an n-dimensional image by integer factors using the local mean on the elements of each block of the size factors given as a parameter to the function.
您的问题的一种可能解决方法是通过 basic slicing:
进行下采样import numpy as np
dx, dy = 2, 2
mask = np.zeros((30, 20), dtype=np.uint16)
mask[22:26, 12:30] = 70
mask[25:27, 14:17] = 30
downsampled = mask[::dx, ::dy]
print(downsampled.shape, np.unique(downsampled))
上面代码片段的输出是:
(15, 10) [ 0 30 70]
使用 openCV 找到解决方案。
import numpy as np
import cv2
resizeto = 2
small_lable = cv2.resize(mask, (mask.shape[1]//resizeto,
mask.shape[0]//resizeto),
interpolation=cv2.INTER_NEAREST)
small_lable = (np.array(small_lable)).astype('uint8')
print(small_lable.shape, np.unique(small_lable))
plt.imshow(small_lable)
输出:
(15, 10) [ 0 30 70]