1

我正在尝试分析图片。我基本上分两步完成:

  1. 将其转换为灰度图片
  2. 拍摄照片中的区域并查看它们是否更有可能是白色或黑色

我的程序在大多数情况下运行良好,但不是全部。那主要是因为我从来没有真正理解,如何将图片转换为黑白。我主要复制了我找到​​的代码并通过反复试验使其工作(这就是为什么我最终使用灰度而不是黑白,因为我没有找到如何将灰度中的每个非白色像素变为黑色)

我正在使用 PIL 进行图片操作,图片操作的主要功能如下所示(convert() 使用一次,avgcol() 用于转换后图片的每个部分,我想分析一下)

def convert():
    global im   
    matrix = (1.412453, 0.357580, 0.180423, 0,
           0.212671, 0.715160, 0.072169, 0,
           0.019334, 0.119193, 0.950227, 0 )
    im = im.convert("L", matrix)

def avgcol(im):
    p_colors=im.getcolors()
    cnt_pix=(im.size[0])*(im.size[1])
    avgpix=0
    for i in range(len(p_colors)):
        avgpix=avgpix+p_colors[i][0]*p_colors[i][1]
    return round(avgpix/cnt_pix  , 1)

我真的不知道矩阵的作用(没有找到解释单个值的站点)。我现在的具体问题是,我想将绿色过多的像素转换为白色像素,但我很确定,如果解决了,就会弹出其他东西,所以一些基本的解释,这样的事情是怎样的完成,会很棒。但我感谢任何指向正确方向的指针。并且请不要使用 for 循环每个像素的解决方案。图片很大,程序应该很快。

4

1 回答 1

3

如果您查看文档,您会看到一些内容。

首先,convert有一个单参数版本,它只需要一个mode.

如果您只想进行 RGB 到灰度的转换:

grey = im.convert("L")

提供矩阵的唯一原因是您不想使用默认转换。

您还可以直接转换为双级黑白:

bw = im.convert("1")

正如文档所说:

转换为双层图像(模式“1”)时,源图像首先转换为黑白。然后将大于 127 的结果值设置为白色,并对图像进行抖动处理。要使用其他阈值,请使用点法。

因此,如果您想要标准阈值和抖动,只需convert. 如果你想要一个不同的阈值,它看起来像这样:

grey = im.convert("L")
table = [int(i>200) for i in range(256)]
bw = grey.point(table, '1')

在你的回答中,你说:

...如何使灰度中的每个非白色像素变为黑色

如果您真的将“绝对纯白色以外的任何东西”作为“非白色”,您就不能使用point它。即使您convert使用65536 项表L16point也无法区分 99.998% 和 100% 白色,并且可以想象,一些不是白色的原始像素匹配错误。因此,为此,您可能只想直接迭代原始像素(使用load函数)并手动构建新图像。


至于矩阵的作用……如果您了解矩阵数学的基础知识,那就很简单了。(如果你不这样做,我无法在这里解释,但维基百科的文章可能是一个很好的起点。)

将每个源像素视为一个向量(例如,在 RGBA 图像中,向量<red, green, blue, alpha>。将该向量乘以一个矩阵,得到一个新向量。将其视为目标色彩空间中的一个像素。

例如,如果您有 D65 RGBA 像素,并将每个像素乘以文档中给出的 4x3 矩阵,则结果为 CIE XYZ 像素。

这意味着没有理由使用 4x3 矩阵转换为 L。您想要的是 4x1 矩阵。然后,仅当您不想要默认值时。正如文档所说:

当从彩色图像到黑白图像时,库使用 ITU-R 601-2 亮度变换:

L = R * 299/1000 + G * 587/1000 + B * 114/1000

……这只是(.299, .587, .114, 0)


所以,如果你想:

将绿色过多的像素转换为白色像素

这有点模棱两可。但至少有一种方法可以做到这一点,那就是过分强调果岭。例如,如果您使用(.1495, .8448 , .0057, 0),用于确定亮度的绿色将比平时多(红色和蓝色少得多)。


同时,在你的问题结束时:

并且请不要使用 for 循环每个像素的解决方案。图片很大,程序应该很快。

当然,在幕后,像这样的 PIL 命令bw = grey.point([int(i>200) for i in range(256)], '1')实际上是对grey. 它只是在 C 而不是 Python 中执行循环。你可以自己用Cython做同样的事情,或者用numpy隐式做,或者只使用PyPy而不是你现有的 Python 解释器(它可以 JIT 你的 Python for 循环几乎达到 C 速度)。

你为什么想这么做?好吧,看一下阈值代码:

# PIL
table = [int(i>200) for i in range(256)]
bw = grey.point(table, '1')

# Python (run in PyPy) or Cython
bw = [pixel > 200 for pixel in grey]

# numpy
bw = grey > 200
于 2013-05-01T20:12:12.143 回答