-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathColorExtract.py
More file actions
248 lines (144 loc) · 7.01 KB
/
ColorExtract.py
File metadata and controls
248 lines (144 loc) · 7.01 KB
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/usr/bin/env python
# coding: utf-8
# # Color Identification using Machine Learning
#
# In this notebook, I have used machine learning algorithm, `KMeans`, to extract colors from a give image. I will use `OpenCV2` for image manipulation, apply `KMeans` to identify the major colors and then plot the information using `Matplotlib`.
# ## Import libraries
#
# Let's first import necessary libraries. We need `sklearn` for KMeans algorithm, `matplotlib.pyplot` for plotting graphs, `numpy` to work with arrays, `cv2` to work with image data, `collections` to use Counter to count values, `rgb2lab` to convert RGB values and `deltaE_cie76` to calculate similarity between colors.
# In[1]:
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
import cv2
from collections import Counter
from skimage.color import rgb2lab, deltaE_cie76
import os
get_ipython().run_line_magic('matplotlib', 'inline')
# ## Working with OpenCV
#
# Let's first read a sample image and understand basic operations that we can do on it.
# In[2]:
path = os.getcwd()
print(path)
# In[ ]:
# In[15]:
image = cv2.imread('Static3.jpg')
print("The type of this input is {}".format(type(image)))
print("Shape: {}".format(image.shape))
plt.imshow(image)
# We see that the image has different colors as compared to the original image. This is because by default OpenCV reads the images in the color order `BLUE GREEN RED` i.e. BGR. Thus, we need to convert it into `REG GREEN BLUE` i.e. RGB.
# In[16]:
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
# The image can also be converted to grayscale if needed.
# In[ ]:
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
plt.imshow(gray_image, cmap='gray')
# We might want to resize the image to a certain size whenever the images are huge or when we are working with multiple images of different dimensions.
# In[5]:
resized_image = cv2.resize(image, (1200, 600))
plt.imshow(resized_image)
# ## Color Identification
#
# Not that we know a bit about OpenCV, let's start identifying colors from an image.
# First, we will define a function that can give us the `hex` values of our the colors that we will identify.
# In[17]:
def RGB2HEX(color):
return "#{:02x}{:02x}{:02x}".format(int(color[0]), int(color[1]), int(color[2]))
# KMeans expects flattened array as input during its fit method. Thus, we need to reshape the image using numpy. Then, we can apply KMeans to first fit and then predict on the image to get the results. Then, the cluster colors are identified an arranged in the correct order. We plot the colors as a pie chart.
#
# I have combined all the steps in two method.
# In[18]:
def get_image(image_path):
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
return image
# In[19]:
def get_colors(image, number_of_colors, show_chart):
modified_image = cv2.resize(image, (600, 400), interpolation = cv2.INTER_AREA)
modified_image = modified_image.reshape(modified_image.shape[0]*modified_image.shape[1], 3)
clf = KMeans(n_clusters = number_of_colors)
labels = clf.fit_predict(modified_image)
counts = Counter(labels)
# sort to ensure correct color percentage
counts = dict(sorted(counts.items()))
center_colors = clf.cluster_centers_
# We get ordered colors by iterating through the keys
ordered_colors = [center_colors[i] for i in counts.keys()]
hex_colors = [RGB2HEX(ordered_colors[i]) for i in counts.keys()]
rgb_colors = [ordered_colors[i] for i in counts.keys()]
if (show_chart):
plt.figure(figsize = (8, 6))
plt.pie(counts.values(), labels = hex_colors, colors = hex_colors)
return rgb_colors
# In[22]:
get_colors(get_image('Static3.jpg'), 3, True)
# In[9]:
get_colors(get_image('Static1.jpg'), 8, True)
# ## Search images using Color
#
# From the model above, we can extract the major colors.
# This create the opportunity to search for images based on certain colors. We can select a color and if it's hex matches or is close to the hex of the major colors of the image, we say it's a match.
# We first get all the images and store them in the `images` variable.
# In[23]:
IMAGE_DIRECTORY = 'images'
COLORS = {
'GREEN': [0, 128, 0],
'BLUE': [0, 0, 128],
'YELLOW': [255, 255, 0]
}
images = []
for file in os.listdir(IMAGE_DIRECTORY):
if not file.startswith('.'):
images.append(get_image(os.path.join(IMAGE_DIRECTORY, file)))
# We can now see all the images.
# In[24]:
plt.figure(figsize=(20, 10))
for i in range(len(images)):
plt.subplot(1, len(images), i+1)
plt.imshow(images[i])
# We define the function below. We will try to match with the top 10 colors of the image. It is highly possible that there will be no extact match for the hex codes, thus we calculate the similarity between the chosen color and the colors of the image.
#
# We keep a threshold value such that if the difference between the chosen color and any of the selected colors is less than that threshold, we declare it as a match.
#
# Hex values or RGB values cannot be directly compared so we first convert them to a device independant and color uniform space. We use `rgb2lab` to convert the values and then find the difference using `deltaE_cie76`. The method calculates the difference between all top 5 colors of the image and the selected color and if atleast one is below the threshold, we show the image.
# In[25]:
def match_image_by_color(image, color, threshold = 60, number_of_colors = 10):
image_colors = get_colors(image, number_of_colors, False)
selected_color = rgb2lab(np.uint8(np.asarray([[color]])))
select_image = False
for i in range(number_of_colors):
curr_color = rgb2lab(np.uint8(np.asarray([[image_colors[i]]])))
diff = deltaE_cie76(selected_color, curr_color)
if (diff < threshold):
select_image = True
return select_image
# We call the above method for all the images in our set and show relevant images out of the same that approximately match our selected color.
# In[26]:
def show_selected_images(images, color, threshold, colors_to_match):
index = 1
for i in range(len(images)):
selected = match_image_by_color(images[i],
color,
threshold,
colors_to_match)
if (selected):
plt.subplot(1, 5, index)
plt.imshow(images[i])
index += 1
# In[27]:
# Search for GREEN
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['GREEN'], 60, 5)
# In[28]:
# Search for BLUE
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['BLUE'], 60, 5)
# In[29]:
# Search for YELLOW
plt.figure(figsize = (20, 10))
show_selected_images(images, COLORS['YELLOW'], 60, 5)
# ## Conclusion
#
# In this notebook, we used KMeans to extract majority colors from images. We then used the RGB Values of Colors to identify images from a collection that have that color in them.