2

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;

    }
19
  • 1
    But 3072x3072x2 is not equal to 18874568. Commented Jun 8, 2022 at 7:50
  • 1
    The data you've posted is 18874568 bytes long; sqrt(18874568/2) is > 3072, so there has to be some other data than just raw image data in there (18874568-(3072*3072*2) = 200 bytes to be exact). Commented Jun 8, 2022 at 7:51
  • 1
    Msybe you can show a screengrab of what parameters you input into IrfanView? Commented Jun 8, 2022 at 8:12
  • 1
    @AKX So, now we are short of data... we need 3072*3072*3*2 bytes. Commented Jun 8, 2022 at 18:38
  • 1
    The Fpd image is combined by the header(96 bytes) + image data (Width * Height * 2) + extra infomation(100 bytes) + CRC(4 bytes) - Their reply Commented Jun 9, 2022 at 7:03

2 Answers 2

1

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... :)

Sign up to request clarification or add additional context in comments.

3 Comments

Actually, I was just thinking np.fromfile() with offset and count might be a fraction cleaner than open() and read()... Don't get me wrong, it's good already ;-)
@MarkSetchell Sure, but OP says they have a data already. :)
D'oh! I better go put the kettle on - I clearly need more coffee!
0

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

1 Comment

Couldn't you just reinterpret an uint16 matrix as an uint8 array without any manual shifting?

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.