Reputation: 21
I create and view a random image. Then, this image is encoded as a jpg file with opencv. However, after decoding this image the colors have been changed slightly. This behavior is not seen using png to encode. Can anyone explain why this occurs? Is it a negative result of the jpeg compression? Am I doing something wrong? Code sample below to recreate this.
import cv2
import numpy as np
random_image = np.random.randint(255, size=(4,4,3), dtype=np.uint8)
cv2.imshow('Image', random_image)
cv2.waitKey()
_, img_encoded = cv2.imencode('.jpg', random_image)
img_string = img_encoded.tostring()
npimg = np.fromstring(img_string, dtype=np.uint8)
img = cv2.imdecode(npimg, 1)
cv2.imshow('Image', img)
cv2.waitKey()
# Does not happen with png
_, img_encoded = cv2.imencode('.png', random_image)
img_string = img_encoded.tostring()
npimg = np.fromstring(img_string, dtype=np.uint8)
img = cv2.imdecode(npimg, 1)
cv2.imshow('Image', img)
cv2.waitKey()
Edited to add some 4x4 images.
Original:
JPG
PNG
Edited again with 512x512 images
Upvotes: 2
Views: 5941
Reputation: 11
you can try this to get a lossless compression:
import cv2
import numpy as np
img = cv2.imread('input_image.png')
# encode image with 'png'
retval, buffer = cv2.imencode('.png', img)
if not retval:
raise ValueError("can't encode image")
decoded_img = cv2.imdecode(buffer, cv2.IMREAD_UNCHANGED)
if np.array_equal(img, decoded_img):
print("image pixe are same.")
else:
print("image pixels are different.")
Upvotes: 0
Reputation: 97
I don't know why your PNG image had the correct colors as in my case it was also affected. Anyway, this should work for any extensions.
OpenCV uses BRG instead of RGB, so it inverts the red and blue colors. To correct this, make sure to re-convert the image colors before encoding them:
correct_color = cv2.cvtColor(img_array , cv2.COLOR_BGR2RGB)
encode_image = cv2.imencode('.jpg', correct_color)
Note that img_array
is the NumPy array resulting from a cv2.imread()
Upvotes: -1
Reputation: 420
JPG
is a lossy compression. It actually works by modifying colours in a way that should be "unoffensive" to the eye. PNG
is a lossless compression, so you get exactly what to had after encode/decode.
You can control how much JPG
will be free to modify the image by specifying the IMWRITE_JPEG_QUALITY
parameter like this:
cv2.imencode(('.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 90])
Higher values means less compression and result closer to original. For example, 100
should be no compression at all and result identical to original.
Upvotes: 3