I have an image that has a bunch of dead pixels in it. In python, I have one numpy array that will hold the final image, and I have another boolean numpy array of the same shape that indicates which pixels need to be filled in.
I want to fill in the dead pixels by taking the average of the 8 surrounding pixels, but only if they actually hold data. For example, if I have this (N means there is no data there, ? is the pixel to fill in):
1 2 N
N ? 2
N N 5
I will fill in the ? with (1+2+2+5)/4 .
Right now, I do this with a for loop as follows. outFrame holds the final image, while populated is the boolean array indicating which pixels have been filled in:
# 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])
Obviously, python looping is slow but I can't figure out any numpy indexing magic to get this behavior. Is there a way to do this functionality quickly in python?
EDIT: I tried using the opencv inpainting function as follows:
mask = (1*~populated).astype(np.uint8)
outFrame = cv2.inpaint(outFrame,mask,3,cv2.INPAINT_NS) # This is very slow
However, this was 10x slower than my original method (my method takes ~3-6 seconds, while the inpainting method took 60 seconds). I have a very large amount of dead pixels, and I think this is the reason it is slow for this method
EDIT: Here is an example image.
Raw image: https://i.stack.imgur.com/2QXc1.jpg
After interpolation: https://i.stack.imgur.com/8BHZn.jpg