''' the_man_with_the_personal_computer.py This program generates a video mosaic of the last four minutes of Dziga Vertov's "The Man with the Movie Camera", made entirely of matching stills from the last four minutes of Dziga Vertov's "The Man with the Movie Camera". Unlike most other films, this one is best seen from afar, or on a small screen. This program is in the public domain. No Copyright 2010-2017 Robert Luxemburg ''' import json import os from PIL import Image # (960, 720) -> (60, 45) -> (15, 15) n = 6218 def get_distance(a, b): return sum([pow(a[i] - b[i], 2) for i in range(12)]) def read_image(image_file): image = Image.open(image_file).convert('L') data = {'image': list(image.resize((4, 3), Image.BICUBIC).getdata())} values = list(image.resize((64, 48), Image.BICUBIC).getdata()) data['images'] = [] for y in range(16): for x in range(16): data['images'].append([]) for dy in range(3): for dx in range(4): data['images'][-1].append( values[y * 192 + x * 4 + dy * 64 + dx] ) return data def read_images(): data = [] for i in range(n): data_file = 'data/{:0>4}.json'.format(i + 1) print(data_file) if not os.path.exists(data_file): image_file = 'src/vertov{:0>4}.png'.format(i + 1) image_data = read_image(image_file) with open(data_file, 'w') as f: f.write(json.dumps(image_data)) else: with open(data_file) as f: image_data = json.loads(f.read()) data.append(image_data) return data def write_images(data): data_file = 'best.json' if not os.path.exists(data_file): best = {} else: with open(data_file) as f: best = json.loads(f.read()) best_counter = {} for i in range(n): image_file = 'dst/{:0>4}.png'.format(i + 1) print(image_file) if os.path.exists(image_file): continue dst_image = Image.new('L', (1920, 1440)) for index, src_data in enumerate(data[i]['images']): key = ','.join([str(value) for value in src_data]) if not key in best: best[key] = [] minimum = float('inf') for j in range(n): distance = get_distance(src_data, data[j]['image']) if distance < minimum: best[key] = [j] minimum = distance elif distance == minimum: best[key].append(j) if len(best[key]) == 1: best_index = 0 else: best_counter[key] = best_counter.get('key', 0) best_index = best_counter[key] % len(best[key]) best_counter[key] += 1 src_file = 'src/vertov{:0>4}.png'.format(best[key][best_index] + 1) src_image = Image.open(src_file) x, y = index % 16 * 120, int(index / 16) * 90 dst_image.paste(src_image.resize((120, 90), Image.BICUBIC), (x, y)) dst_image.save(image_file) with open(data_file, 'w') as f: f.write(json.dumps(best, sort_keys=True)) write_images(read_images())