我想在python中循环二值图像的像素,并根据周围像素的邻域设置像素值。类似于卷积,但我想创建一个方法,使用自定义函数设置中心像素的值,而不是将中心像素设置为邻域的算术平均值的普通卷积。
实际上,我想创建一个函数,它执行以下操作:
def convolve(img, conv_function = lambda subImg: np.mean(subImg)):
newImage = emptyImage
for nxn_window in img:
newImage[center_pixel] = conv_function(nxn_window)
return newImage
此刻我有一个办法但却是十分缓慢:
#B is the structuing array or convolution window/kernel
def convolve(func):
def wrapper(img, B):
#get dimensions of img
length, width = len(img), len(img[0])
#half width and length of dimensions
hw = (int)((len(B) - 1) / 2)
hh = (int)((len(B[0]) - 1) / 2)
#convert to npArray for fast operations
B = np.array(B)
#initialize empty return image
retVal = np.zeros([length, width])
#start loop over the values where the convolution window has a neighborhood
for row in range(hh, length - hh):
for pixel in range(hw, width - hw):
#window as subarray of pixels
window = [arr[pixel-hh:pixel+hh+1]
for arr in img[row-hw:row+hw+1]]
retVal[row][pixel] = func(window, B)
return retVal
return wrapper
使用这个函数作为装饰器
# dilation
@convolve
def __add__(img, B):
return np.mean(np.logical_and(img, B)) > 0
# erosion
@convolve
def __sub__(img, B):
return np.mean(np.logical_and(img, B)) == 1
有没有提供这种类型函数的库,或者有没有更好的方法可以循环图像?
1条答案
按热度按时间fnvucqvd1#
这里有一个想法:给每个像素分配一个数组,然后简单地把你的自定义函数应用到扩展的图像上。如果你的B形是(3,3),那么你需要9倍的内存)。
我已经使用了灰度图像512x512像素和过滤器3x3进行测试:
为了与我使用的卷积进行比较:
在我的机器上,
convolve
的时间是4.3秒,convolve2
的时间是0.05秒。在我的例子中,自定义函数需要指定操作的轴,即保存邻域数据的附加维度。也许轴也可以避免,但我没有尝试过。
注意:这适用于2D图像(灰度)(如您所问的二进制图像),但也可以很容易地扩展到3D(彩色)图像。在您的情况下,您可能会摆脱框架(或填充0或1,例如,在重复应用该功能的情况下)。
如果内存是一个问题,你可能想适应一个快速实现的卷积我已经张贴在这里:https://stackoverflow.com/a/74288118/20188124。