0

Im not expert in python. I want to seee the effect of quantization (bit depth reduction) by converting the image (array) with type of uint8 to uint4 (4 bit arrray).

Is it possible an array with type of uint4 in python?

I scaled my data to 0-15 and use this line im4 = np.bitwise_and(im_scaled, 0x0f) But still the type is uint8 as you see in below: In[173]: im4.dtype Out[173]: dtype('uint8')

I expected dtype('uint4')

1 Answer 1

1

Here is the list of numpy's data types, so no uint4.

For uints, you have the following:

(note: .itemsize returns the "length of one array element in bytes")

In [1]: numpy_dtypes = (
   ...:     (np.uint8, np.ubyte),
   ...:     (np.uint16, np.ushort),
   ...:     (np.uint32, np.uintc),
   ...:     (np.uint64, np.uintp, np.ulonglong),
   ...: )
   ...: for dtypes in numpy_dtypes:
   ...:     print([dt().itemsize for dt in dtypes])
[1, 1]
[2, 2]
[4, 4]
[8, 8, 8]

You can simulate any bit depth by just scaling into the correct dynamic range and rounding to integers:

various num bits plots

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable


def main():

    imh, imw = 512, 512

    data = np.arange(imh * imw).reshape(imh, imw)
    num_bits = [2, 4, 8, 16]

    images = {
        nbits: np.round(minmax_scale(data, vmin=0, vmax=2**nbits - 1))
        for nbits in num_bits
    }

    fig, axes = plt.subplots(ncols=len(images), figsize=(12, 4))

    for ax, (nbits, image) in zip(axes, images.items()):
        ax.set_title(f"{nbits = }")
        im = ax.imshow(image, vmin=0, vmax=2**nbits - 1, interpolation="none")
        add_colorbar(ax, im)

    plt.subplots_adjust(wspace=0.8)
    plt.show()


def add_colorbar(ax, im):
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="5%", pad=0.05)
    cax.get_figure().colorbar(im, cax=cax, orientation="vertical")


def minmax_scale(arr, *, vmin, vmax):
    amin, amax = arr.min(), arr.max()
    arr_std = (arr - amin) / (amax - amin)
    return arr_std * (vmax - vmin) + vmin


if __name__ == "__main__":
    main()
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your answer. Are the printed numbers related to bytes? And do you know how can I make an array in 4 bits in python? I have an image dataset in 8 bits. I want to create another dataset by converting the images to 4 bits.
Added an edit for that
I see the differences in the images for different numbers of bits. But my concern is all 4 created images in images {dict} are Array of float64. Do you think is it ok created an image in 2 bits that is stored it in float 64?
It is enough to "see the effect of quantization". Sure it is not best suited for storage, but as you can only use np.uint8, np.uint16, np.uint32 and np.uint64 you have no other choice but to use at best the "smallest" data type that is "big" enough. For example in remote sensing optical imagery it is common for sensors to have a dynamic range of 12 bits, and images are stored in uint16 with metadata describing that the dynamic range is only 12 bits, so the maximum value expected is only 2 ** 12 - 1 and not 2 ** 16 - 1 as the data type used for storage would have suggested.
Btw a byte is the minimum entity for computers, so 8 bits. Even if you try a custom data type in numpy using dtype = np.dtype((np.void, 1)) then you'll found dtype.itemsize to be 1 (byte).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.