Home > Back-end >  Convert 1D 16bit image data to 2D numpy array
Convert 1D 16bit image data to 2D numpy array

Time:06-09

I have a 1D array of size 18874568 created from bytes as shown below

np_img = np.array(list(data), dtype=np.uint16)

How can I convert this to a 2D array of size 3072 x 3072 and in 8bit?

The bytes data is acquired from a image capture device called as a flat panel detector (FPD). It's specified in the docs that the FPD captures 16bit image of size 3072x3072.

16bit raw image is attached below https://drive.google.com/file/d/1Kw1UeKOaBGtXNpxGsCXEk-gjGw3YaDJJ/view?usp=sharing

Edit: C# code on conversion given by the FPD support team

    private Bitmap Load16bppGrayImage(string fileName, int offset=0)
    {
        Bitmap loadind_bmp;
        var raw = File.ReadAllBytes(fileName).Skip(offset).ToArray();
        var pwi = 3072;
        var phi = 3072;
        var dpiX = 96d;
        var dpiY = 96d;

        loadind_bmp = new Bitmap(pwi, phi, PixelFormat.Format48bppRgb);

        BitmapData bmpData = loadind_bmp.LockBits(new Rectangle(0, 0, loadind_bmp.Width, loadind_bmp.Height), ImageLockMode.ReadWrite, loadind_bmp.PixelFormat);
        int depth = Bitmap.GetPixelFormatSize(bmpData.PixelFormat) / 16;
        IntPtr srcAdr = bmpData.Scan0;

        unsafe
        {
            for (int y = 0; y < bmpData.Height; y  )
            {
                int pos = y * bmpData.Stride / 3;
                ushort* imgPtr = (y * bmpData.Stride / 2)   (ushort*)bmpData.Scan0;

                for (int x = 0; x < bmpData.Width; x  )
                {
                    ushort value = (ushort)(raw[pos   (x * sizeof(ushort))   1] << 8 | raw[pos   x * sizeof(ushort)]);

                    imgPtr[x * depth] = value;    //Blue 0-255
                    imgPtr[x * depth   1] = value;   //Green   0-255
                    imgPtr[x * depth   2] = value;  //Red 0-255
                }
            }
        }

        loadind_bmp.UnlockBits(bmpData);
        return loadind_bmp;

    }

CodePudding user response:

Right, based on all of the information gathered by the comments, I think you'll want something like this:

import numpy as np
import PIL.Image as Image

with open("data1.raw", "rb") as fp:
    data = fp.read()

w = h = 3072
dt = np.dtype(np.uint16).newbyteorder("<")  # little-endian
image = np.frombuffer(data, offset=96, count=w * h, dtype=dt).reshape((h, w))

# Dump to 16bpp TIFF:
Image.fromarray(image).save("data1.tiff")

The resulting image is quite dark, not "just white" – maybe it needs to be inverted? Who knows... :)

CodePudding user response:

Use ndarray.view:

>>> a = np.random.randint(2 ** 7, 2 ** 12, 10, dtype=np.uint16)
>>> a
array([3434, 1565, 3144,  357, 3755, 3130, 3799,  338, 3224, 2794],
      dtype=uint16)
>>> a.view(np.uint8)
array([106,  13,  29,   6,  72,  12, 101,   1, 171,  14,  58,  12, 215,
        14,  82,   1, 152,  12, 234,  10], dtype=uint8)

The better way is to read with uint8 instead of uint16 before conversion. You should refer to: Input and output

  • Related