CiscoTheProot/minDistance.py

132 lines
No EOL
4 KiB
Python

import math
from PIL import Image
import numpy as np
from scipy.optimize import linear_sum_assignment
class Point2D:
x = 0
y = 0
def __init__(self, x, y):
self.x = x
self.y = y
def round(self):
self.x = round(self.x)
self.y = round(self.y)
return self
def distance(self, other):
dx = self.x - other.x
dy = self.y - other.y
return math.sqrt(dx**2 + dy**2)
def interpolate(self, other, percentage):
new_x = self.x + (other.x - self.x) * percentage
new_y = self.y + (other.y - self.y) * percentage
return Point2D(new_x, new_y)
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def generate_point_array_from_image(image):
image = image.convert("RGB") # Convert image to RGB color mode
width, height = image.size
point_array = []
# Iterate over the pixels and generate Point2D instances
for y in range(height):
for x in range(width):
pixel = image.getpixel((x, y))
if pixel != (0, 0, 0): # Assuming white pixels
point = Point2D(x, y)
point_array.append(point)
return point_array
def generate_image_from_point_array(points, width, height):
# Create a new blank image
image = Image.new("RGB", (width, height), "black")
# Set the pixels corresponding to the points as white
pixels = image.load()
for point in points:
point = point.round()
x = point.x
y = point.y
pixels[x, y] = (255, 255, 255)
return image
def pair_points(points1, points2):
# Determine the size of the point arrays
size1 = len(points1)
size2 = len(points2)
# Create a cost matrix based on the distances between points
cost_matrix = np.zeros((size1, size2))
for i in range(size1):
for j in range(size2):
cost_matrix[i, j] = points1[i].distance(points2[j])
# Duplicate points in the smaller array to match the size of the larger array
if size1 > size2:
num_duplicates = size1 - size2
duplicated_points = np.random.choice(points2, size=num_duplicates).tolist()
points2 += duplicated_points
elif size2 > size1:
num_duplicates = size2 - size1
duplicated_points = np.random.choice(points1, size=num_duplicates).tolist()
points1 += duplicated_points
# Update the size of the point arrays
size1 = len(points1)
size2 = len(points2)
# Create a new cost matrix with the updated sizes
cost_matrix = np.zeros((size1, size2))
for i in range(size1):
for j in range(size2):
cost_matrix[i, j] = points1[i].distance(points2[j])
# Solve the assignment problem using the Hungarian algorithm
row_ind, col_ind = linear_sum_assignment(cost_matrix)
# Create pairs of points based on the optimal assignment
pairs = []
for i, j in zip(row_ind, col_ind):
pairs.append((points1[i], points2[j]))
return pairs
def interpolate_point_pairs(pairs, percentage):
interpolated_points = []
for pair in pairs:
point1, point2 = pair
interpolated_point = point1.interpolate(point2, percentage)
interpolated_points.append(interpolated_point)
return interpolated_points
Image1 = Image.open("CiscoTheProot/faces/prootface3.png")
Image2 = Image.open("CiscoTheProot/faces/prootface4.png")
pixelArray1 = generate_point_array_from_image(Image1)
pixelArray2 = generate_point_array_from_image(Image2)
pairs = pair_points(pixelArray1, pixelArray2)
generate_image_from_point_array(interpolate_point_pairs(pairs, 0), 128, 32).show()
generate_image_from_point_array(interpolate_point_pairs(pairs, .25), 128, 32).show()
generate_image_from_point_array(interpolate_point_pairs(pairs, .5), 128, 32).show()
generate_image_from_point_array(interpolate_point_pairs(pairs, .75), 128, 32).show()
generate_image_from_point_array(interpolate_point_pairs(pairs, 1), 128, 32).show()
print(pairs)