将图片转换为 RGB 点图像(半色调效果)

Convert a Picture to RGB Dots Image (Half Toning Like Effect)

我正在尝试向学生展示 RGB 颜色模型如何创建特定颜色(或者让他们相信它确实如此)。所以我想拍照并将每个像素转换为 RGB 表示,这样当您放大时,您看到的不是单个彩色像素,而是 RGB 颜色。

我已经这样做了,但是由于一些非常明显的原因,转换后的图片要么被洗掉了,要么比原来的颜色更暗(这是一个小小的不便,但我认为如果我能让它更强大,它会更强大和原来一样)。

这里有两张图片"zoomed out":

这是一个"medium zoom",开始显示转换后的图片中的RGB伪影:

这是一张放大的图片,您可以清楚地看到单个像素 RGB 方块:

您会注意到像素周围的颜色不变;那是图片的平均RGB。我把它放在那里,这样你就可以看到单个像素(否则你只会看到 rows/columns 的阴影 red/green/blue)。如果我把 space 完全去掉,图像会更暗,如果我用白色替换它,那么图像看起来会褪色(缩小时)。

我知道为什么这样显示会导致它更暗:"pure red" 将带有完全黑色的蓝色和绿色。从某种意义上说,如果我要拍一张全红的照片,它基本上是原始亮度的 1/3。

所以我的问题是:

1:是否有可用的工具可以执行此操作(或类似的操作)?

2:关于如何让转换后的图像更接近原始图像有什么想法吗?

对于第二个问题,我当然可以只增加每个"RGB pixel"(每个正方形中的三个水平条纹)的亮度,但是增加多少?我当然不能只将 RGB 整数乘以 3(显然是对我上面所说的补偿)。我想知道是否有某种方法可以调整我的背景颜色来补偿我?还是每张图片都需要摆弄一下?

不要在这上面浪费太多时间。如果其中一张中的信息较少,则无法使两张图片看起来相同。你仍然有你的计算机,它会在缩小时以奇怪的方式对你的图像进行子采样。

只需将放大镜穿过class,这样他们就可以在手机或其他屏幕上自己查看,或者以不同的放大级别显示屏幕图片。

如果您想坚持使用软件,请将图像分辨率提高三倍,不要使用空行和空列,或者至少将它们设为黑色以增加对比度并将 RGB 组件缩放到全范围。

你为什么不保留放大的图像作为背景?这将使两个图像在缩小时看起来完全相同,而 RGB 条带在放大时仍然清晰可见。

如果不是,则使用整个图像的平均颜色以保持相似的强度,但洗涤效果将保持不变。

一个中间选项是在图像上应用强大的低通滤波器以平滑所有细节并将其用作背景,但我认为与第一种方法相比没有真正的优势。

您认为可以通过将所有值乘以 3 来保持亮度是正确的。只有一个小问题:图像中的 RGB 值使用伽玛校正,因此强度不是线性的。您需要对这些值进行去伽马运算,相乘,然后再次进行伽马校正。

您还需要去掉每个像素周围的边框。这些边界占据了最终图像的 7/16,这太多了,无法弥补。我尝试将每个其他像素旋转 90 度,虽然它给出了一个明确的锯齿形图案,但它确实明确了像素边界的位置。

当您在图像查看器中缩小时,您可能也会看到伽玛问题。许多观众在调整大小时都懒得做伽玛校正。有关深入说明,请参阅 Gamma error in picture scaling,并使用末尾提供的测试图像。完全放弃缩放并简单地退出监视器可能会更好。

这里有一些 Python 代码和生成图像的裁剪图。

from PIL import Image
im = Image.open(filename)
im2 = Image.new('RGB', (im.size[0]*3, im.size[1]*3))
ld1 = im.load()
ld2 = im2.load()
for y in range(im.size[1]):
    for x in range(im.size[0]):
        rgb = ld1[x,y]
        rgb = [(c/255)**2.2 for c in rgb]
        rgb = [min(1.0,c*3) for c in rgb]
        rgb = tuple(int(255*(c**(1/2.2))) for c in rgb)
        x2 = x*3
        y2 = y*3
        if (x+y) & 1:
            for x3 in range(x2, x2+3):
                ld2[x3,y2] = (rgb[0],0,0)
                ld2[x3,y2+1] = (0,rgb[1],0)
                ld2[x3,y2+2] = (0,0,rgb[2])
        else:
            for y3 in range(y2, y2+3):
                ld2[x2,y3] = (rgb[0],0,0)
                ld2[x2+1,y3] = (0,rgb[1],0)
                ld2[x2+2,y3] = (0,0,rgb[2])