forked from lbrabec/decorrstretch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathds.py
55 lines (51 loc) · 1.62 KB
/
ds.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import numpy as np
from functools import reduce
def decorrstretch(A, tol=None):
"""
Apply decorrelation stretch to image
Arguments:
A -- original image as numpy.array.
tol -- specify a linear contrast stretch, e.g. 0.01.
"""
# save the original shape
orig_shape = A.shape
# reshape the image
# B G R
# pixel 1 .
# pixel 2 .
# . . . .
A = A.reshape((-1,3)).astype(np.float)
# covariance matrix of A
cov = np.cov(A.T)
# source and target sigma
sigma = np.diag(np.sqrt(cov.diagonal()))
# eigen decomposition of covariance matrix
eigval, V = np.linalg.eig(cov)
# stretch matrix
S = np.diag(1/np.sqrt(eigval))
# compute mean of each color
mean = np.mean(A, axis=0)
# substract the mean from image
A -= mean
# compute the transformation matrix
T = reduce(np.dot, [sigma, V, S, V.T])
# compute offset
offset = mean - np.dot(mean, T)
# transform the image
A = np.dot(A, T)
# add the mean and offset
A += mean + offset
# restore original shape
B = A.reshape(orig_shape)
# for each color...
for b in range(3):
# apply contrast stretching if requested
if tol:
# find lower and upper limit for contrast stretching
low, high = np.percentile(B[:,:,b], 100*tol), np.percentile(B[:,:,b], 100-100*tol)
B[B<low] = low
B[B>high] = high
# ...rescale the color values to 0..255
B[:,:,b] = 255 * (B[:,:,b] - B[:,:,b].min())/(B[:,:,b].max() - B[:,:,b].min())
# return it as uint8 (byte) image
return B.astype(np.uint8)