nvImageCodec icon indicating copy to clipboard operation
nvImageCodec copied to clipboard

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

Open rahedges opened this issue 1 year ago • 4 comments

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

  • [X] I have searched the open bugs/issues and have found no duplicates for this bug report

rahedges avatar May 02 '24 22:05 rahedges

@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.

jantonguirao avatar May 06 '24 09:05 jantonguirao

@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?

rahedges avatar May 06 '24 14:05 rahedges

@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.

jantonguirao avatar May 06 '24 14:05 jantonguirao

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

rahedges avatar May 06 '24 14:05 rahedges

This issue should be fixed with the new release v0.3.0. Please reopen if the issue persists.

jantonguirao avatar Aug 09 '24 08:08 jantonguirao