1

我发现最好的马赛克代码可以在这个页面上看到: https ://github.com/codebox/mosaic

但是,该代码在我的 Windows 计算机上运行不佳,而且我认为该代码对于它应该做的事情来说太高级了。这是我在reddit上发布的要求:

1)主照片已经减少了颜色数量(8)

2)我已经有每张与颜色相关的图像都需要替换(例如,数字 1 应该替换黑色像素,数字 2 替换绿色像素......)

3)我需要将照片放大小照片的大小(9 x 9 小照片将产生 81 倍大的图像),这应该将像素“2n”点彼此推开,而不是产生 anxn 同色区域围绕它们中的每一个(这就是我认为放大的一般工作方式,如果我错了,请纠正我),它只会用无法识别的颜色为空白区域着色,这与任何小照片无关(我们称之为颜色) C)

4) 现在它所需要的只是遍历所有非 C 色像素并将图像放在该像素的中心,这将创建马赛克。


由于我对 Python(尤其是图形)还很陌生并且只需要它一次使用,有人可以帮助我创建该代码吗?我认为我受到启发的代码太复杂了。我不需要两件事:

1)“近似”——如果放大小于100%质量所需(例如图片是9x9,但原始照片的每一边只能放大3倍,那么程序需要将一些不同颜色的像素合并在一起,导致质量损失)

2)关联颜色-图片:我的图片调色板很小,颜色也很丰富,我可以手动完成

对于那些不明白我的意思的人,这是我的想法:https ://ibb.co/9GNhqBx

4

1 回答 1

1

我快速使用pyvips

#!/usr/bin/python3

import sys
import os
import pyvips

if len(sys.argv) != 4:
    print("usage: tile-directory input-image output-image")
    sys.exit(1)

# the size of each tile ... 16x16 for us
tile_size = 16

# load all the tile images, forcing them to the tile size
print(f"loading tiles from {sys.argv[1]} ...")
for root, dirs, files in os.walk(sys.argv[1]):
    tiles = [pyvips.Image.thumbnail(os.path.join(root, name), tile_size, 
                                    height=tile_size, size="force") 
             for name in files]

# drop any alpha
tiles = [image.flatten() if image.hasalpha() else image
         for image in tiles]

# copy the tiles to memory, since we'll be using them many times
tiles = [image.copy_memory() for image in tiles]

# calculate the average rgb for an image, eg. image -> [12, 13, 128]
def avg_rgb(image):
    m = image.stats()
    return [m(4,i)[0] for i in range(1,4)]

# find the avg rgb for each tile
tile_colours = [avg_rgb(image) for image in tiles]

# load the main image ... we can do this in streaming mode, since we only 
# make a single pass over the image
main = pyvips.Image.new_from_file(sys.argv[2], access="sequential")

# find the abs of an image, treating each pixel as a vector
def pyth(image):
    return sum([band ** 2 for band in image.bandsplit()]) ** 0.5

# calculate a distance map from the main image to each tile colour
distance = [pyth(main - colour) for colour in tile_colours]

# make a distance index -- hide the tile index in the bottom 16 bits of the
# distance measure
index = [(distance[i] << 16) + i for i in range(len(distance))]

# find the minimum distance for each pixel and mask out the bottom 16 bits to
# get the tile index for each pixel
index = index[0].bandrank(index[1:], index=0) & 0xffff

# replicate each tile image to make a set of layers, and zoom the index to
# make an index matching the output size
layers = [tile.replicate(main.width, main.height) for tile in tiles]
index = index.zoom(tile_size, tile_size)

# now for each layer, select pixels matching the index
final = pyvips.Image.black(main.width * tile_size, main.height * tile_size)
for i in range(len(layers)):
    final = (index == i).ifthenelse(layers[i], final)

print(f"writing {sys.argv[3]} ...")
final.write_to_file(sys.argv[3])

我希望它很容易阅读。我可以这样运行它:

$ ./mosaic3.py smallpic/ mainpic/Use\ this.jpg x.png
loading tiles from smallpic/ ...
writing x.png ...
$

在这台 2015 年的笔记本电脑上大约需要 5 秒,并制作了这样的图像:

在此处输入图像描述

我不得不缩小它以进行上传,但这里有一个细节(第一个 H 的左下角):

在此处输入图像描述

这是马赛克的谷歌驱动器链接,也许它会起作用:https ://drive.google.com/file/d/1J3ofrLUhkuvALKN1xamWqfW4sUksIKQl/view?usp=sharing

这是 github 上的代码:https ://github.com/jcupitt/mosaic

于 2019-09-24T13:53:00.917 回答