我找了几个小时才找到类似的问题,但没有什么能让我满意。我的问题是:我有一个PIL图像(代表运河(已经转换成Numpy数组(使用PIL的"L"模式(,我想检索其邻居是黑色的白色像素(事实上它们的索引(,而不使用循环(图像真的很大(。我想到了np.其中,但我不知道该如何使用它来解决我的问题,我也不知道它是否会比使用用于循环更快(因为我的目标是用最快的解决方案达到这个目标(。
我希望我已经足够清楚了,我提前感谢你的回复!
编辑:例如,对于这个图像(一个简单的运河,它已经是一个黑白图像,所以image.convert('L'(在这里并不是很有用,但如果可能的话,代码应该是通用的(,我会做这样的事:
import numpy as np
from PIL import Image
image = Image.open(canal)
image = image.convert("L")
array = np.asarray(image)
l = []
for i in range(1, len(array) - 1):
for j in range(1, len(array[0]) - 1):
if array[i][j] == 255 and (array[i+1][j] == 0 or array[i-1][j] == 0 or array[i][j+1] == 0 or array[i][j-1] == 0):
l.append((i, j))
我希望尽快获得l:(在下一张图片中,我已经将需要的像素涂成了红色:在这里。
第二版:谢谢大家的帮助,它起了作用!
您可以使用numba
即时编译器来加速循环。
from numba import njit
@njit
def find_highlow_pixels(img):
pixels = []
for j in range(1, img.shape[0]-1):
for i in range(1, img.shape[1]-1):
if (
img[j, i] == 255 and (
img[j-1, i]==0 or img[j+1,i]==0 or
img[j, i-1]==0 or img[j, i+1]==0
)
):
pixels.append((j, i))
return pixels
我想到的另一种可能性是使用最小过滤器。然而,我预计它会比第一个提出的解决方案慢,但在它的基础上构建更多可能是有用的
import numpy as np
from scipy.ndimage import minimum_filter
# create a footprint that only takes the neighbours into account
neighbours = (np.arange(9) % 2 == 1).reshape(3,3)
# create a mask of relevant pixels, img should be your image as array
mask = np.logical_and(
img == 255,
minimum_filter(img, footprint=neighbours) == 0
)
# get indexes
indexes = np.where(mask)
# as list
list(zip(*indexes))
如果不考虑内存空间,我更喜欢如下操作掩码。
# Step 1: Generate two masks of white and black.
mask_white = img == 255
mask_black = img == 0
# Step 2: Apply 8-neighborhood dilation on black mask
# if you want to use numpy only, you need to implement dilation by yourself.
# define function of 8-neighborhood dilation
def dilate_8nb(m):
index_row, index_col = np.where(m)
ext_index_row = np.repeat(index_row,9)
ext_index_col = np.repeat(index_col,9)
ext_index_row.reshape(-1,9)[:, :3] += 1
ext_index_row.reshape(-1,9)[:, -3:] -= 1
ext_index_col.reshape(-1,9)[:, ::3] += 1
ext_index_col.reshape(-1,9)[:, 2::3] -= 1
ext_index_row = np.clip(ext_index_row, 0, m.shape[0]-1)
ext_index_col = np.clip(ext_index_col, 0, m.shape[1]-1)
ret = m.copy()
ret[ext_index_row, ext_index_col] = True
return ret
ext_mask_black = dilate_8nb(mask_black)
# or just using dilation in scipy
# from scipy import ndimage
# ext_mask_black = ndimage.binary_dilation(mask_black, structure=ndimage.generate_binary_structure(2, 2))
# Step 3: take the intersection of mask_white and ext_mask_black
mask_target = mask_white & ext_mask_black
# Step 4: take the index using np.where
l = np.where(mask_target)
# modify this type to make it consistency with your result
l = list(zip(*l))