Skip to content

Commit

Permalink
Changed plotting code structure
Browse files Browse the repository at this point in the history
  • Loading branch information
allengu01 committed Oct 1, 2020
1 parent f62335e commit b9ea0d8
Show file tree
Hide file tree
Showing 29 changed files with 213 additions and 170 deletions.
67 changes: 38 additions & 29 deletions imageify.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from kmeans_mpl import run_kmeans
from kmeans_clustering import kmeans
from plot_mpl import plot_iterations, plot_rotate, plot_palette
import numpy as np
import os, shutil
import imageio
import cv2
from PIL import Image
import PIL as Image

def split_rgb(image):
b, g, r = cv2.split(image)
Expand All @@ -15,13 +16,30 @@ def flatten(arr):

def reset():
shutil.rmtree("figs")
os.mkdir('figs')
os.mkdir("figs")

shutil.rmtree("output")
os.mkdir("output")

def run_kmeans(data, k):
file_names = {}
centroids_dict = kmeans(data, k)
final_centroids = centroids_dict[len(centroids_dict)-1]
iteration_files = plot_iterations(data, centroids_dict)
file_names['iterate'] = iteration_files

rotate_files = plot_rotate(data, final_centroids)
file_names['rotate'] = rotate_files

palette_file = plot_palette(k, final_centroids)
file_names['palette'] = palette_file
return file_names

def main():
reset()

image_file = 'starrynight.jpg'
img = cv2.imread('images/' + image_file) # change file here
img = cv2.imread('images/' + image_file)
resized_img = cv2.resize(img, (40, 40), interpolation=cv2.INTER_AREA)
img_r, img_g, img_b = split_rgb(resized_img)
flatten_img_r, flatten_img_g, flatten_img_b = list(map(flatten, [img_r, img_g, img_b]))
Expand All @@ -30,39 +48,30 @@ def main():
# K-MEANS
k = 3
print("Number of Pixels:", pixels.shape[0])
kmeans_filenames, centroids = run_kmeans(pixels, k)
kmeans_file_names = run_kmeans(pixels, k)

# ITERATION ANIMATION
iterate_animation_dir = 'figs/'
iterate_animation_dir = 'figs'
images = []
for filename in kmeans_filenames["iterate"]:
print(filename)
assert filename.endswith('.png')
file_path = os.path.join(iterate_animation_dir, filename)
for file_name in kmeans_file_names["iterate"]:
assert file_name.endswith('.png') and file_name.startswith('iteration')
file_path = os.path.join(iterate_animation_dir, file_name)
images.append(imageio.imread(file_path))
imageio.mimsave('figs/iterate_animation.gif', images, fps=1)
shutil.copyfile(file_path, "output/" + file_name)
imageio.mimsave('output/iterate_animation.gif', images, fps=1)

# ROTATION ANIMATION
rotate_animation_dir = 'figs/'
rotate_animation_dir = 'figs'
images = []
for filename in kmeans_filenames["rotate"]:
print(filename)
assert filename.endswith('.png') and filename.startswith('rotate')
file_path = os.path.join(rotate_animation_dir, filename)
for file_name in kmeans_file_names["rotate"]:
assert file_name.endswith('.png') and file_name.startswith('rotate')
file_path = os.path.join(rotate_animation_dir, file_name)
images.append(imageio.imread(file_path))
os.remove(file_path)
imageio.mimsave('figs/rotate_animation.gif', images, fps=10)
imageio.mimsave('output/rotate_animation.gif', images, fps=10)

# COLOR PALETTE
color_width = 360 // k
image_array = np.empty([3, 360, 0])
for centroid in centroids:
color_block = np.ones([3, 360, color_width]) * centroid[:, np.newaxis, np.newaxis]
image_array = np.append(image_array, color_block, axis=2)
print(image_array)
print(image_array.shape)
palette = Image.fromarray(image_array.transpose(1, 2, 0).astype(np.uint8), 'RGB')
palette.save('figs/palette.png')


palette_dir = 'figs'
palette_file_name = kmeans_file_names["palette"]
palette_file_path = os.path.join(palette_dir, palette_file_name)
shutil.copyfile(palette_file_path, "output/" + palette_file_name)
main()
95 changes: 95 additions & 0 deletions kmeans_clustering.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import numpy as np

def distance(p1, p2):
"""
Returns the Euclidean distance between two points
"""
return np.sqrt(np.sum((p2 - p1) * (p2 - p1), axis=1))

def range_of(data):
"""
Returns the minimum and maximum values for each column in the data
"""
return {"min" : np.array([np.min(data, axis=0)]), "max" : np.array([np.max(data, axis=0)])}

def random_in_range(data):
"""
Returns a random array with length equal to the number of columns in data between the range of values in each column
"""
data_range = range_of(data)
data_min, data_max = data_range["min"], data_range["max"]
data_diff = data_max - data_min
return data_min + np.array([np.random.rand(data.shape[1])]) * data_diff

def initialize_random_centroids(data, k):
"""
Randomly initializes k centroids between the range of the data
"""
centroids = np.empty((0, data.shape[1]))
for _ in range(k):
centroids = np.concatenate([centroids, random_in_range(data)])
return centroids

def cluster_data(data, centroids):
"""
Creates clusters from the data and centroids where each data point belongs to the cluster corresponding to the centroid it is closest to
"""
clusters = {}
for i in range(1, len(centroids) + 1):
clusters[i] = np.empty((0, data.shape[1]))
for point in data:
nearest_centroid = int(np.argmin(distance(np.array([point]), centroids))) + 1
clusters[nearest_centroid] = np.concatenate([clusters[nearest_centroid], np.array([point])])
return clusters

def cost_function(data, centroids, clusters):
"""
A cost function using the Euclidean distance (L2 norm) of each data point to its closest centroid and averaging it over the number of data points
"""
total_cost = 0
n = data.shape[0]
for centroid_num in clusters:
d = distance(clusters[centroid_num], centroids[centroid_num - 1])
total_cost += np.sum(d)
return total_cost / n

def update_centroids(data, centroids, clusters):
"""
Moves each centroid to the mean of all data points in its cluster
"""
change = False
for centroid_num in clusters:
if clusters[centroid_num].shape[0] == 0:
pass
else:
points_in_cluster = clusters[centroid_num]
new_centroid = np.sum(points_in_cluster, axis=0) / points_in_cluster.shape[0]
if not np.array_equal(centroids[centroid_num - 1], new_centroid):
change = True
centroids[centroid_num - 1] = new_centroid
return centroids, change

def kmeans(data, k):
"""
Runs the k-means algorithm
Returns a dictionary containing the list of centroids for each iteration
"""
centroids = initialize_random_centroids(data, k)
clusters = cluster_data(data, centroids)
centroids_iterations = {}

centroids_changed = True
i = 0
iteration_files = []
while centroids_changed:
print("Iteration:", i)
centroids_iterations[i] = centroids.copy() # Lists passed by reference
clusters = cluster_data(data, centroids)
centroids, centroids_changed = update_centroids(data, centroids, clusters)
print(centroids_iterations)
i += 1
centroids_iterations[i] = centroids
print("Cost:", cost_function(data, centroids, clusters))
print(centroids_iterations)
return centroids_iterations
141 changes: 0 additions & 141 deletions kmeans_mpl.py

This file was deleted.

Binary file added output/iterate_animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_21.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/iteration_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/palette.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added output/rotate_animation.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b9ea0d8

Please sign in to comment.