Rectified image: interpolate missing points - python

I have an image that I try to rotate around an x, y and z axis (rectification). This works fine, but I loose a lot of data. This is the script I use:
# import libraries
import numpy as np
# import dateutil
# import pyparsing
import matplotlib.pyplot as plt
import cv2
import sys
from scipy import *
import Image
import matrotation as rmat
import math
from scipy.interpolate import griddata
# set variable with location of files
working_dir = 'C:\Users\Yorian\Desktop\TU\Stage Shore\python_files\Rectification'
sys.path.append(working_dir)
# C is 3x1 matrix met (Xc, Yc, Zc).transpose()
# neem voor nu: C is nulvector
C = np.zeros((3,1), dtype='float32')
# 3x3 Identity matrix
I = np.identity(3)
# k matrix 3x3, LOAD the center pixel automatically as the point to rate around
K = np.array([[1.49661077e+04, -4.57744650e-13, 0.0],
[0.0, -1.49661077e+04, 0.0],
[0.0, 0.0, 1.0]])
# rotatie matrix 1 (3x3) 0 graden om zowel x, y als z as
R1 = rmat.getR(25.0, 45.0, 0.0)
# [I|-C] (Zie Sierds paper) =
I_extended = np.hstack((I,C))
# P = K*R*I
P1 = K.dot(R1).dot(I_extended)
# rotatie matrix 2
R2 = rmat.getR(0.0, 0.0, 0.0)
P2 = K.dot(R2).dot(I_extended)
# Homography Matrix = H = P_rect * pinv(P) => P2 * pinv(P1)
H = P2.dot(np.linalg.pinv(P1))
# do image transform: x_uv_new = H * x_uv_original
# load image and convert it to grayscale (L)
img = Image.open('c5.jpg').convert('L')
# img.show()
img_array = np.array(img)
height = img_array.shape[0]
width = img_array.shape[1]
U, V = np.meshgrid(range(img_array.shape[1]),
range(img_array.shape[0]))
UV = np.vstack((U.flatten(),
V.flatten())).T
UV_warped = cv2.perspectiveTransform(np.array([UV]).astype(np.float32), H)
UV_warped = UV_warped[0]
UV_warped = UV_warped.astype(np.int)
x_translation = min(UV_warped[:,0])
y_translation = min(UV_warped[:,1])
new_width = np.amax(UV_warped[:,0])-np.amin(UV_warped[:,0])
new_height = np.amax(UV_warped[:,1])-np.amin(UV_warped[:,1])
# new_img_2 = cv2.warpPerspective(img_array, H, (new_height+1, new_width+1))
UV_warped[:,0] = UV_warped[:,0] - int(x_translation)
UV_warped[:,1] = UV_warped[:,1] - int(y_translation)
# create box for image
new_img = np.zeros((new_height+1, new_width+1)) # 0 = black 255 - white background
for uv_pix, UV_warped_pix in zip(UV, UV_warped):
x_orig = uv_pix[0] # x in origineel
y_orig = uv_pix[1] # y in origineel
color = img_array[y_orig, x_orig]
x_new = UV_warped_pix[0] # new x
y_new = UV_warped_pix[1] # new y
new_img[y_new, x_new] = np.array(color)
img = Image.fromarray(np.uint8(new_img))
img.save("testje.jpg")
This works fine. However I miss a lot of information. The larger the rotations the more information I loose. To get more information back I want to: interpolate the missing points. I tried to do this using grid(), but it returns an array that looks like this:
[nan]
The code for this:
# import libraries
import numpy as np
# import dateutil
# import pyparsing
import matplotlib.pyplot as plt
import cv2
import sys
from scipy import *
import Image
import matrotation as rmat
import math
from scipy.interpolate import griddata
# set variable with location of files
working_dir = 'C:\Users\Yorian\Desktop\TU\Stage Shore\python_files\Rectification'
sys.path.append(working_dir)
# C is 3x1 matrix met (Xc, Yc, Zc).transpose()
# neem voor nu: C is nulvector
C = np.zeros((3,1), dtype='float32')
# 3x3 Identity matrix
I = np.identity(3)
# k matrix 3x3, LOAD the center pixel automatically as the point to rate around
K = np.array([[1.49661077e+04, -4.57744650e-13, 0.0],
[0.0, -1.49661077e+04, 0.0],
[0.0, 0.0, 1.0]])
# rotatie matrix 1 (3x3) 0 graden om zowel x, y als z as
R1 = rmat.getR(25.0, 45.0, 0.0)
# [I|-C] (Zie Sierds paper) =
I_extended = np.hstack((I,C))
# P = K*R*I
P1 = K.dot(R1).dot(I_extended)
# rotatie matrix 2
R2 = rmat.getR(0.0, 0.0, 0.0)
P2 = K.dot(R2).dot(I_extended)
# Homography Matrix = H = P_rect * pinv(P) => P2 * pinv(P1)
H = P2.dot(np.linalg.pinv(P1))
# do image transform: x_uv_new = H * x_uv_original
# load image and convert it to grayscale (L)
img = Image.open('c5.jpg').convert('L')
# img.show()
img_array = np.array(img)
height = img_array.shape[0]
width = img_array.shape[1]
U, V = np.meshgrid(range(img_array.shape[1]),
range(img_array.shape[0]))
UV = np.vstack((U.flatten(),
V.flatten())).T
UV_warped = cv2.perspectiveTransform(np.array([UV]).astype(np.float32), H)
UV_warped = UV_warped[0]
UV_warped = UV_warped.astype(np.int)
x_translation = min(UV_warped[:,0])
y_translation = min(UV_warped[:,1])
new_width = np.amax(UV_warped[:,0])-np.amin(UV_warped[:,0])
new_height = np.amax(UV_warped[:,1])-np.amin(UV_warped[:,1])
UV_warped[:,0] = UV_warped[:,0] - int(x_translation)
UV_warped[:,1] = UV_warped[:,1] - int(y_translation)
# create box for image
data = np.zeros((len(UV_warped),1))
for i, uv_pix in enumerate(UV):
data[i,0] = img_array[uv_pix[1], uv_pix[0]]
grid = griddata(UV_warped, data, (new_width+1, new_height+1), method='linear')
Can anybody help me to get an image from this that is interpolated?
BTW: I used the function warpPerspective as someone has told me, but this stretches the image but doesn't "rotate" it.
I also looked at cv2.inpaint() but can't get that to work either. I found this: http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_photo/py_inpainting/py_inpainting.html but that plots it. I want to make an image of it.
EDIT:
The code I used to do this with warpTransform:
#Importing modules
import json
import urllib2
import numpy as np
import cv2
from scipy import *
import Image
# data is now a dictionairy containing list with dictionairies with the x, y, z, U, V
# example:
# data[cameraID][listnumber] = {'x': x, 'y': y, 'z': z, 'U': U, 'V': V}
T = {} # H is a list of Translation matrices, one for each camera
for cam in data:
if len(cam) > 4:
xyz_ar = np.array([[data[cam][0]['x'], data[cam][0]['y']],
[data[cam][1]['x'], data[cam][1]['y']],
[data[cam][2]['x'], data[cam][2]['y']],
[data[cam][3]['x'], data[cam][3]['y']]],np.float32)
UV_ar = np.array([[data[cam][0]['U'], data[cam][0]['V']],
[data[cam][1]['U'], data[cam][1]['V']],
[data[cam][2]['U'], data[cam][2]['V']],
[data[cam][3]['U'], data[cam][3]['V']]], np.float32)
T[cam] = cv2.getPerspectiveTransform(UV_ar, xyz_ar)
else:
print('niet genoeg meetpunten voor de camera')
# load image
img = cv2.imread('c5.jpg')
rows, cols, channels = img.shape
# warp voor camera 5
dst = cv2.warpPerspective(img, T[u'KDXX05C'], (rows, cols))
new_img = Image.fromarray(np.uint8(dst))
new_img.save('testje.jpg')

I am still convinced that warpPerspective does exactly what you want (jedi mind trick). Seriously, it should do in one line what you are trying to achieve with the meshgrid, vstack and griddata.
Can you try the following code ? (I am not familiar with Python, so this might require some adjustements) :
# load image and convert it to grayscale (L)
img = cv2.imread('c5.jpg')
rows, cols, channels = img.shape
# img.show()
# Homography Matrix = H = P_rect * pinv(P) => P2 * pinv(P1)
H = P2.dot(np.linalg.pinv(P1))
cv2.warpPerspective(img, H, (rows, cols), dst, cv2.INTER_LINEAR)
new_img = Image.fromarray(np.uint8(dst))
new_img.save('testje.jpg')
where H is the exact same matrix as you use in the first code sample you gave.

The third argument of griddata is a (M,D) shaped array of locations that need interpolation (D=2 here). You are inputting a tuple of (width, height), so that is probably why you get a [nan] array.

Related

vectorizing custom python function with numpy array

Not sure if that is the correct terminology. Basically trying to take a black and white image and first transform it such that all the white pixels that border black-pixels remain white, else turn black. That part of the program works fine, and is done in find_edges. Next I need to calculate the distance from each element in the image to the closest white-pixel. Right now I am doing it by using a for-loop that is insanely slow. Is there a way to make the find_nearest_edge function written solely with numpy without the need for a for-loop to call it on each element? Thanks.
####
from PIL import Image
import numpy as np
from scipy.ndimage import binary_erosion
####
def find_nearest_edge(arr, point):
w, h = arr.shape
x, y = point
xcoords, ycoords = np.meshgrid(np.arange(w), np.arange(h))
target = np.sqrt((xcoords - x)**2 + (ycoords - y)**2)
target[arr == 0] = np.inf
shortest_distance = np.min(target[target > 0.0])
return shortest_distance
def find_edges(img):
img = img.convert('L')
img_np = np.array(img)
kernel = np.ones((3,3))
edges = img_np - binary_erosion(img_np, kernel)*255
return edges
a = Image.open('a.png')
x, y = a.size
edges = find_edges(a)
out = Image.fromarray(edges.astype('uint8'), 'L')
out.save('b.png')
dists =[]
for _x in range(x):
for _y in range(y):
dist = find_nearest_edge(edges,(_x,_y))
dists.append(dist)
print(dists)
Images:
You can use KDTree to compute distances fast.
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import binary_erosion
from scipy.spatial import KDTree
def find_edges(img):
img_np = np.array(img)
kernel = np.ones((3,3))
edges = img_np - binary_erosion(img_np, kernel)*255
return edges
def find_closest_distance(img):
# NOTE: assuming input is binary image and white is any non-zero value!
white_pixel_points = np.array(np.where(img))
tree = KDTree(white_pixel_points.T)
img_meshgrid = np.array(np.meshgrid(np.arange(img.shape[0]), np.arange(img.shape[1]))).T
distances, _ = tree.query(img_meshgrid)
return distances
test_image = np.zeros((200, 200))
rectangle = np.ones((30, 80))
test_image[20:50, 60:140] = rectangle
test_image[150:180, 60:140] = rectangle
test_image[60:140, 20:50] = rectangle.T
test_image[60:140, 150:180] = rectangle.T
test_image = test_image * 255
edge_image = find_edges(test_image)
distance_image = find_closest_distance(edge_image)
fig, axes = plt.subplots(1, 3, figsize=(12, 5))
axes[0].imshow(test_image, cmap='Greys_r')
axes[1].imshow(edge_image, cmap='Greys_r')
axes[2].imshow(distance_image, cmap='Greys_r')
plt.show()
You can make your code 25X faster by just changing find_nearest_edge as follows. Many other optimizations are possible, but this is the biggest bottleneck in your code.
from numba import njit
#njit
def find_nearest_edge(arr, point):
x, y = point
shortest_distance = np.inf
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if arr[i,j] == 0: continue
shortest_distance = min(shortest_distance, (i-x)**2 + (j-y)**2)
return np.sqrt(shortest_distance)

Convolution on Python

So I suppose to calculate the convolution between Fourier Transformed image and the mask.
from scipy import fftpack
import numpy as np
import imageio
from PIL import Image, ImageDraw
import cv2
import matplotlib.pyplot as plt
import math
from scipy.ndimage.filters import convolve
input_image = Image.open('....image....')
input_image=np.array(input_image)
M,N = input_image.shape[0],input_image.shape[1]
FT_img = fftpack.fftshift(fftpack.fft2(input_image))
n = 2; # order value can change this value accordingly
D0 = 60; # cut-off frequency can change this value accordingly
# Designing filter
u = np.arange(0, M)
idx = u > M/2
u[idx] = u[idx] - M
v = np.arange(0, N)
idy = v > N/2
v[idy] = v[idy] - N
V,U = np.meshgrid(v,u)
# Calculating Euclidean Distance
D=np.linalg.norm(V-U)
# determining the filtering mask
H = 1/(1 + (D0/D)**(2*n));
# Convolution between the Fourier Transformed image and the mask
G = convolve(H, FT_img)
And I get "Runtime error:filter weights array has incorrect shape." error at the last line when I run this code snippet. What I understand is H is float and FT_img is array so I cannot perform convolution on these. But I don't know how to solve that.
How can I solve this problem?
calculating distance D, and filter H for each (u, v) this will yield an array with same size of input image, multiplying that array(H the Filter) with the image in Fourier Domain will be equivalent to convolution in the Time domain, and the results will be as following:
import numpy as np
import cv2
import matplotlib.pyplot as plt
# Read Image as Grayscale
img = cv2.imread('input.png', 0)
# Designing filter
#------------------------------------------------------
def butterworth_filter(shape, n=2, D0=60):
'''
n = 2; # order value can change this value accordingly
D0 = 60; # cut-off frequency can change this value accordingly
'''
M, N = shape
# Initialize filter with zeros
H = np.zeros((M, N))
# Traverse through filter
for u in range(0, M):
for v in range(0, N):
# Get euclidean distance from point D(u,v) to the center
D_uv = np.sqrt((u - M / 2) ** 2 + (v - N / 2) ** 2)
# determining the filtering mask
H[u, v] = 1/(1 + (D0/D_uv)**(2*n))
return H
#-----------------------------------------------------
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
phase_spectrumR = np.angle(fshift)
magnitude_spectrum = 20*np.log(np.abs(fshift))
# Generate Butterworth Filter
H = butterworth_filter(img.shape)
# Convolution between the Fourier Transformed image and the mask
G = H * fshift
# Obtain the Result
result = np.abs(np.fft.ifft2(np.fft.ifftshift((G))))
plt.subplot(222)
plt.imshow(img, cmap='gray')
plt.title('Original')
plt.axis('off')
plt.subplot(221)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('magnitude spectrum')
plt.axis('off')
plt.subplot(223)
plt.imshow(H, "gray")
plt.title("Butterworth Filter")
plt.axis('off')
plt.subplot(224)
plt.imshow(result, "gray")
plt.title("Result")
plt.axis('off')
plt.show()

python program to fade an image in radial direction

I am trying to write a program which fades an image in radial direction. which means as we move away from the centre of the image, the pixels fade to black. For this, I have written five different functions:
center: returns coordinate pair (center_y, center_x) of the image center.
radial_distance: returns for image with width w and height h an array with shape (h,w), where the number at index (i,j) gives the euclidean distance from the point (i,j) to the center of the image.
scale: returns a copy of the array 'a' (or image) with its elements scaled to be in the given range.
radial_mask: takes an image as a parameter and returns an array with same height and width filled with values between 0.0 and 1.0.
radial_fade: returns the image multiplied by its radial mask.
The program is:
import numpy as np
import matplotlib.pyplot as plt
def center(a):
y, x = a.shape[:2]
return ((y-1)/2,(x-1)/2) # note the order: (center_y, center_x)
def radial_distance(b):
h, w = b.shape[:2]
y, x = center(b)
o = b[:h,:w,0]
for i in range(h):
for j in range(w):
o[i,j] = np.sqrt((y-i)**2 + (x-j)**2)
return o
def scale(c, tmin=0.0, tmax=1.0):
"""Returns a copy of array 'a' with its values scaled to be in the range
[tmin,tmax]."""
mini, maxi = c.min(), c.max()
if maxi == 0:
return 0
else:
m = (tmax - tmin)/(maxi - mini)
f = tmin - m*mini
return c*m + f
def radial_mask(d):
f = radial_distance(d)
g = scale(f, tmin=0.0, tmax=1.0)
# f = g[:,:,0]
n = 1.0 - g
return n
def radial_fade(l):
f, g = l.shape[:2]
q = l[:f,:g,0]
return q * radial_mask(l)
image = plt.imread("src/painting.png")
fig, ax = plt.subplots(3)
masked = radial_mask(ima)
faded = radial_fade(ima)
ax[0].imshow(ima)
ax[1].imshow(masked)
ax[2].imshow(faded)
plt.show()
there is something wrong somewhere in the code as it does not do the expected job.
One problem is that in
o = b[:h,:w,0]
you're using the same precision as the image that may be integers (e.h. uint8).
You should use for example
o = np.zeros((h, w), np.float32)

Independent component analysis to separate objects from frame

I have 200 frames of (100*100 ) each in a numpy array of (200, 100, 100).
The frames have circles at random positions, mixed with noise. I want to extract the circles from these frames using Independent Component analysis.
I tried working it with sklearn FastICA, it gives random mixed frame instead of separated out circles.
I was expecting each linear combination(lc_test) to give circles (separated out) from each frame but it is giving random frames.
input: output code is giving (incorrect):
import numpy as np
import random
from sklearn.decomposition import FastICA, PCA
#Creating Data
def createCircle(width,height , rad ):
w = random.randint(1, height)
h = random.randint(1, height)
center = [int(w), int(h)]
radius = rad
Y, X = np.ogrid[:height, :width]
dist_from_center = np.sqrt((X - center[0])**2 + (Y-center[1])**2)
mask = dist_from_center <= radius
return mask
def addCircle(test_image):
m = createCircle(width = 100, height = 100 , rad = 8 )
masked_img = test_image.copy()
masked_img[m] = 0
return masked_img
def noise(image):
row,col= image.shape
mean = 0
var = 0.1
sigma = var**0.5
gauss = np.random.normal(mean,sigma,(row,col))
gauss = gauss.reshape(row,col)
noisy = image + gauss #adding gauss noise
s1 = np.sin(8) #adding sin fill
noisy += s1
return noisy
img = np.zeros([100,100],dtype=np.uint8)
img.fill(20)
img_test = img
#Making 200 frames
ims = np.zeros((200, 100, 100)) # initialize your array
for i in range(1,200):
for j in range(1,5):
img_test = addCircle(test_image=img_test)
im1 = noise(img_test)
img_test = img
ims[i, ...] = im1
print(ims.shape) #(200,100,100)
#Apply Independent Component Analysis on ims
ims_flat = ims.reshape(200,10000)
ica_test = FastICA(max_iter = 3000, tol = 0.3)
s_test= ica_test.fit_transform(ims_flat.T) #source matrix
print(s_test.shape) #(10000, 200)
a_test = ica_test.mixing_ #mixing matrix
print(a_test.shape) #(200, 200)
#unmixing matrix : inverse of mixing matrix
w_test = np.linalg.inv(a_test) #unmixing matrix
print(w_test.shape) #(200, 200)
#Taking Linear combination of unmixing matrix and ims_flat(original) to extract Independent components
lc_test = np.linalg.solve(w_test, ims_flat) #Linear combinations
print(lc_test.shape) #(200, 10000)
#plotting Linear combinations
for i in range(1,200): #Does not extract circles
plt.imshow(lc_test[i,:].reshape(100, 100))
plt.show()
The goal is to extract/separate circles from all 200 frames.

Implementing GLCM texture feature with scikit-image and Python

I am trying to implement a texture image as described in this tutorial using Python and skimage.
The issue is to move a 7x7 window over a large raster and replace the center of each pixel with the calculated texture from the 7x7 window. I manage to do this with the code below, but I see no other way than looping through each individual pixel, which is very slow.
One software package does that in a few seconds, so there must be some other way ... is there?
Here the code that works but is very slow ...
import matplotlib.pyplot as plt
import gdal, gdalconst
import numpy as np
from skimage.feature import greycomatrix, greycoprops
filename = "//mnt//glaciology//RS2_20140101.jpg"
outfilename = "//home//max//Documents//GLCM_contrast.tif"
sarfile = gdal.Open(filename, gdalconst.GA_ReadOnly)
sarraster = sarfile.ReadAsArray()
#sarraster is satellite image, testraster will receive texture
testraster = np.copy(sarraster)
testraster[:] = 0
for i in range(testraster.shape[0] ):
print i,
for j in range(testraster.shape[1] ):
#windows needs to fit completely in image
if i <3 or j <3:
continue
if i > (testraster.shape[0] - 4) or j > (testraster.shape[0] - 4):
continue
#Calculate GLCM on a 7x7 window
glcm_window = sarraster[i-3: i+4, j-3 : j+4]
glcm = greycomatrix(glcm_window, [1], [0], symmetric = True, normed = True )
#Calculate contrast and replace center pixel
contrast = greycoprops(glcm, 'contrast')
testraster[i,j]= contrast
sarplot = plt.imshow(testraster, cmap = 'gray')
Results:
I had the same problem, different data. Here is a script I wrote that uses parallel processing and a sliding window approach:
import gdal, osr
import numpy as np
from scipy.interpolate import RectBivariateSpline
from numpy.lib.stride_tricks import as_strided as ast
import dask.array as da
from joblib import Parallel, delayed, cpu_count
import os
from skimage.feature import greycomatrix, greycoprops
def im_resize(im,Nx,Ny):
'''
resize array by bivariate spline interpolation
'''
ny, nx = np.shape(im)
xx = np.linspace(0,nx,Nx)
yy = np.linspace(0,ny,Ny)
try:
im = da.from_array(im, chunks=1000) #dask implementation
except:
pass
newKernel = RectBivariateSpline(np.r_[:ny],np.r_[:nx],im)
return newKernel(yy,xx)
def p_me(Z, win):
'''
loop to calculate greycoprops
'''
try:
glcm = greycomatrix(Z, [5], [0], 256, symmetric=True, normed=True)
cont = greycoprops(glcm, 'contrast')
diss = greycoprops(glcm, 'dissimilarity')
homo = greycoprops(glcm, 'homogeneity')
eng = greycoprops(glcm, 'energy')
corr = greycoprops(glcm, 'correlation')
ASM = greycoprops(glcm, 'ASM')
return (cont, diss, homo, eng, corr, ASM)
except:
return (0,0,0,0,0,0)
def read_raster(in_raster):
in_raster=in_raster
ds = gdal.Open(in_raster)
data = ds.GetRasterBand(1).ReadAsArray()
data[data<=0] = np.nan
gt = ds.GetGeoTransform()
xres = gt[1]
yres = gt[5]
# get the edge coordinates and add half the resolution
# to go to center coordinates
xmin = gt[0] + xres * 0.5
xmax = gt[0] + (xres * ds.RasterXSize) - xres * 0.5
ymin = gt[3] + (yres * ds.RasterYSize) + yres * 0.5
ymax = gt[3] - yres * 0.5
del ds
# create a grid of xy coordinates in the original projection
xx, yy = np.mgrid[xmin:xmax+xres:xres, ymax+yres:ymin:yres]
return data, xx, yy, gt
def norm_shape(shap):
'''
Normalize numpy array shapes so they're always expressed as a tuple,
even for one-dimensional shapes.
'''
try:
i = int(shap)
return (i,)
except TypeError:
# shape was not a number
pass
try:
t = tuple(shap)
return t
except TypeError:
# shape was not iterable
pass
raise TypeError('shape must be an int, or a tuple of ints')
def sliding_window(a, ws, ss = None, flatten = True):
'''
Source: http://www.johnvinyard.com/blog/?p=268#more-268
Parameters:
a - an n-dimensional numpy array
ws - an int (a is 1D) or tuple (a is 2D or greater) representing the size
of each dimension of the window
ss - an int (a is 1D) or tuple (a is 2D or greater) representing the
amount to slide the window in each dimension. If not specified, it
defaults to ws.
flatten - if True, all slices are flattened, otherwise, there is an
extra dimension for each dimension of the input.
Returns
an array containing each n-dimensional window from a
'''
if None is ss:
# ss was not provided. the windows will not overlap in any direction.
ss = ws
ws = norm_shape(ws)
ss = norm_shape(ss)
# convert ws, ss, and a.shape to numpy arrays
ws = np.array(ws)
ss = np.array(ss)
shap = np.array(a.shape)
# ensure that ws, ss, and a.shape all have the same number of dimensions
ls = [len(shap),len(ws),len(ss)]
if 1 != len(set(ls)):
raise ValueError(\
'a.shape, ws and ss must all have the same length. They were %s' % str(ls))
# ensure that ws is smaller than a in every dimension
if np.any(ws > shap):
raise ValueError(\
'ws cannot be larger than a in any dimension.\
a.shape was %s and ws was %s' % (str(a.shape),str(ws)))
# how many slices will there be in each dimension?
newshape = norm_shape(((shap - ws) // ss) + 1)
# the shape of the strided array will be the number of slices in each dimension
# plus the shape of the window (tuple addition)
newshape += norm_shape(ws)
# the strides tuple will be the array's strides multiplied by step size, plus
# the array's strides (tuple addition)
newstrides = norm_shape(np.array(a.strides) * ss) + a.strides
a = ast(a,shape = newshape,strides = newstrides)
if not flatten:
return a
# Collapse strided so that it has one more dimension than the window. I.e.,
# the new array is a flat list of slices.
meat = len(ws) if ws.shape else 0
firstdim = (np.product(newshape[:-meat]),) if ws.shape else ()
dim = firstdim + (newshape[-meat:])
# remove any dimensions with size 1
dim = filter(lambda i : i != 1,dim)
return a.reshape(dim), newshape
def CreateRaster(xx,yy,std,gt,proj,driverName,outFile):
'''
Exports data to GTiff Raster
'''
std = np.squeeze(std)
std[np.isinf(std)] = -99
driver = gdal.GetDriverByName(driverName)
rows,cols = np.shape(std)
ds = driver.Create( outFile, cols, rows, 1, gdal.GDT_Float32)
if proj is not None:
ds.SetProjection(proj.ExportToWkt())
ds.SetGeoTransform(gt)
ss_band = ds.GetRasterBand(1)
ss_band.WriteArray(std)
ss_band.SetNoDataValue(-99)
ss_band.FlushCache()
ss_band.ComputeStatistics(False)
del ds
#Stuff to change
if __name__ == '__main__':
win_sizes = [7]
for win_size in win_sizes[:]:
in_raster = #Path to input raster
win = win_size
meter = str(win/4)
#Define output file names
contFile =
dissFile =
homoFile =
energyFile =
corrFile =
ASMFile =
merge, xx, yy, gt = read_raster(in_raster)
merge[np.isnan(merge)] = 0
Z,ind = sliding_window(merge,(win,win),(win,win))
Ny, Nx = np.shape(merge)
w = Parallel(n_jobs = cpu_count(), verbose=0)(delayed(p_me)(Z[k]) for k in xrange(len(Z)))
cont = [a[0] for a in w]
diss = [a[1] for a in w]
homo = [a[2] for a in w]
eng = [a[3] for a in w]
corr = [a[4] for a in w]
ASM = [a[5] for a in w]
#Reshape to match number of windows
plt_cont = np.reshape(cont , ( ind[0], ind[1] ) )
plt_diss = np.reshape(diss , ( ind[0], ind[1] ) )
plt_homo = np.reshape(homo , ( ind[0], ind[1] ) )
plt_eng = np.reshape(eng , ( ind[0], ind[1] ) )
plt_corr = np.reshape(corr , ( ind[0], ind[1] ) )
plt_ASM = np.reshape(ASM , ( ind[0], ind[1] ) )
del cont, diss, homo, eng, corr, ASM
#Resize Images to receive texture and define filenames
contrast = im_resize(plt_cont,Nx,Ny)
contrast[merge==0]=np.nan
dissimilarity = im_resize(plt_diss,Nx,Ny)
dissimilarity[merge==0]=np.nan
homogeneity = im_resize(plt_homo,Nx,Ny)
homogeneity[merge==0]=np.nan
energy = im_resize(plt_eng,Nx,Ny)
energy[merge==0]=np.nan
correlation = im_resize(plt_corr,Nx,Ny)
correlation[merge==0]=np.nan
ASM = im_resize(plt_ASM,Nx,Ny)
ASM[merge==0]=np.nan
del plt_cont, plt_diss, plt_homo, plt_eng, plt_corr, plt_ASM
del w,Z,ind,Ny,Nx
driverName= 'GTiff'
epsg_code=26949
proj = osr.SpatialReference()
proj.ImportFromEPSG(epsg_code)
CreateRaster(xx, yy, contrast, gt, proj,driverName,contFile)
CreateRaster(xx, yy, dissimilarity, gt, proj,driverName,dissFile)
CreateRaster(xx, yy, homogeneity, gt, proj,driverName,homoFile)
CreateRaster(xx, yy, energy, gt, proj,driverName,energyFile)
CreateRaster(xx, yy, correlation, gt, proj,driverName,corrFile)
CreateRaster(xx, yy, ASM, gt, proj,driverName,ASMFile)
del contrast, merge, xx, yy, gt, meter, dissimilarity, homogeneity, energy, correlation, ASM
This script calculates GLCM properties for a defined window size, with no overlap between adjacent windows.

Categories