0

Can someone please explain why do I get this inconsistency in rgb values after saving the image.

import imageio as io

image = 'img.jpg'
type = image.split('.')[-1]
output = 'output' + type

img = io.imread(image)

print(img[0][0][1]) # 204

img[0][0][1] = 255

print(img[0][0][1]) # 255

io.imwrite(output, img, type, quality = 100)

imgTest = io.imread(output)

print(imgTest[0][0][1]) # 223

# io.help('jpg')

Image used = img.jpg

2 Answers2

1

The reason that pixels are changed when loading a jpeg image and then saving it as a jpeg again is that jpeg uses lossy compression. To save storage space for jpeg images, pixel values are saved in a dimension-reduced representation. You can find some information about the specific algorithm here. The advantage of lossy compression is that the image size can significantly be reduced, without the human eye noticing any changes. However, without any additional methods, we will not retrieve the original image after saving it in jpg format.

An alternative that does not use lossy compression is the png format, which we can verify by converting your example image to png and runnning the code again:

import imageio as io
import numpy as np
import matplotlib.pyplot as plt

image = '/content/drive/My Drive/img.png'
type = image.split('.')[-1]
output = 'output' + type

img = io.imread(image)

print(img[0][0][1]) # 204

img[0][0][1] = 255

print(img[0][0][1]) # 255

io.imwrite(output, img, type)

imgTest = io.imread(output)

print(imgTest[0][0][1]) # 223

# io.help('jpg')

Output:

204
255
255

We can also see that the png image takes up much more storage space than the jpg image

import os
os.path.getsize('img.png')
# output: 688444
os.path.getsize('img.jpg')
# output: 69621

Here is the png image: png image

yuki
  • 745
  • 4
  • 15
  • It worked with PNG. @yuki Thank you for your time mate. Just a quick question : I've experienced this when I was trying to create a simple Steganography function. So this means it won't work well jpegs ? – Nimesh Nelanga Aug 06 '21 at 19:26
  • https://stackoverflow.com/questions/29677726/steganography-in-lossy-compression-java Does this answer help you? It seems you have to encode your hidden message in a specific step of the jpeg compression algorithm so that the pixels (and thereby your hidden message) are not destroyed during lossy compression. – yuki Aug 07 '21 at 09:11
0

there is a defined process in the imageio

imageio reads in a structure of RGB, if you are trying to save it in the opencv , you need to convert this RGB to BGR. Also, if you are plotting in a matplotlib, it varies accordingly.

the best way is,

  1. Read the image in imageio
  2. convert RGB to BGR
  3. save it in the opencv write
Tamil Selvan
  • 1,600
  • 1
  • 9
  • 25
  • 1
    OP is both reading and writing the image with imageio, the issue you're describing only occurs if you are mixing imageio and opencv and not if you're only using one of imageio/opencv – yuki Aug 04 '21 at 11:48