-
Notifications
You must be signed in to change notification settings - Fork 3
/
PriusImage.py
186 lines (147 loc) · 5 KB
/
PriusImage.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
import argparse
import datetime
import os
import time
import cv2
import numpy as np
from PriusPalette import PriusPalette
from sklearn.cluster import KMeans
class PriusImage(object):
def __init__(self, image):
self.image = image
self.avgColor = []
self.pcaColors = []
@classmethod
def from_image(cls, image):
return cls(image)
@classmethod
def from_path(cls, path):
image = cv2.imread(path)
return cls(image)
def has_perfect_match(self):
try:
palette = PriusPalette()
isMatch = False
matches = []
matches.append(self.has_required_shades())
avg = self.avg_color()
matches.append(palette.has_shade(avg))
requiredColors = []
for color in self.pca_colors():
requiredColors.append(palette.has_shade(color))
matches.append(any(requiredColors))
return all(matches)
except Exception as e:
print(e)
return False
def color_profile(self):
start = time.time()
try:
shadePredictedCount = 0
avgPredictedCount = 0
pcaPredictedCount = 0
totalPredictedCount = 0
# print("\nColor Profile for Image")
palette = PriusPalette()
totalPredictedCount = totalPredictedCount + 1
if self.has_required_shades():
shadePredictedCount = shadePredictedCount + 1
avg = self.avg_color()
avgInPalette = palette.has_shade(avg)
# print("Average Color: " + str(avg) + " Palette Match? " + str(avgInPalette))
if avgInPalette:
avgPredictedCount = avgPredictedCount + 1
requiredColors = []
for color in self.pca_colors():
requiredColors.append(palette.has_shade(color))
# print("PCA Analysis\n")
if any(requiredColors):
pcaPredictedCount = pcaPredictedCount + 1
except Exception as e:
print(e)
end = time.time()
print("\nRequired Palettes: " + str(shadePredictedCount) + " Average Color: " + str(
avgPredictedCount) + " PCA Colors: " + str(pcaPredictedCount) + " Total: " + str(
totalPredictedCount) + " Time: " + str(end - start) + "\n")
def has_shade(self, shade):
for (lower, upper) in shade:
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
mask = cv2.inRange(self.image, lower, upper)
output = cv2.bitwise_and(self.image, self.image, mask=mask)
return output.any() > 0
def has_required_shades(self):
shadeList = []
palette = PriusPalette()
for shade in palette.required_shades():
shadeList.append(self.has_shade(shade))
return all(shadeList)
def avg_color(self):
if len(self.avgColor) > 0:
return self.avgColor
height, width, _ = np.shape(self.image)
# calculate the average color of each row of our image
avg_color_per_row = np.average(self.image, axis=0)
# calculate the averages of our rows
avg_colors = np.average(avg_color_per_row, axis=0)
# avg_color is a tuple in BGR order of the average colors
# but as float values
# print(f'avg_colors: {avg_colors}')
# so, convert that array to integers
int_averages = np.array(avg_colors, dtype=np.uint8)
# print(f'int_averages: {int_averages}')
# create a new image of the same height/width as the original
average_image = np.zeros((height, width, 3), np.uint8)
# and fill its pixels with our average color
average_image[:] = int_averages
# finally, show it side-by-side with the original
# cv2.imshow("Avg Color", np.hstack([img, average_image]))
# cv2.waitKey(0)
self.avgColor = int_averages
return int_averages
def has_avg_match(self):
palette = PriusPalette()
avgColor = self.avg_color()
if palette.has_shade(avgColor):
return True
return False
def has_pca_match(self):
palette = PriusPalette()
pcaColors = self.pca_colors()
for color in pcaColors:
if palette.has_shade(color):
return True
return False
def pca_colors(self):
if len(self.pcaColors) > 0:
return self.pcaColors
height, width, _ = np.shape(self.image)
# reshape the image to be a simple list of RGB pixels
image = self.image.reshape((height * width, 3))
# we'll pick the 5 most common colors
num_clusters = 1
clusters = KMeans(n_clusters=num_clusters)
clusters.fit(image)
# count the dominant colors and put them in "buckets"
histogram = self.make_histogram(clusters)
# then sort them, most-common first
combined = zip(histogram, clusters.cluster_centers_)
combined = sorted(combined, key=lambda x: x[0], reverse=True)
# finally, we'll output a graphic showing the colors in order
rgb_values = []
for index, rows in enumerate(combined):
rgb = int(rows[1][2]), int(rows[1][1]), int(rows[1][0])
rgb_values.append(rgb)
self.pcaColors = rgb_values
return rgb_values
def make_histogram(self, cluster):
"""
Count the number of pixels in each cluster
:param: KMeans cluster
:return: numpy histogram
"""
numLabels = np.arange(0, len(np.unique(cluster.labels_)) + 1)
hist, _ = np.histogram(cluster.labels_, bins=numLabels)
hist = hist.astype('float32')
hist /= hist.sum()
return hist