Check this: https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes
in your code:
- opencv read image in mode "BGR" ==> value between [0, 255]
- PILLOW read your image in mode "P" , I'll let you see the link to understand a little bit, if you get the pixel values between [0, 255], you have to convert your Image to "RGBA", "RGB" or "L" mode.
Try this:
import numpy as np
from PIL import Image
img_p = Image.open("img.png")
print("mode =",img_p.mode) #RGBA
print(np.unique(np.array(img_p)))
img_rgb = img_p.convert(mode = "RGB")
print("mode =",img_rgb.mode) #RGB
print(np.unique(np.array(img_rgb)))
img_rgb = img_p.convert(mode = "P")
print("mode =",img_rgb.mode) #P
print(np.unique(np.array(img_rgb)))
img_rgb = img_p.convert(mode = "L")
print("mode =",img_rgb.mode) #L
print(np.unique(np.array(img_rgb)))
if you have 3 colors, the "P" mode returns you [0, 1, 2] ....
if you have 4 colors, the "P" mode returns you [0, 1, 2, 3] ....
Palette "P" mode works by creating a mapping table, which corresponds to an index (between 0 and 255) to a discrete color in a larger color space (like RGB). For example, the RGB color value (0, 0, 255) (Pure Blue) in an image gets an index of 1 (just a hypothetical example). This same process goes through every single pixel value in the original image (but the table size should not exceed 256, in the mapping process).
therefore each color corresponds to an index in the mapping table, rather than the actual color value itself. So you can interpret them as an index which, when playing an image, is converted to the actual color value stored in that index. To answer your question, when you switch from "P" mode to "L" mode you just retrieve the real values stored in this index