我需要制作一个 "mosaic" - 但非常简单
I need to make a "mosaic" - but very simple
我发现的最好的马赛克代码你可以在这个页面看到:
https://github.com/codebox/mosaic
但是,该代码在我的 Windows 计算机上运行不佳,而且我认为该代码对于它应该做的事情来说太高级了。这是我在 reddit 上发布的要求:
1) 主图已经减少了颜色数(8)
2) 我已经有每张与颜色相关的图像都需要替换(例如,数字 1 应该替换黑色像素,数字 2 替换绿色像素...)
3) 我需要将照片放大小照片的尺寸(9 x 9 的小照片将产生大 81 倍的图像),这应该将像素“2n”点彼此推开,而不是 在它们中的每一个周围生成一个 n x n 相同颜色的区域(这就是我认为一般放大的方式,如果我错了请纠正我),它只会用无法识别的颜色为空白区域着色颜色,与任何小照片无关(我们称该颜色为 C)
4) 现在它所需要的只是 运行 通过所有非 C 色像素并将图像放在该像素的中心,这将创建马赛克。
由于我对 Python(尤其是图形)还很陌生,并且只需要一次使用,有人可以帮我创建该代码吗?我认为我受到启发的代码太复杂了。两件事我不需要:
1) "approximation" - 如果放大小于 100% 质量所需(例如图片为 9x9,但原始照片的每一面只能放大 3 倍,则程序需要将一些不同颜色的像素合并在一起,导致质量下降)
2)关联颜色-图片:我的图片调色板很小,颜色也很多,我可以手动完成
对于那些不明白我意思的人,这是我的想法:https://ibb.co/9GNhqBx
我使用了 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 的左下角):
这是马赛克的 google 驱动器 link,也许它会起作用:https://drive.google.com/file/d/1J3ofrLUhkuvALKN1xamWqfW4sUksIKQl/view?usp=sharing
这是 github 上的代码:https://github.com/jcupitt/mosaic
我发现的最好的马赛克代码你可以在这个页面看到: https://github.com/codebox/mosaic
但是,该代码在我的 Windows 计算机上运行不佳,而且我认为该代码对于它应该做的事情来说太高级了。这是我在 reddit 上发布的要求:
1) 主图已经减少了颜色数(8)
2) 我已经有每张与颜色相关的图像都需要替换(例如,数字 1 应该替换黑色像素,数字 2 替换绿色像素...)
3) 我需要将照片放大小照片的尺寸(9 x 9 的小照片将产生大 81 倍的图像),这应该将像素“2n”点彼此推开,而不是 在它们中的每一个周围生成一个 n x n 相同颜色的区域(这就是我认为一般放大的方式,如果我错了请纠正我),它只会用无法识别的颜色为空白区域着色颜色,与任何小照片无关(我们称该颜色为 C)
4) 现在它所需要的只是 运行 通过所有非 C 色像素并将图像放在该像素的中心,这将创建马赛克。
由于我对 Python(尤其是图形)还很陌生,并且只需要一次使用,有人可以帮我创建该代码吗?我认为我受到启发的代码太复杂了。两件事我不需要:
1) "approximation" - 如果放大小于 100% 质量所需(例如图片为 9x9,但原始照片的每一面只能放大 3 倍,则程序需要将一些不同颜色的像素合并在一起,导致质量下降)
2)关联颜色-图片:我的图片调色板很小,颜色也很多,我可以手动完成
对于那些不明白我意思的人,这是我的想法:https://ibb.co/9GNhqBx
我使用了 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 的左下角):
这是马赛克的 google 驱动器 link,也许它会起作用:https://drive.google.com/file/d/1J3ofrLUhkuvALKN1xamWqfW4sUksIKQl/view?usp=sharing
这是 github 上的代码:https://github.com/jcupitt/mosaic