Skip to content

Implement selection of tile from multiple best fitting ones #22

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 2 commits 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
25 changes: 19 additions & 6 deletions mosaic.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import sys
import random
import os, os.path
from PIL import Image, ImageOps
from multiprocessing import Process, Queue, cpu_count

# Change these 3 config parameters to suit your needs...
TILE_SIZE = 50 # height/width of mosaic tiles in pixels
TILE_MATCH_RES = 5 # tile matching resolution (higher values give better fit but require more processing)
ENLARGEMENT = 8 # the mosaic image will be this many times wider and taller than the original
# Change these 5 config parameters to suit your needs...
TILE_SIZE = 50 # height/width of mosaic tiles in pixels
TILE_MATCH_RES = 5 # tile matching resolution (higher values give better fit but require more processing)
ENLARGEMENT = 8 # the mosaic image will be this many times wider and taller than the original
SELECTION_THRESHOLD = 50_000 # consider all images with difference smaller than this to top candidate when selecting tile
DISABLE_DIFF_BAILOUT = True # disable pre-termination of image difference computation (makes diff threshold work properly)

Image.MAX_IMAGE_PIXELS = sys.maxsize

TILE_BLOCK_SIZE = TILE_SIZE / max(min(TILE_MATCH_RES, TILE_SIZE), 1)
WORKER_COUNT = max(cpu_count() - 1, 1)
Expand Down Expand Up @@ -92,7 +97,7 @@ def __get_tile_diff(self, t1, t2, bail_out_value):
for i in range(len(t1)):
#diff += (abs(t1[i][0] - t2[i][0]) + abs(t1[i][1] - t2[i][1]) + abs(t1[i][2] - t2[i][2]))
diff += ((t1[i][0] - t2[i][0])**2 + (t1[i][1] - t2[i][1])**2 + (t1[i][2] - t2[i][2])**2)
if diff > bail_out_value:
if not DISABLE_DIFF_BAILOUT and diff > bail_out_value:
# we know already that this isn't going to be the best fit, so no point continuing with this tile
return diff
return diff
Expand All @@ -103,14 +108,22 @@ def get_best_fit_tile(self, img_data):
tile_index = 0

# go through each tile in turn looking for the best match for the part of the image represented by 'img_data'
scores = []
for tile_data in self.tiles_data:
diff = self.__get_tile_diff(img_data, tile_data, min_diff)
scores.append((tile_index, diff))
if diff < min_diff:
min_diff = diff
best_fit_tile_index = tile_index
tile_index += 1

return best_fit_tile_index
assert min(scores, key=lambda x: x[1])[0] == best_fit_tile_index
scores = sorted(scores, key=lambda x: x[1])

best_match = scores[0]
candidates = [idx for idx, val in scores if abs(best_match[1] - val) < SELECTION_THRESHOLD]

return random.choice(candidates)

def fit_tiles(work_queue, result_queue, tiles_data):
# this function gets run by the worker processes, one on each CPU core
Expand Down