1

I have N 2D array with fixed size (5,3844) Now I want to stack them vertically as an images and as the result to have all images stacked together. I tried to do that using PIL but id didn't work with me . I do that but for numpy arras I used numpy to save 22 2D array each of size (5,3844) but I can't do this as an images. I am trying for more than 2 weeks to find how I can do it.

Any help would be appreciated.

signals=np.zeros((22,5,3844))
    t=0
    movement=int(S*256)
    if(S==0):
        movement=_SIZE_WINDOW_SPECTOGRAM        
    while data.shape[1]-(t*movement+_SIZE_WINDOW_SPECTOGRAM) > 0:
        for i in range(0, 22):
            start = t*movement
            stop = start+_SIZE_WINDOW_SPECTOGRAM
            signals[i,:]=wavelet(data[i,start:stop])
        if(signalsBlock is None):
            signalsBlock=np.array(signals)
        else:
            signalsBlock=np.append(signalsBlock, signals, axis=0)
Edayildiz
  • 545
  • 7
  • 16

2 Answers2

2

There are two parts to this question: first, how to concatenate or stack arrays, and second, how to save the result to file.

Concatenating or stacking arrays

Suppose you have N arrays in a Python list called arrays, each array being 2D and of shape (5, 3844). Then np.concatenate(arrays) concatenates the arrays vertically, resulting in a 2D array of shape (5*N, 3844). [Or to concatenate horizontally, you would do np.concatenate(arrays, axis=1).]

Alternatively, np.stack(arrays) will "stack" the arrays three dimensionally to produce an array of shape (N, 5, 3844). This works fine, but 3D data has more limited options for saving to file, as we discuss next.

Numpy reference:

Saving the array to file

There are many options of file format with different pros and cons. It depends how you will use the output to say which fits best in your case.

ND arrays:

  • Numpy .npy file: The easiest thing to do is save the array in numpy's native ".npy" file format. Simply np.save('out.npy', array) to save it, then later you can do array = np.load('out.npy') to read it back in. This should work with 2D or 3D or any array dimensionality and just about any dtype. The downside is that not much other software interoperates with the .npy format.

  • FITS image: An option with somewhat better software support is Flexible Image Transport System (FITS). For instance, GIMP can read and display FITS images. FITS supports any array dimensionality and various dtypes, including floats. One way to save a FITS image is with the astropy.io.fits library. Or since the format is intentionally simple, it's doable to implement a basic FITS reader/writer yourself.

2D or 3D arrays:

  • TIFF image: TIFF is extremely flexible. Unlike most image formats, it can store a wide range of dtypes, including floats, and can store an arbitrary number of image channels. So you can store a 3D array as a TIFF. Beware that not all software support the full extent of TIFF's features; I wouldn't expect many programs to nicely handle a float data TIFF with more than 3 channels, if at all. One way to write such TIFF images from Python is with tifffile. See SO post Save 32-bit floating point TIFF image. Beware that PIL wouldn't work for this, since it does not support images with more than 4 channels.

2D arrays:

  • CSV file: You can save a 2D array as a comma-separated values (CSV) file. This is easy to do with Python's csv library. CSV supports floats and lots of software interoperates with it. Another plus: it's human readable!

  • PNG image: The PNG format supports 8-bit or 16-bit unsigned integer samples, but not floats. So for this option you will need to cast your data to np.uint8 or np.uint16. On the plus side, tons of software supports PNG. You can use PIL to write an array as an 8-bit PNG with e.g.

    Image.fromarray(np.round(array).clip(0, 255).astype(np.uint8)).save('out.png')

    If you must have 16-bit, use the pypng library and see also SO post Can I save a numpy array as a 16-bit image using “normal” (Enthought) python?.

    Side note: Besides 2D data, PNG can store 2, 3, or 4 channels (gray+alpha, RGB, or RGBA). So you could store a 3D array as PNG if it's narrow enough in some dimension.

  • PGM image: The Portable GrayMap (PGM) format supports 8-bit or 16-bit samples, and it is widely supported. PIL can write 8-bit PGM. To write 16-bit PGM, see SO post Python and 16-bit PGM. PGM is an intentionally simple format and it's doable to code your own PGM reader/writer.

  • Other image formats?: There sure are a bunch of other image formats out there. But note that most support only 8-bit integer samples, so you're no better off than with one of the options above.

  • JPEG image?: Don't do this! Saving data as a JPEG image introduces lossy compression artifacts, even at max (100) quality level. Prefer a lossless format like PNG or PGM instead.

Pascal Getreuer
  • 2,906
  • 1
  • 5
  • 14
1

You can write a (22,5,3884) array of float32 to a TIFF like this:

import tifffile
import numpy as np 

# Synthesize image
signals = np.zeros((22,5,3844), dtype=np.float32)

# Save as TIFF
tifffile.imwrite('signals.tif', signals)

If you check the result with tiffinfo:

tiffinfo signals.tif

you can see there are 22 images in the file, each one a 3844x5 greyscale image of 32-bit IEEE-754 floating point.

Sample Output

TIFF Directory at offset 0x8 (8)
  Image Width: 3844 Image Length: 5
  Resolution: 1, 1 (unitless)
  Bits/Sample: 32
  Sample Format: IEEE floating point
  Compression Scheme: None
  Photometric Interpretation: min-is-black
  Samples/Pixel: 1
  Rows/Strip: 5
  Planar Configuration: single image plane
  ImageDescription: {"shape": [22, 5, 3844]}
  Software: tifffile.py
TIFF Directory at offset 0x19d020 (1691680)
  ... abbreviated, but as above ...
TIFF Directory at offset 0x19d0d2 (1691858)
  ... abbreviated, but as above ...
TIFF Directory at offset 0x19d184 (1692036)
  ... abbreviated, but as above ...
TIFF Directory at offset 0x19d236 (1692214)
TIFF Directory at offset 0x19d2e8 (1692392)
TIFF Directory at offset 0x19d39a (1692570)
TIFF Directory at offset 0x19d44c (1692748)
TIFF Directory at offset 0x19d4fe (1692926)
TIFF Directory at offset 0x19d5b0 (1693104)
TIFF Directory at offset 0x19d662 (1693282)
TIFF Directory at offset 0x19d714 (1693460)
TIFF Directory at offset 0x19d7c6 (1693638)
TIFF Directory at offset 0x19d878 (1693816)
TIFF Directory at offset 0x19d92a (1693994)
TIFF Directory at offset 0x19d9dc (1694172)
TIFF Directory at offset 0x19da8e (1694350)
TIFF Directory at offset 0x19db40 (1694528)
TIFF Directory at offset 0x19dbf2 (1694706)
TIFF Directory at offset 0x19dca4 (1694884)
TIFF Directory at offset 0x19dd56 (1695062)
TIFF Directory at offset 0x19de08 (1695240)

If you want the signals stacked one-above-the-other vertically, you can reshape() like this:

tifffile.imwrite('signals.tif', signals.reshape(110,3844))

I made each of the 22 sub-images a solid grey that increases down the stack so you can see the image is dark at the top and light at the bottom:

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432