Search code examples
pythonimageopencvgrayscale

Why there are stray pixels in computing the average of grayscale images?


I am computing the average of three grayscale images attached herewith. image1Each image is of size 256 x 256. Upon averaging, I am getting several stray pixels in the averaged output. Given below is the code I am using to generate the averaged image. image1 image2

image3 avg_output

avg_without_255_multiplication

import cv2
img1 = 'image1.png'
img2 = 'image2.png'
img3 = 'image3.png'

img_1 = cv2.imread(img1).astype("float32")
img_2 = cv2.imread(img2).astype("float32")
img_3 = cv2.imread(img3).astype("float32")

# averaging
result = 255*((img_1 + img_2 + img_3)/3)
result1 = result.clip(0, 255).astype("uint8")    
cv2.imwrite('avg.png', result1)

Solution

  • Jifi has the answer. If you had printed the arrays you're reading, you would have realized that those arrays ALREADY run from 0 to 255. You assumed they run from 0 to 1. If you remove the 255*, you'll get the results you expect.

    That does say that at least some of your images do have stray pixels down in that bottom area. A pixel value of 1 (out of 255) in any of the images would result in 85 in the final average.

    Followup

    OK, I'm now assuming that what you really want is the UNION of those three images, not the AVERAGE. If so, this will do it:

    import cv2
    img1 = 'x1.png'
    img2 = 'x2.png'
    img3 = 'x3.png'
    
    img_1 = cv2.imread(img1) > 1
    img_2 = cv2.imread(img2) > 1
    img_3 = cv2.imread(img3) > 1
    
    result = ((img_1 | img_2 | img_3) * 255).astype("uint8")
    cv2.imwrite('avg.png', result)
    

    So, img_x will contain True where the image pixel value is larger than 1. True and False behave as 1 and 0 in arithmetic computations.

    If you change the > 1 to > 0, you will see all of the non-zero pixels in your original images, which gives you the stray blobs at the bottom.