def find_nearest_floss(block): # This way searches full blown sum of squared error for best color #error = [block.color_error(floss['rgb']) for floss in dmc_flosses.flosses] # This way does a jenky averaged color search average_point = [average(coord) for coord in zip(*block.points)] error = [sum_squared_error(average_point, Pixel.FromRGB(floss['rgb']).get_Lab()) for floss in dmc_flosses.flosses] best_error = min(error) idx = error.index(best_error) return dmc_flosses.flosses[idx]
def find_nearest_floss(region_point): error = [ sum_squared_error(region_point, Pixel.FromRGB(floss['rgb']).get_Lab()) for floss in dmc_flosses.flosses ] best_error = min(error) idx = error.index(best_error) return dmc_flosses.flosses[idx]
def floss_image(image, color_map): x, y = image.size pixel_data = image.load() flossed_image = Image.new('RGB', (x, y), None) flossed_pixels = flossed_image.load() for r in range(x): for c in range(y): value = Pixel.FromRGB(pixel_data[r,c]).get_Lab() possible_flosses = [floss for block, floss in color_map.iteritems() if value in block] # FIXME: I may be doing something weird because I seem to have pixels that can fall into multiple blocks #assert len(possible_flosses) == 1 flossed_pixels[r,c] = possible_flosses[0]['rgb'] # save debug image flossed_image.save(os.path.join(options.output_dir, 'floss.bmp'), 'BMP') return flossed_image
def flossit(resized_image, median_cut_options): global options options = median_cut_options assert options.num_colors > 0 if not options.strategy: options.strategy = 'random' elif options.strategy not in seed_strategies.keys(): print '[Lloyd\'s] Unknown seeding strategy "%s" -- falling back to random seeds!' % options.strategy options.strategy = 'random' print '[Lloyd\'s] Enumerating the pixel data in the resized image...' all_points = [ Pixel.FromRGB(rgb).get_Lab() for rgb in get_image_points(resized_image) ] print '[Lloyd\'s] Setting initial seed regions...' regions = seed_strategies[options.strategy](all_points, options.num_colors) region_kd_tree = kdtree(regions) print '[Lloyd\'s] Finding initial point assignments...' assignments = [ closest_region(point, regions, region_kd_tree) for point in all_points ] iteration = 1 last_assignments = [] while last_assignments != assignments: print '[Lloyd\'s] Iterating regions (%s)...' % iteration populated_regions = [k for k, g in groupby(sorted(assignments))] regions = [ central_point( compress(all_points, [assignment == region for assignment in assignments])) for region in populated_regions ] region_kd_tree = kdtree(regions) iteration += 1 last_assignments = assignments assignments = [ closest_region(point, regions, region_kd_tree) for point in all_points ] print '[Lloyd\'s] Assigning floss colors to regions...' colors = [find_nearest_floss(region) for region in regions] print '[Lloyd\'s] Flossing image...' return floss_image(resized_image, regions, colors)
def flossit(resized_image, median_cut_options): global options options = median_cut_options assert options.num_colors > 0 if not options.strategy: options.strategy = 'size' elif options.strategy not in division_strategies.keys(): print '[Median Cut] Unknown division strategy "%s" -- falling back to size-based cuts!' % options.strategy options.strategy = 'size' print '[Median Cut] Enumerating the pixel data in the resized image...' all_points = [Pixel.FromRGB(rgb).get_Lab() for rgb in get_image_points(resized_image)] print '[Median Cut] Breaking image into %s discrete color groups...' % options.num_colors color_blocks = subdivide(all_points) print '[Median Cut] Finding best matching floss colors for each region...' color_map = map_blocks_to_floss(color_blocks) print '[Median Cut] Rendering image using appropriate floss colors...' return floss_image(resized_image, color_map)
def floss_image(image, region_points, region_colors): x, y = image.size pixel_data = image.load() flossed_image = Image.new('RGB', (x, y), None) flossed_pixels = flossed_image.load() for r in range(x): for c in range(y): pixel = Pixel.FromRGB(pixel_data[r, c]).get_Lab() error = [ sum_squared_error(pixel, region_point) for region_point in region_points ] best_error = min(error) idx = error.index(best_error) flossed_pixels[r, c] = region_colors[idx]['rgb'] # save debug image flossed_image.save(os.path.join(options.output_dir, 'floss.bmp'), 'BMP') return flossed_image