-
Notifications
You must be signed in to change notification settings - Fork 1
/
algorithm_rgb.py
193 lines (143 loc) · 6.52 KB
/
algorithm_rgb.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
"""Greenness Transformer
"""
# Importing modules.
import numpy as np
# Definitions
VERSION = '1.0'
# Information on the creator of this algorithm
ALGORITHM_AUTHOR = 'Chris Schnaufer, Clairessa Brown, David Lebauer'
ALGORITHM_AUTHOR_EMAIL = 'schnaufer@arizona.edu, clairessabrown@email.arizona.edu, dlebauer@email.arizona.edu'
ALGORITHM_CONTRIBUTORS = ["Jacob van der Leeuw"]
ALGORITHM_NAME = 'Greenness Transformer'
ALGORITHM_DESCRIPTION = 'This algorithm performs a variety of calculations using RGB pixels from images in order' \
'to assess plant and crop health and growth'
# Citation information for publication
CITATION_AUTHOR = 'Clairessa Brown'
CITATION_TITLE = 'Woebbecke, D.M. et al'
CITATION_YEAR = '2020'
# The name of one or more variables returned by the algorithm, separated by commas
VARIABLE_NAMES = 'excess greenness index, green leaf index, cive, normalized difference index, excess red, ' \
'exgr, combined indices 1, combined indices 2, vegetative index, normalized green-red difference,' \
' percent green'
# Variable units matching the order of VARIABLE_NAMES, also comma-separated.
VARIABLE_UNITS = '[-510:510], [-1:1], [-255:255], [-127:129], [-255:255], [-255:332], ' \
'[-1000:1000], [-1000:1000], [-255:255], [-255:255], [0:100]'
# Variable labels matching the order of VARIABLE_NAMES, also comma-separated.
VARIABLE_LABELS = 'excess_greenness_index, green_leaf_index, cive, normalized_difference_index(pxarray), ' \
'excess_red, exgr, combined_indices_1, combined_indices_2, vegetative_index, ngrdi, percent_green'
# Entry point for plot-level RBG algorithm
def excess_greenness_index(pxarray: np.ndarray) -> float:
"""
Minimizes variation between different illuminations and enhances detection
of plants
"""
red, green, blue = get_red_green_blue_averages(pxarray)
return round(2 * green - (red + blue), 2)
def green_leaf_index(pxarray: np.ndarray) -> float:
"""
Calculates the green leaf index of an image
"""
red, green, blue = get_red_green_blue_averages(pxarray)
return round((2 * green - red - blue) / (2 * green + red + blue), 2)
def cive(pxarray: np.ndarray) -> float:
"""
Can measure crop growth status
"""
red, green, blue = get_red_green_blue_averages(pxarray)
return round(0.441 * red - 0.811 * green + 0.385 * blue + 18.78745, 2)
def normalized_difference_index(pxarray: np.ndarray) -> float:
"""
Calculates the normalized difference index of an image
"""
red, green, _ = get_red_green_blue_averages(pxarray)
return round(128 * ((green - red) / (green + red)) + 1, 2)
def excess_red(pxarray: np.ndarray) -> float:
"""
Finds potential illumination issues that make it difficult to
tease apart redness from crops/leaves from soil or camera
artifacts
"""
red, green, _ = get_red_green_blue_averages(pxarray)
return round(1.3 * red - green, 2)
def exgr(pxarray: np.ndarray) -> float:
"""
Minimizes the variation between different illuminations
"""
return round(excess_greenness_index(pxarray) - excess_red(pxarray), 2)
def combined_indices_1(pxarray: np.ndarray) -> float:
"""
Combined indices calculation 1
"""
return round(excess_greenness_index(pxarray) + cive(pxarray), 2)
def combined_indices_2(pxarray: np.ndarray) -> float:
"""
Combined indices calculation 2
"""
return round(0.36 * excess_greenness_index(pxarray) + 0.47 * cive(pxarray) + 0.17 * vegetative_index(pxarray), 2)
def vegetative_index(pxarray: np.ndarray) -> float:
"""
Minimize illumination differences between images
"""
red, green, blue = get_red_green_blue_averages(pxarray)
return round(green / ((red ** 0.667) * (blue ** .333)), 2)
def ngrdi(pxarray: np.ndarray) -> float:
"""
Can measure crop growth status
"""
red, green, _ = get_red_green_blue_averages(pxarray)
return round((green - red) / (green + red), 2)
def percent_green(pxarray: np.ndarray) -> float:
"""
Returns the percentage of an image that is green, which can be used
to identify plant cover
"""
if pxarray.shape[2] < 4:
# Get redness, greenness, and blueness values
red = np.sum(pxarray[:, :, 0])
green = np.sum(pxarray[:, :, 1])
blue = np.sum(pxarray[:, :, 2])
else:
# Handle Alpha channel masking
# Get redness, greenness, and blueness values
alpha_mask = np.where(pxarray[:, :, 3] == 0, 1, 0) # Convert alpha channel to numpy.ma acceptable format
channel_masked = np.ma.array(pxarray[:, :, 0], mask=alpha_mask)
red = np.ma.sum(channel_masked)
channel_masked = np.ma.array(pxarray[:, :, 1], mask=alpha_mask)
green = np.ma.sum(channel_masked)
channel_masked = np.ma.array(pxarray[:, :, 2], mask=alpha_mask)
blue = np.ma.sum(channel_masked)
del channel_masked
return round(green / (red + green + blue), 2)
def get_red_green_blue_averages(pxarray: np.ndarray) -> tuple:
"""
Returns the average red, green, and blue values in a pxarray object
"""
if pxarray.shape[2] < 4:
# Get redness, greenness, and blueness values
red = np.average(pxarray[:, :, 0])
green = np.average(pxarray[:, :, 1])
blue = np.average(pxarray[:, :, 2])
else:
# Handle Alpha channel masking
# Get redness, greenness, and blueness values
alpha_mask = np.where(pxarray[:, :, 3] == 0, 1, 0) # Convert alpha channel to numpy.ma acceptable format
channel_masked = np.ma.array(pxarray[:, :, 0], mask=alpha_mask)
red = np.ma.average(channel_masked)
channel_masked = np.ma.array(pxarray[:, :, 1], mask=alpha_mask)
green = np.ma.average(channel_masked)
channel_masked = np.ma.array(pxarray[:, :, 2], mask=alpha_mask)
blue = np.ma.average(channel_masked)
del channel_masked
return red, green, blue
def calculate(pxarray: np.ndarray) -> list:
"""Calculates one or more values from plot-level RGB data
Arguments:
pxarray: Array of RGB data for a single plot
Return:
Returns a list of the calculated values from the
"""
return_list = [excess_greenness_index(pxarray), green_leaf_index(pxarray), cive(pxarray),
normalized_difference_index(pxarray), excess_red(pxarray), exgr(pxarray),
combined_indices_1(pxarray), combined_indices_2(pxarray), vegetative_index(pxarray),
ngrdi(pxarray), percent_green(pxarray)]
return return_list