Python 重新缩放PIL图像的强度

Python 重新缩放PIL图像的强度,python,image-processing,python-imaging-library,Python,Image Processing,Python Imaging Library,什么是重新缩放PIL图像强度的最简单/最干净的方法 假设我有一个来自12位相机的16位图像,因此只使用0–4095的值。我想重新缩放强度,以便使用整个范围0–65535。当图像表示为PIL的图像类型时,最简单/最干净的方法是什么 到目前为止,我提出的最佳解决方案是: pixels = img.getdata() img.putdata(pixels, 16) 这是可行的,但总是将四个最低有效位留空。理想情况下,我希望将每个值向左移动四位,然后将四个最高有效位复制到四个最低有效位。我不知道怎么做

什么是重新缩放PIL图像强度的最简单/最干净的方法

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

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

pixels = img.getdata()
img.putdata(pixels, 16)
这是可行的,但总是将四个最低有效位留空。理想情况下,我希望将每个值向左移动四位,然后将四个最高有效位复制到四个最低有效位。我不知道怎么做得那么快。

你需要做的是。 有关如何使用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
def(n):
返回n>0
65664#哎呀>2^16

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


但是,将4个msb复制到4个lsb中不是一个好办法:)

您需要进行直方图拉伸()而不是直方图均衡化:


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

也许您应该通过16。(浮点)而不是16(整数)。我试着测试它,但由于某种原因,数据根本不会成倍增长。。。因此,我希望它对您有效。

因为您知道像素值为0-4095,所以我找不到比这更快的方法:

new_image= image.point(lambda value: value<<4 | value>>8)
最大输出像素值将为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

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

两个链接完全相同,直方图均衡化以不同方式拉伸直方图的不同部分。我想做的只是均匀地拉伸直方图,以便使用整个强度范围。我认为复制4 MSB的原因是它将使用整个范围0–(2^16-1),因此原始图像中的饱和像素在重新缩放的图像中也将显示为饱和。的确,这是将每个通道的位数提升到更高的标准方法。这是一个非常好的主意,但因为如果PIL类型为“I”,则16位图像为,
point
的参数必须是
argument*scale+offset
形式的函数。当然,您是正确的。希望“第二次拍摄”对你来说足够有效。
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