OpenCV reads image differently based on installation (pip vs conda)

Depending on whether opencv was installed via conda or pip, it reads the same image differently. The following is the script and image I used to test this.

Code

import cv2
import rasterio as rio
from skimage import io
import numpy as np

def check(path):
    # All images should be in RGB mode
    im1 = rio.open(path)
    im1 = im1.read()
    im1 = im1.transpose(1, 2, 0) # CHW to HWC
    im2 = cv2.imread(path)
    im2 = im2[:,:,::-1] # BGR to RGB
    im3 = io.imread(path)
    

    print(f"Rasterio and OpenCV = {np.all(im1[:,:,0] == im2[:,:,0])}")
    print(f"Rasterio and Skimage = {np.all(im1[:,:,0] == im3[:,:,0])}")

if __name__ == "__main__":
    check("rgb.jpg")

How to reproduce

Create two environments as follows:

conda create -n s1 -c conda-forge rasterio scikit-image python=3.7
conda activate s1
pip install opencv-python
conda create -n s2 -c conda-forge rasterio scikit-image opencv python=3.7

Link to image here

Output

# For s1 (opencv from pip)
Rasterio and OpenCV = False
Rasterio and Skimage = True
# For s2 (opencv from conda)
Rasterio and OpenCV = True
Rasterio and Skimage = True

s1 returns False for the rasterio vs opencv test, whereas s2 returns True for the same.

Why does this happen?

Because it’s not same library used for jpeg

Could you elaborate? What do you mean by not using the same library for jpeg?

use print(cv.getBuildInformation()) to check lib :

  Media I/O:
    ZLib:                        optimized G:/lib/install/zlib/lib/zlibstatic.lib debug G:/lib/install/zlib/lib/zlibstaticd.lib (ver 1.2.11)
    JPEG:                        build-libjpeg-turbo (ver 2.0.6-62)
    WEBP:                        build (ver encoder: 0x020f)
    PNG:                         optimized G:/lib/install/libpng/lib/libpng16_static.lib debug G:/lib/install/libpng/lib/libpng16_staticd.lib (ver 1.6.36)
    TIFF:                        build (ver 42 - 4.0.10)
    JPEG 2000:                   build (ver 2.3.1)
    OpenEXR:                     build (ver 2.3.0)
    HDR:                         YES
    SUNRASTER:                   YES
    PXM:                         YES
    PFM:                         YES
  Video I/O:
    DC1394:                      NO
    FFMPEG:                      YES (prebuilt binaries)
      avcodec:                   YES (58.91.100)
      avformat:                  YES (58.45.100)
      avutil:                    YES (56.51.100)
      swscale:                   YES (5.7.100)
      avresample:                YES (4.0.0)
    GStreamer:                   NO
    DirectShow:                  YES
    Media Foundation:            YES
      DXVA:                      YES
1 Like

you should never expect lossy file formats to compress and decompress to identical results.

Thanks. That was exactly it. Post 3.3.0.10, opencv-python ships with libjpeg-turbo and that’s what you get when you install via pip. The conda version ships with libjpeg. That was the reason the images were read differently.