Reputation: 11
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
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
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