Skip to content

Add fixed implementation #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions erebor3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import operator
from collections import namedtuple
from functools import reduce
from pprint import pprint
from typing import Sequence, Iterator, Tuple, Any, Callable, List

from PIL import Image


CROP_SIZE = (60, 60)
CROP_X, CROP_Y = CROP_SIZE
THRESHOLD = 25 # max value difference between closest part per one channel (RGB)
STEP = 1


XY = namedtuple('XY', ['x', 'y'])
TileData = namedtuple('TileData', ['frames', 'tile_image'])
ScoredTile = namedtuple('ScoredTile', ['scores', 'data'])


STRANGE_MAPPING = {
(0, 0, False): (0, Image.FLIP_LEFT_RIGHT),
(0, 1, False): (1, Image.FLIP_TOP_BOTTOM),
(0, 2, False): (0, Image.FLIP_TOP_BOTTOM),
(0, 3, False): (1, Image.FLIP_LEFT_RIGHT),
(1, 0, False): (1, Image.FLIP_TOP_BOTTOM),
(1, 1, False): (0, Image.FLIP_TOP_BOTTOM),
(1, 2, False): (1, Image.FLIP_LEFT_RIGHT),
(1, 3, False): (0, Image.FLIP_LEFT_RIGHT),
(2, 0, False): (0, Image.FLIP_TOP_BOTTOM),
(2, 1, False): (1, Image.FLIP_LEFT_RIGHT),
(2, 2, False): (0, Image.FLIP_LEFT_RIGHT),
(2, 3, False): (1, Image.FLIP_TOP_BOTTOM),
(3, 0, False): (1, Image.FLIP_LEFT_RIGHT),
(3, 1, False): (0, Image.FLIP_LEFT_RIGHT),
(3, 2, False): (1, Image.FLIP_TOP_BOTTOM),
(3, 3, False): (0, Image.FLIP_TOP_BOTTOM),
(0, 0, True): (2, None),
(0, 1, True): (1, None),
(0, 2, True): (0, None),
(0, 3, True): (3, None),
(1, 0, True): (3, None),
(1, 1, True): (2, None),
(1, 2, True): (1, None),
(1, 3, True): (0, None),
(2, 0, True): (0, None),
(2, 1, True): (3, None),
(2, 2, True): (2, None),
(2, 3, True): (1, None),
(3, 0, True): (1, None),
(3, 1, True): (0, None),
(3, 2, True): (3, None),
(3, 3, True): (2, None),
}


def apply_transform(pattern_side, side, reverse, image):
rotate, flip = STRANGE_MAPPING[pattern_side, side, reverse]
if rotate:
image = image.rotate(-rotate * 90)
if flip:
image = image.transpose(flip)
return image


def split_images(source: Image, crop_size: Tuple[int, int]) -> Iterator:
source_width, source_height = source.size
crop_width, crop_height = crop_size
for row in range(0, source_height, crop_height):
for cell in range(0, source_width, crop_width):
crop_window = (cell, row, cell+crop_width, row+crop_height)
yield source.crop(crop_window).rotate(90)


def pixels_slice(
image: Image, ranges: Tuple[Tuple[int, int], Tuple[int, int]]
) -> List[Tuple[int, int, int]]:

begin, end = ranges
b_x, b_y = begin
e_x, e_y = end
slice = tuple(
image.getpixel((column, row))
for column in range(b_x, e_x, STEP if b_x < e_x else -STEP)
for row in range(b_y, e_y, STEP if b_y < e_y else -STEP)
)
if len(slice) != 60:
raise ValueError('Wrong length')
return slice


def compare(side_a, side_b):
r_a, g_a, b_a = zip(*side_a)
r_b, g_b, b_b = zip(*side_b)
r_difference = []
for a, b in zip(r_a, r_b):
r_difference.append(abs(a-b))
# r_difference = sum(r_difference)
g_difference = []
for a, b in zip(g_a, g_b):
g_difference.append(abs(a - b))
# g_difference = sum(g_difference)
b_difference = []
for a, b in zip(b_a, b_b):
b_difference.append(abs(a - b))
# b_difference = sum(b_difference)
difference = []
difference.extend(r_difference)
difference.extend(g_difference)
difference.extend(b_difference)
return reduce(operator.add, (d for d in difference if d), 1)


def get_sides(tile):
left = pixels_slice(tile, ((0, 0), (1, CROP_Y)))
top = pixels_slice(tile, ((CROP_X - 1, 0), (-1, 1)))
right = pixels_slice(tile, ((CROP_X - 1, CROP_Y - 1), (CROP_X - 2, -1)))
bottom = pixels_slice(tile, ((0, CROP_Y - 1), (CROP_X, CROP_Y - 2)))
return left, top, right, bottom

image = Image.open('./HWSYU5_H.png')
# image.show()

tiles = list(split_images(image, CROP_SIZE))
pattern_tile = tiles.pop(0)
# pattern_tile = tiles[0]
pattern_tile.show()
pattern_side_num = 3
pattern_side = get_sides(pattern_tile)[pattern_side_num]
min_difference = len(pattern_side) * THRESHOLD ** 10000

d = {}
for tile_num, tile in enumerate(tiles):
reverse = False
for tile_side_num, side in enumerate(get_sides(tile)):
# print('.', end='')
difference = compare(pattern_side, side)
if difference < min_difference:
min_difference = difference
similar_side_num = tile_side_num
similar_reverse = reverse
similar_tile_num = tile_num
similar_tile = tile
d[difference] = tile

reverse = True
for tile_side_num, side in enumerate(get_sides(tile)):
# print(',', end='')
side = side[::-1]
difference = compare(pattern_side, side)
if difference < min_difference:
min_difference = difference
similar_side_num = tile_side_num
similar_reverse = reverse
similar_tile_num = tile_num
similar_tile = tile
d[difference] = tile


print('similar_tile_num', similar_tile_num)
print('min_difference', min_difference)
print('similar_side_num', similar_side_num)
print('similar_reverse', similar_reverse)
# similar_tile.show()
#
fixed_tile = apply_transform(pattern_side_num, similar_side_num, similar_reverse, similar_tile)
fixed_tile.show()

# l = [d[D] for D in sorted(d)]
# for x in l[:10]:
# x.show()