user3005915
user3005915

Reputation: 11

How to use python to read timeseries from stack of images?

I am trying to read a stack of images into a 3-d matrix (e.g. X, Y, Z). The objective is to go across the entire image (from (X1, Y1) to (Xn, Yn). At each position e.g. (X1, Y3), I want to read the entire Z array and do some processing on it. One output image for example would contain the result of the calculation.

As an example, let's say that I have 12 (3x3) images with reflectance data, each image gives the reflectance of a month.

Image 1:

   X1 X2 X3
Y1 10 10 14
Y2 12 14 16
Y3 10 19 17

Image 2:

   20 21 23
   20 23 29
   21 22 21

. . .

Image 7:

   50 50 60
   60 70 60
   65 67 80

. . .

Image 12:

   X1 X2 X3
Y1 10 11 12
Y2 10 16 17
Y3 12 13 14

So, at the end, I want to read the z-array at each (X,Y) location. starting at (X1,Y1) and ending at (X12, y12). At (X1, Y3) for example, the Z-array would be: [10, 21, ., ., ., 65, ., ., ., 12]. I will apply some functions on the array, for example, the maximum value of the array. The value of the new output image for location (X1,Y3) would be 65 for example.

I have done something similar in IDL, using the ENVI image processing library. But I really would want to do this with python as my objective is to switch to open source languages. I just started to use python, and my search so far has not given me any solution, reason why I am reaching out to help from more experienced python users.

Thank you very much, Angela

Upvotes: 1

Views: 2009

Answers (2)

alko
alko

Reputation: 48317

One option is to use pandas, with it it would be easy to:

Load data:

import pandas as pd
from StringIO import StringIO
data1 = """   X1 X2 X3
Y1 10 10 14
Y2 12 14 16
Y3 10 19 17"""
df1 = pd.DataFrame.from_csv(StringIO(data1), sep='\s+')

data12 = """   X1 X2 X3
Y1 10 11 12
Y2 10 16 17
Y3 12 13 14"""
df12 = pd.DataFrame.from_csv(StringIO(data12), sep='\s+')

To create a 3d Panel

panel = pd.Panel([df1.values,df12.values], items = ['image1','image12'], major_axis=df1.columns, minor_axis=df1.index)

To make some evaluations along different axis of resulting 3d object:

>>>   import numpy as np 
>>> panel.apply(np.average, axis=0)
    Y1    Y2    Y3
X1  10  10.5  13.0
X2  11  15.0  16.5
X3  11  16.0  15.5

>>> panel.apply(np.max, axis=1)
    image1  image12
Y1      12       12
Y2      19       16
Y3      17       17

>>> panel.apply(np.min, axis=2).T
         X1  X2  X3
image1   10  12  10
image12  10  10  12

Upvotes: 1

Hannes Ovrén
Hannes Ovrén

Reputation: 21831

Using numpy this is actually very easy, so I'll just give you some code right away. Note that it is not going to necessarily be the full solution.

import numpy as np
import cv2

image_files = [] # Your list of files
image_height = 3
image_width = 3
image_stack = np.empty((image_height, image_width, len(image_files))) # Create empty HxWxN array/matrix

for i, fname in enumerate(image_files):
    img = cv2.imread(fname, cv2.CV_LOAD_IMAGE_GRAYSCALE)
    image_stack[:,:,i] = img # Set the i:th slice to this image

mean_img = np.mean(image_stack, axis=2) # Take the mean for each pixel

Since we only use OpenCV for image loading, you could of course switch that with something else, as long as it gives you a numpy-array.

If you have questions, give a comment and I'll update accordingly.

Upvotes: 6

Related Questions