4

重新调整 PIL 图像强度的最简单/最干净的方法是什么?

假设我有一个来自 12 位相机的 16 位图像,所以只有 0-4095 的值在使用中。我想重新调整强度,以便使用 0-65535 的整个范围。当图像表示为 PIL 的图像类型时,最简单/最干净的方法是什么?

到目前为止,我提出的最佳解决方案是:

pixels = img.getdata()
img.putdata(pixels, 16)

这可行,但总是将四个最低有效位留空。理想情况下,我想将每个值向左移动四位,然后将四个最高有效位复制到四个最低有效位。我不知道怎么做那么快。

4

5 回答 5

3

既然你知道像素值是 0-4095,我找不到比这更快的方法:

new_image= image.point(lambda value: value<<4 | value>>8)

根据文档,无论图像大小如何,lambda 函数最多会被调用 4096 次。

编辑:由于给定点的函数必须argument * scale + offset是图像中的形式I,那么这是使用该函数的最佳point方法:

new_image= image.point(lambda argument: argument*16)

最大输出像素值为 65520。

第二次拍摄:

您自己的解决方案的修改版本,itertools用于提高效率:

import itertools as it # for brevity
import operator

def scale_12to16(image):
    new_image= image.copy()
    new_image.putdata(
        it.imap(operator.or_,
            it.imap(operator.lshift, image.getdata(), it.repeat(4)),
            it.imap(operator.rshift, image.getdata(), it.repeat(8))
        )
    )
    return new_image

这避免了point函数参数的限制。

于 2009-09-16T02:42:59.757 回答
2

您需要进行直方图拉伸链接到我回答的类似问题)而不是直方图均衡直方图拉伸 http://cct.rncan.gc.ca/resource/tutor/fundam/images/linstre.gif

图片来源

在您的情况下,您需要将所有像素值乘以16 这是两个动态范围(65536/4096)之间的因子。

于 2009-08-26T12:45:18.910 回答
2

为什么要将 4 msb 复制回 4 lsb?每个像素只有 12 个有效位信息。您所做的任何事情都不会改善这一点。如果您可以接受只有 4K 的强度,这对于大多数应用程序来说都很好,那么您的解决方案是正确的并且可能是最佳的。如果您需要更多级别的阴影,那么正如大卫发布的那样,使用直方图重新计算。但是,这将明显变慢。

但是,将 4 msb 复制到 4 lsb 不是要走的路:)

于 2009-08-25T13:49:39.217 回答
1

您需要做的是Histogram Equalization。关于如何使用 python 和 pil:

编辑:代码将每个值向左移动四位,然后将四个最高有效位复制到四个最低有效位...

def f(n):
   return  n<<4 + int(bin(n)[2:6],2)

print(f(0))
print(f(2**12))

# output
>>> 0
    65664 # Oops > 2^16
于 2009-08-25T12:31:36.787 回答
0

也许你应该传递 16.(浮点数)而不是 16(整数)。我试图测试它,但由于某种原因,putdata 根本不会成倍增加......所以我希望它对你有用。

于 2009-09-11T13:48:17.053 回答