Unit 01.01: What the channel order silently changes
The same three bytes are a warm yellow or a blue, depending entirely on which library read them.
RGB and BGR, and nothing that warns you
OpenCV reads and writes BGR. PIL, matplotlib and essentially every pretrained model expect RGB.
The code shows one pixel interpreted both ways.
import numpy as np
# The same three bytes, read two ways.
pixel_rgb = np.array([220, 180, 40], dtype="uint8")
pixel_bgr = pixel_rgb[::-1]
print("as RGB:", pixel_rgb, "-> a warm yellow")
print("as BGR:", pixel_bgr, "-> a blue")
for library, order in [("PIL / matplotlib", "RGB"), ("OpenCV", "BGR"),
("most pretrained models", "RGB")]:
print(f"{library:24} expects {order}")
print("\nMixing them does not raise. It changes the colours and nothing else.")
# This is the single most common silent bug in vision code. A model trained on
# RGB and fed BGR still runs, still produces confident predictions, and is
# quietly worse -- with no error anywhere to find.
Nothing raises. The image loads, the model runs, the predictions come out confident, and the colours are wrong - which for a model trained on RGB means every input is subtly out of distribution.
It is the most common silent bug in vision code precisely because it produces no symptom other than being worse.
The mistake this prevents
The mistake is converting at the point of confusion instead of at the boundary. Convert once where the image enters your code, assert the order there, and let everything downstream assume RGB.
Takeaway
OpenCV is BGR; almost everything else is RGB. Mixing them changes the colours and raises nothing, so convert at the boundary and assert.
