重新调整PIL图像的强度

时间:2009-08-25 12:25:52

标签: python image-processing python-imaging-library

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

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

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

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

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

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

你需要做直方图拉伸link to a similar question I answered)而不是直方图均衡histogram stretch http://cct.rncan.gc.ca/resource/tutor/fundam/images/linstre.gif

Image source

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

答案 2 :(得分:2)

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

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

根据documentation,无论图像大小如何,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函数参数的限制。

答案 3 :(得分: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

答案 4 :(得分:0)

也许你应该传递16.(一个浮点数)而不是16(一个int)。我试图测试它,但由于某种原因putdata根本没有倍增...所以我希望它只适合你。