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
53 stars 4 forks source link

How do I save a single channel greyscale image encoder.write() function with the Python API? #6

Open rahedges opened 2 months ago

rahedges commented 2 months ago

Describe the question.

I have experimental data which is grayscale ( not rgb) and so the image shape is 2-D not 3-D. I would like to save the data as a jp2k image using the nvImageCodec encoder using the python AIP.

If I use the encode.write() command with 2-D array, I receive an error: RuntimeError: Unexpected number of dimensions

However, if I duplicate the channel so that it is a 3-D array: frameRGB=np.asarray(np.dstack((frame, frame, frame)),dtype=np.uint16)

It will save frameRFB without an error.

The application that reads this data expects it to be single channel (2-D) data. I couldn't find any parameters that would specify this was single channel data.

The C API appears to support this with the num_planes parameter of nvimgcodecImageInfo_t : https://docs.nvidia.com/cuda/nvimagecodec/c_api.html#nvimgcodecimageinfo-t

Does this python API have such an option?

Check for duplicates

jantonguirao commented 2 months ago

@rahedges Thanks for reporting this. Currently, nvimagecodec expects the input to have 3 dimensions, even for single channel images. You can easily add an extra channels dimension with one element, by simply doing:

arr = np.expand_dims(arr, -1)  # goes from shape (M, N) to (M, N, 1)

Please let us know if that helps.

That being said, we will consider lifting this restriction on nvImageCodec side, so that you can pass 2D arrays directly.

rahedges commented 2 months ago

@rahedges Thanks for reporting this. Currently, nvimagecodec expects the input to have 3 dimensions, even for single channel images. You can easily add an extra channels dimension with one element, by simply doing:

arr = np.expand_dims(arr, -1)  # goes from shape (M, N) to (M, N, 1)

Please let us know if that helps.

That being said, we will consider lifting this restriction on nvImageCodec side, so that you can pass 2D arrays directly.

This didn't' work for me when the frame has shape (M,N,1) , I receive and an error:

[ERROR] [nvjpeg2k_encoder] Could not encode jpeg2k code stream - nvjpeg2k extension: Invalid parameter /home/jenkins/agent/workspace/nvimagecodec/helpers/release_v0.2.0/Release_12/build/extensions/nvjpeg2k/cuda_encoder.cpp:453

However, when expand it to a full 3 channel dataset which shape (M,N,3), it works: frameRGB = np.dstack((frame, frame, frame))

This isn't ideal since it uses more memory. Where you able to get it to work with an (M,N,1) array?

jantonguirao commented 2 months ago

@rahedges You are right, there's a bug. We will fix it in the next release. We don't have a target release date yet but we will let you know when it is fixed.

rahedges commented 2 months ago

Thanks, I can make things work with np.dstack work around for now.