我想从图像中删除抗锯齿。此代码将从图像中获取4种主要颜色,将每个像素与4种主要颜色进行比较,并分配最接近的颜色。
import numpy as np
from PIL import Image
image = Image.open('pattern_2.png')
image_nd = np.array(image)
image_colors = {}
for row in image_nd:
for pxl in row:
pxl = tuple(pxl)
if not image_colors.get(pxl):
image_colors[pxl] = 1
else:
image_colors[pxl] += 1
sorted_image_colors = sorted(image_colors, key=image_colors.get, reverse=True)
four_major_colors = sorted_image_colors[:4]
def closest(colors, color):
colors = np.array(colors)
color = np.array(color)
distances = np.sqrt(np.sum((colors - color) ** 2, axis=1))
index_of_smallest = np.where(distances == np.amin(distances))
smallest_distance = colors[index_of_smallest]
return smallest_distance[0]
for y, row in enumerate(image_nd):
for x, pxl in enumerate(row):
image_nd[y, x] = closest(four_major_colors, image_nd[y, x])
aliased = Image.fromarray(image_nd)
aliased.save("pattern_2_al.png")
结果如下:
正如你所看到的,颜色之间的边界并不完美。
这就是我想要的结果
(it似乎图像托管网站压缩的图像,并不会显示“别名”的图像正确)
2条答案
按热度按时间9udxz4iz1#
这里的主要问题位于
closest
方法中:colors
和color
都成为uint8
类型的NumPy数组。现在,当减去uint8
值时,不会得到负值,但会发生整数下溢,导致值接近255
。因此,然后计算的distances
是错误的,最终导致错误的颜色拾取。因此,最快的解决方法是将两个变量都转换为
int32
:此外,利用NumPy的矢量化能力可能很有用。考虑以下方法用于
closest
方法:所以,不是迭代所有像素,
你可以简单地传递整个图像:
使用给定的图像,我在我的机器上获得了100倍的速度。当然,找到RGB直方图值也可以优化。(不幸的是,我使用Python字典的经验还不是那么好。
无论如何-希望有帮助!
vaj7vani2#
由于您的测试图像大多包含相同颜色的块,因此您可以尝试应用“模式”图像过滤器,该过滤器在每个像素周围的NxN框中选择最常见的颜色:
我发现一个5x5的盒子对于我自己的测试图像效果很好,对于你的测试图像也相当好,但是你可能想玩一下盒子的大小(注意盒子越大,你的“锯齿”结果就越圆)。
结果并不完美(它生成的图像有10种颜色,而不是4种颜色),但您也可能会发现,在运行自己的算法之前应用图像过滤器会给您带来良好的结果。
有关详细信息,请参见Pillow文档。