Search code examples
pythonnumpypngjpegopencv

Why are colour pixels detected in .png format images but not in those in .jpg format?


I have a picture with a white background in which there are red, green and blue lines. The red green and blue lines are exclusively of the following values: (255,0,0), (0,255,0) and (0,0,255). The image is now saved as .png and as .jpg. The code should work in both formats. The following code is to detect the colours and return the number of the respective colour pixels. As .png the code works, as .jpg only the green pixels are recognised, but unfortunately not all of them. How can all pixels of all 3 colours also be recognised with .jpg?

import cv2
import numpy as np

img = cv2.imread(r"...\red.jpg")
x,y,z = img.shape
print(x,y,z)

r = np.where((img == (0, 0, 255)).all(axis=2))
redarray = np.array(r)
red = np.size(redarray)
g = np.where((img == (0, 255, 0)).all(axis=2))
greenarray = np.array(g)
green = np.size(greenarray)
bl = np.where((img == (255, 0, 0)).all(axis=2))
bluearray = np.array(bl)
blue = np.size(bluearray)
       

print("red: ", red)
print("green: ", green)
print("blue: ", blue)


Solution

  • Without seeing the images, jpeg images are compressed and if not handled with care pixel values are not the same as the equivalent png image.

    Two approaches:

    1. Upon saving the jpeg you might try using a higher resolution/lower compression. It might work. It will also increase the file size.
    2. Instead of searching for the exact values (for example red == (0, 0, 255)), look for pixels under some thresholds. For example define th=10 and look for red pixels in the range of: green <= 0+th & blue <= 0+th & red >= 255-th.

    Sorry I don't have a running code under this answer, let me know if you need further assistance with the masking.