如今,抗锯齿技术在具有高像素数的显示器上使用灰度像素值。

我想退后一步,了解可用于抗锯齿或至少改善分辨率的技术。在绑定式(开/关)1位显示器上绘制的曲线和字体的质量,例如下面所示的这些低成本OLED显示器。

我不知道该程序是否称为反混叠或其他。理想情况下,对数学过程或算法的解释或链接/引用将是最有帮助的,或者如果Python中存在某些内容,那也将非常有用。我有一个预感,它最适用于灰度或RGB连续色调图像,而不是二进制1位图像。

例如,请参阅问题:使用PIL绘制多语言文本并另存为1位和8位图,其中PIL将此灰度图像转换为:



转换为该1位二进制图像:



如果我在PIL中画圆然后转换为1位,也会发生类似的情况。抗锯齿是专为连续色调显示而设计的,因此后续的阈值只会使情况变得一团糟。 AdaFruit Page Monochrome 0.96“ 128x64 OLED图形显示器,产品ID:326。



评论

我不知道您使用情况的所有细节,但是如果刷新率不错,则可以通过快速打开和关闭单个像素来伪造灰度,从而获得抗锯齿功能。不仅如此,所以您可能会发现这两个文章很有趣:blog.demofox.org/2017/10/31/…blog.demofox.org/2017/11/03/…

@AlanWolfe真是个好主意!对于这种特定类型的单位,数据速率很慢,并且没有可供切换的额外数据缓冲区,但是我会牢记这一点,如果我有一个可能的单位,我会给它一个机会。谢谢!

#1 楼

当您将图像转换为1位时,PIL的Image.convert函数默认执行抖动处理,而不仅仅是阈值处理。这就是沿形状边缘产​​生噪音的原因。抗锯齿不是问题。不幸的是,在如此低的分辨率下,抖动带来的弊大于利。

我从另一个问题中抓取了您的原始图像,并在128处设置了直阈值,结果看起来好多了:



大约和您在低分辨率1位显示器上所能做的一样好,而没有专门针对这些情况设计的位图字体。

在PIL中可以使用Image.point来实现此操作,如下所示:

image1Bit = image8Bit.point(lambda x: 0 if x < 128 else 1, mode='1')


评论


$ \ begingroup $
老实说,如果您修饰了几个像素,则可以很好地兼顾两者。
$ \ endgroup $
– joojaa
17年11月30日在21:17

$ \ begingroup $
太好了!这正是我所需要的,谢谢。
$ \ endgroup $
– uhoh
17年12月1日,0:33

#2 楼

看看矢量纹理和特殊效果的改进的Alpha测试放大倍率[Gre07](pdf)。他们方法的要点是将距离字段信息存储在字体纹理中,而不是位图字形中。然后,此信息将用于构建质量更高的字形升级版本。他们甚至描述了没有可编程阴影的渲染路径,从而给出了不错的结果。

评论


$ \ begingroup $
感谢您的链接。由于我是新手,因此阅读此类内容非常有帮助。
$ \ endgroup $
– uhoh
17年12月1日,0:37

#3 楼

这只是基于已接受答案的补充答案,它使用原始的64x128像素图像而不是放大的内插屏幕快照。

imtype = "RGB": (真实RGB)

imtype = "L": (灰度8位)

imtype = "1": (二进制1位,阈值= 128)

imtype = "1": (二进制1位,阈值= 80)


以下是未戴眼镜者的屏幕截图:

(1位屏幕截图,阈值= 128)

(1位屏幕截图,阈值= 80)

from PIL import Image, ImageDraw, ImageFont
w_disp   = 128
h_disp   =  64
fontsize =  32
text     =  u"你好!"

imageRGB  = Image.new("RGB", (w_disp, h_disp))
draw      = ImageDraw.Draw(imageRGB)
font      = ImageFont.truetype("/Library/Fonts/Arial Unicode.ttf", fontsize)
w, h      = draw.textsize(text, font=font)

draw.text(((w_disp - w)/2, (h_disp - h)/2), text, font=font)

imageRGB.save("NiHao! " + "RGB" + ".bmp")

image8bit = imageRGB.convert("L")

image8bit.save("NiHao! " + "L" + ".bmp")

threshold = 80
image1bit = image8bit.point(lambda x: 0 if x < threshold else 1, mode='1')
image1bit.save("NiHao! " + "1" + " threshold = " + str(threshold) + ".bmp")

threshold = 128
image1bit = image8bit.point(lambda x: 0 if x < threshold else 1, mode='1')
image1bit.save("NiHao! " + "1" + " threshold = " + str(threshold) + ".bmp")


#4 楼

在过去,对于诸如字体之类的东西,它们并没有进行抗锯齿处理。它们通常是手工制作的位图字体,因为它产生了最清晰,最容易读取的结果。

这就是说,您可以研究误差扩散,半色调或其他抖动技术,以将连续色调图像更改为1。位图像。这些是用于减少图像位深度的技术。

评论


$ \ begingroup $
啊!对于椭圆(可能是任意角度的线),PIL确实绘制了“看起来不错”的1位曲线,而没有标准的抗锯齿功能,即i.stack.imgur.com/HGDox.png,实际上,此答案显示了如何做更多的任意处理曲线。因此,将这些与搜索历史位图字体结合起来,我应该很好!如果您想将此信息包含在您的答案中,我将删除此评论。谢谢!
$ \ endgroup $
– uhoh
17年11月30日在7:08



$ \ begingroup $
问题是,所有这些技术都需要权衡空间分辨率,而且并不是说这些显示器有多余的像素。
$ \ endgroup $
–丹·赫尔姆
17年11月30日在10:34