从图像中删除抗锯齿
Remove anti-aliasing from an image
我想从图像中删除抗锯齿。此代码将从图像中获取 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")
这是结果:
如您所见,颜色之间的边界并不完美。
这就是我想要的结果:
(图片托管站点似乎压缩了图片,无法正确显示 "aliased" 图片)
这里的主要问题出在你的closest
方法上:
def closest(colors, color):
colors = np.array(colors)
color = np.array(color)
distances = np.sqrt(np.sum((colors - color) ** 2, axis=1))
colors
和 color
都变成 uint8
类型的 NumPy 数组。现在,当减去 uint8
值时,您不会得到负值,但会发生整数下溢,导致值接近 255
。所以,当时计算出来的distances
是错误的,最终导致选色错误
因此,最快的解决方法是将两个变量都转换为 int32
:
def closest(colors, color):
colors = np.array(colors).astype(np.int32)
color = np.array(color).astype(np.int32)
distances = np.sqrt(np.sum((colors - color) ** 2, axis=1))
此外,利用 NumPy 的矢量化能力可能会有用。为您的 closest
方法考虑以下方法:
def closest(colors, image):
colors = np.array(colors).astype(np.int32)
image = image.astype(np.int32)
distances = np.argmin(np.array([np.sqrt(np.sum((color - image) ** 2, axis=2)) for color in colors]), axis=0)
return colors[distances].astype(np.uint8)
所以,不是用
迭代所有像素
for y in np.arange(image_nd.shape[0]):
for x in np.arange(image_nd.shape[1]):
image_nd[y, x] = closest(four_major_colors, image_nd[y, x])
你可以简单地传递整个图像:
image_nd = closest(four_major_colors, image_nd)
使用给定的图像,我在我的机器上获得了 100 倍的加速。当然,找到RGB直方图值也可以优化。 (不幸的是,我对 Python 字典的体验还不是很好...)
总之——希望对您有所帮助!
我想从图像中删除抗锯齿。此代码将从图像中获取 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")
这是结果:
如您所见,颜色之间的边界并不完美。
这就是我想要的结果:
(图片托管站点似乎压缩了图片,无法正确显示 "aliased" 图片)
这里的主要问题出在你的closest
方法上:
def closest(colors, color):
colors = np.array(colors)
color = np.array(color)
distances = np.sqrt(np.sum((colors - color) ** 2, axis=1))
colors
和 color
都变成 uint8
类型的 NumPy 数组。现在,当减去 uint8
值时,您不会得到负值,但会发生整数下溢,导致值接近 255
。所以,当时计算出来的distances
是错误的,最终导致选色错误
因此,最快的解决方法是将两个变量都转换为 int32
:
def closest(colors, color):
colors = np.array(colors).astype(np.int32)
color = np.array(color).astype(np.int32)
distances = np.sqrt(np.sum((colors - color) ** 2, axis=1))
此外,利用 NumPy 的矢量化能力可能会有用。为您的 closest
方法考虑以下方法:
def closest(colors, image):
colors = np.array(colors).astype(np.int32)
image = image.astype(np.int32)
distances = np.argmin(np.array([np.sqrt(np.sum((color - image) ** 2, axis=2)) for color in colors]), axis=0)
return colors[distances].astype(np.uint8)
所以,不是用
迭代所有像素for y in np.arange(image_nd.shape[0]):
for x in np.arange(image_nd.shape[1]):
image_nd[y, x] = closest(four_major_colors, image_nd[y, x])
你可以简单地传递整个图像:
image_nd = closest(four_major_colors, image_nd)
使用给定的图像,我在我的机器上获得了 100 倍的加速。当然,找到RGB直方图值也可以优化。 (不幸的是,我对 Python 字典的体验还不是很好...)
总之——希望对您有所帮助!