Python 用于图像插值的快速numpy索引
我有一张图像,里面有一堆死像素。在python中,我有一个用于保存最终图像的numpy数组,还有另一个相同形状的布尔numpy数组,用于指示需要填充哪些像素 我想通过取周围8个像素的平均值来填充死像素,但前提是它们实际包含数据。例如,如果我有这个N意味着那里没有数据?是要填充的像素:Python 用于图像插值的快速numpy索引,python,image,numpy,indexing,slice,Python,Image,Numpy,Indexing,Slice,我有一张图像,里面有一堆死像素。在python中,我有一个用于保存最终图像的numpy数组,还有另一个相同形状的布尔numpy数组,用于指示需要填充哪些像素 我想通过取周围8个像素的平均值来填充死像素,但前提是它们实际包含数据。例如,如果我有这个N意味着那里没有数据?是要填充的像素: 1 2 N N ? 2 N N 5 我来填表格好吗?1+2+2+5/4 现在,我使用for循环来实现这一点,如下所示。outFrame保存最终图像,而填充的是布尔数组,指示已填充的像素: # Lo
1 2 N
N ? 2
N N 5
我来填表格好吗?1+2+2+5/4
现在,我使用for循环来实现这一点,如下所示。outFrame保存最终图像,而填充的是布尔数组,指示已填充的像素:
# Loop through each pixel in the image
for row in range(height):
for col in range(width):
# Check to see if the pixel needs to be filled in
if not populated[row,col]:
# Check for boundary conditions
xmin = max(0,col-1)
xmax = min(width-1,col+1)
ymin = max(0,row-1)
ymax = min(height-1,row+1)
# Find the 8 surrounding values
vals = outFrame[ymin:ymax+1,xmin:xmax+1]
mask = populated[ymin:ymax+1,xmin:xmax+1]
# Find the average of only the populated pixels
if vals[mask].size != 0:
outFrame[row,col] = np.mean(vals[mask])
显然,python循环速度很慢,但我无法想出任何numpy索引魔术来实现这种行为。有没有办法在python中快速实现这一功能
编辑:我尝试使用opencv修复功能,如下所示:
mask = (1*~populated).astype(np.uint8)
outFrame = cv2.inpaint(outFrame,mask,3,cv2.INPAINT_NS) # This is very slow
然而,这比我原来的方法慢了10倍。我的方法需要3-6秒,而修复方法需要60秒。我有大量的死像素,我认为这就是这种方法速度慢的原因
编辑:下面是一个示例图像。
原始图像:
插值后:很难为您提供帮助,因为您没有提供最低限度的完整可验证代码示例,以及显示如何打开图像的所有导入语句和代码,甚至没有指明您是在使用OpenCV还是PIL或skimage。另外,您还没有为第二个文件提供绘制所需的所有点的遮罩,我也不知道您实际想要实现的目标,因此目前,我只是尝试提供一种方法,在我看来,它得到的结果与您显示的结果类似 无论如何,这里有一个方法,使用形态学,在我的Mac电脑上需要100微秒——这可能与你正在使用的任何东西都不一样-
#!/usr/bin/env python3
import cv2
import numpy as np
# Load image and make into Numpy array
im = cv2.imread('holey.png')
# Use morphology to find maximum pixel in each 3x3 square
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph = cv2.morphologyEx(im, cv2.MORPH_DILATE, kernel)
# Save result
cv2.imwrite('result.png', morph)
这很难为您提供帮助,因为您没有提供一个最低限度的完整的可验证代码示例,其中包含显示如何打开图像的所有导入语句和代码,甚至没有指明您使用的是OpenCV、PIL还是skimage。另外,您还没有为第二个文件提供绘制所需的所有点的遮罩,我也不知道您实际想要实现的目标,因此目前,我只是尝试提供一种方法,在我看来,它得到的结果与您显示的结果类似 无论如何,这里有一个方法,使用形态学,在我的Mac电脑上需要100微秒——这可能与你正在使用的任何东西都不一样-
#!/usr/bin/env python3
import cv2
import numpy as np
# Load image and make into Numpy array
im = cv2.imread('holey.png')
# Use morphology to find maximum pixel in each 3x3 square
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph = cv2.morphologyEx(im, cv2.MORPH_DILATE, kernel)
# Save result
cv2.imwrite('result.png', morph)
我找到了适合我的用例的完美方法,我想我会发布它。我相信它与我最初的for-loop方法功能完全相同,同时执行速度快了约300倍!3-4秒到0.01秒
import cv2
image = <READ IMAGE IN>
populated = <BOOLEAN MASK OF SAME SHAPE AS image>
image[~populated] = 0
blurred = cv2.boxFilter(image,-1,(3,3),normalize=False)
countMask = cv2.boxFilter(populated.astype('int'),-1,(3,3),normalize=False)
image[countMask != 0] = blurred[countMask != 0] / countMask[countMask != 0]
第一行将未填充的像素设置为0,因此它们不会增加模糊步骤的和。
第二行使图像模糊,而不进行标准化,对于每个像素,对其周围的像素求和。
第三行模糊遮罩,这会导致每个像素计算其周围的有效像素数。
最后,第四行通过使用有效数字规范化模糊像素来填充未填充的像素
多亏了Divakar,他有了正确的想法。我找到了适合我的用例的完美方法,我想我会发布它。我相信它与我最初的for-loop方法功能完全相同,同时执行速度快了约300倍!3-4秒到0.01秒
import cv2
image = <READ IMAGE IN>
populated = <BOOLEAN MASK OF SAME SHAPE AS image>
image[~populated] = 0
blurred = cv2.boxFilter(image,-1,(3,3),normalize=False)
countMask = cv2.boxFilter(populated.astype('int'),-1,(3,3),normalize=False)
image[countMask != 0] = blurred[countMask != 0] / countMask[countMask != 0]
第一行将未填充的像素设置为0,因此它们不会增加模糊步骤的和。
第二行使图像模糊,而不进行标准化,对于每个像素,对其周围的像素求和。
第三行模糊遮罩,这会导致每个像素计算其周围的有效像素数。
最后,第四行通过使用有效数字规范化模糊像素来填充未填充的像素
归功于Divakar,他的想法是正确的。只需对图像和遮罩的3x3内核进行2D卷积,然后将其分割?OpenCV将非常快速地完成此操作-称为修复,请参见此处。。。我编辑以显示使用修复的结果。这对我来说是非常缓慢的me@Divakar,我考虑过这样做,但我不确定如果我使用cv2.Convalve2D,如何忽略死像素appropriately@JayJackman在对遮罩进行卷积时,会考虑死像素。如果没有死像素,图像的直接卷积就足够了。只需对图像和遮罩的3x3内核进行2D卷积并将其分割?OpenCV将非常快地完成此操作-称为修复,请参见此处。。。我编辑以显示使用修复的结果。这对我来说是非常缓慢的me@Divakar,我考虑过这样做,但我不确定如果我使用cv2.Convalve2D,如何忽略死像素appropriately@JayJackman在对遮罩进行卷积时,会考虑死像素。Wi
尽管没有死像素,图像的直接卷积就足够了。我认为这应该很好!我没有想到形态学运算,因为我以为它们只是处理二值图像。我知道我的图像看起来是二值的,但一般来说不会。这对我来说是非常快的0.01秒,这很好。非常感谢。我认为这应该是相当好的!我没有想到形态学运算,因为我以为它们只是处理二值图像。我知道我的图像看起来是二值的,但一般来说不会。这对我来说是非常快的0.01秒,这很好。非常感谢。