NVIDIA / nvImageCodec

A nvImageCodec library of GPU- and CPU- accelerated codecs featuring a unified interface
https://docs.nvidia.com/cuda/nvimagecodec/index.html
Apache License 2.0
65 stars 5 forks source link

Possibly wrong encoding of jpeg from nparray #15

Open liorbenhorin opened 3 weeks ago

liorbenhorin commented 3 weeks ago

Version

0.3.0

Describe the bug.

When encoding an image from an nparray to jpeg - result is incorrect, image is offset to the righ, colors are 'separated'.

The exact image, if saved to jpg to disk (using cv2), and then loaded and encoded - will be saved correctly.

This observation is not happening when using j2k encoder. However, the j2k encoder does not respect quality params (same result for any value)

original image original

original image as npy (compressed for security) original_as_npy.zip

incorrect result out_as_jpg

Minimum reproducible example

import cv2
from nvidia import nvimgcodec

encoder = nvimgcodec.Encoder()

# start from an image that is saved as nparray - (720, 720, 4) uint8
orig_npy = np.load("original.npy")

# saving out as jpg and as j2k, default params
encoder.write("out_as_jpg2.jpg", orig_npy)
encoder.write("out_as_j2k.j2k", orig_npy)

###############################################################################

# if you start from an image and not nparray, you will get correct jpg result
orig_img = cv2.imread("original.jpg")
encoder.write("out_as_jpg2.jpg", orig_img)

Environment details

Ubuntu 22.04
Python 3.10.12
A6000 ADA
python venv pip freeze >
contourpy==1.2.1
cycler==0.12.1
fonttools==4.53.1
kiwisolver==1.4.5
matplotlib==3.9.2
numpy==2.1.0
nvidia-nvimgcodec-cu12==0.3.0.5
nvidia-nvjpeg-cu12==12.3.3.23
nvidia-nvjpeg2k-cu12==0.8.0.38
nvidia-pyindex==1.0.9
opencv-python==4.10.0.84
packaging==24.1
pillow==10.4.0
pyparsing==3.1.2
python-dateutil==2.9.0.post0
six==1.16.0

Relevant log output

No response

Other/Misc.

No response

Check for duplicates

smatysik-nv commented 3 weeks ago

Thanks for reporting this issue.

Unfortunately nvImageCodec currently does not support RGBA format (nvjpeg which we use under the hood also does not support RGBA) and this is what looks is in orig_npy. We can consider adding RGBA format in future (or at least ignore A if there is 4 color components) but for now definitively we should rather report error and not silently encode and corrupt image.

For now, you can try to remove forth component and pass rgb array

orig_rgb = orig_npy[:,:,:3].copy()
encoder.write("out_as_jpg.jpg",orig_rgb)

Unfortunately in this case there is copy necessary.

Regarding " j2k encoder does not respect quality params" comment, for JPEG 2000 please use target_psnr instead of quality