python - 我需要制作一个 "mosaic"- 但非常简单

标签 python image request photo 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) “近似” - 如果放大小于 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 秒才能生成此图像:

enter image description here

我必须缩小它才能上传,但这里有一个细节(第一个 H 的左下角):

enter image description here

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

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

关于python - 我需要制作一个 "mosaic"- 但非常简单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57963870/

相关文章:

c# - 显示来自 ASP.NET 应用程序外部的图像

amazon-web-services - 从 AWS EC2 元数据链接本地地址获取多个项目

javascript - 为什么我们必须对数组进行字符串化而不是对请求的对象进行字符串化?

python - 如何在 Django 中创建/使用自定义数据库函数

python - 使用 python 3 将 CSV 转换为 JSON

c - 在C中显示颜色数组

jquery - 自定义 WP FlexSlider 插件 - 改变 slider 图像的裁剪方式

python - 使用 Python 将 ASCII 文件转换为 netCDF(ASCII 文件中的选择性列)

python - 一旦行数大于 N,就删除 MySQL 表的前 X 行

java - 如何在 servlet 中处理发布的字符串数组?