如何在VIPS/Python中对某个音调范围应用转换
我必须对VIP(和Python)中16位tiff文件的不同色调范围应用各种转换。我已经设法做到了,但我是新来的贵宾,我不相信我这样做是有效率的。这些图像每幅都有几百兆字节,剪切每个多余的步骤可以为每个图像节省几秒钟的时间 我想知道是否有更有效的方法来实现我从下面的代码中获得的相同结果,例如使用查找表(我真的不知道它们在VIP中是如何工作的)。该代码分离红色通道中的阴影,并将其通过变换如何在VIPS/Python中对某个音调范围应用转换,python,image-processing,vips,Python,Image Processing,Vips,我必须对VIP(和Python)中16位tiff文件的不同色调范围应用各种转换。我已经设法做到了,但我是新来的贵宾,我不相信我这样做是有效率的。这些图像每幅都有几百兆字节,剪切每个多余的步骤可以为每个图像节省几秒钟的时间 我想知道是否有更有效的方法来实现我从下面的代码中获得的相同结果,例如使用查找表(我真的不知道它们在VIP中是如何工作的)。该代码分离红色通道中的阴影,并将其通过变换 im = Vips.Image.new_from_file("test.tiff") # Separate t
im = Vips.Image.new_from_file("test.tiff")
# Separate the red channel
band = im[0]
# Find the tone limit for the bottom 5%
lim = band.percent(5)
# Create a mask using the tone limit
mask = (band <= lim)
# Convert the mask to 16 bits
mask = mask.cast(band.BandFmt, shift = True)
# Run the transformation on the image and keep only the shadow areas
new_shadows = (65535 * (shadows / lim * 0.1)) & mask
我为您制作了一个演示程序,演示如何使用VIP直方图功能执行类似操作:
import sys
import pyvips
im = pyvips.Image.new_from_file(sys.argv[1])
# find the image histogram
#
# we'll get a uint image, one pixel high and 256 or
# 65536 pixels across, it'll have three bands for an RGB image source
hist = im.hist_find()
# find the normalised cumulative histogram
#
# for a 16-bit source, we'll have 65535 as the right-most element in each band
norm = hist.hist_cum().hist_norm()
# search from the left for the first pixel > 5%: the position of this pixel
# will give us the pixel value that 5% of pixels fall below
#
# .profile() gives back a pair of [column-profile, row-profile], we want index 1
# one. .getpoint() reads out a pixel as a Python array, so for an RGB Image
# we'll have something like [19.0, 16.0, 15.0] in shadows
shadows = (norm > 5.0 / 100.0 * norm.width).profile()[1].getpoint(0, 0)
# Now make an identity LUT that matches our original image
lut = pyvips.Image.identity(bands=im.bands,
ushort=(im.format == "ushort"))
# do something to the shadows ... here we just brighten them a lot
lut = (lut < shadows).ifthenelse(lut * 100, lut)
# make sure our lut is back in the original format, then map the image through
# it
im = im.maplut(lut.cast(im.format))
im.write_to_file(sys.argv[2])
导入系统
进口pyvips
im=pyvips.Image.new\u from\u文件(sys.argv[1])
#找到图像直方图
#
#我们将得到一个uint图像,一个像素高,256或更高
#65536像素宽,它将有三个波段用于RGB图像源
hist=im.hist_find()
#找到归一化的累积直方图
#
#对于16位源,每个频带中最右边的元素是65535
norm=hist.hist_cum().hist_norm()
#从左侧搜索第一个大于5%的像素:此像素的位置
#将给我们5%的像素低于的像素值
#
#.profile()返回一对[column profile,row profile],我们需要索引1
#一。getpoint()以Python数组的形式读取像素,因此对于RGB图像
#我们会在阴影中看到类似[19.0,16.0,15.0]的东西
阴影=(norm>5.0/100.0*norm.width).profile()[1].获取点(0,0)
#现在制作一个与原始图像匹配的标识LUT
lut=pyvips.Image.identity(bands=im.bands,
ushort=(im.format=“ushort”))
#对阴影做点什么。。。在这里,我们只是让它们变得更加明亮
lut=(lut<阴影)。如果其他(lut*100,lut)
#确保我们的lut恢复为原始格式,然后通过
#它
im=im.maplut(lut.cast(im.format))
im.write_到_文件(sys.argv[2])
它对源图像执行一次查找直方图操作,然后执行一次映射直方图操作,因此速度应该很快
这只是调整阴影,您需要稍微扩展它来处理中间色调和高光,但是您可以从单个初始直方图中进行所有三个修改,因此不会再慢了
如果您还有任何问题,请在libvips tracker上打开一个问题:
是的,您应该能够让它更快一点。例如,您正在运行(我猜?
percent
三次,每个波段一次。相反,在开始时找到图像的直方图,然后对其进行分析,以获得每个波段的百分比。请张贴一个小但完整的例子,我们可以尝试运行。编辑:正如你所说的,当然你也可以使用LUT,这将带来另一个巨大的加速。
import sys
import pyvips
im = pyvips.Image.new_from_file(sys.argv[1])
# find the image histogram
#
# we'll get a uint image, one pixel high and 256 or
# 65536 pixels across, it'll have three bands for an RGB image source
hist = im.hist_find()
# find the normalised cumulative histogram
#
# for a 16-bit source, we'll have 65535 as the right-most element in each band
norm = hist.hist_cum().hist_norm()
# search from the left for the first pixel > 5%: the position of this pixel
# will give us the pixel value that 5% of pixels fall below
#
# .profile() gives back a pair of [column-profile, row-profile], we want index 1
# one. .getpoint() reads out a pixel as a Python array, so for an RGB Image
# we'll have something like [19.0, 16.0, 15.0] in shadows
shadows = (norm > 5.0 / 100.0 * norm.width).profile()[1].getpoint(0, 0)
# Now make an identity LUT that matches our original image
lut = pyvips.Image.identity(bands=im.bands,
ushort=(im.format == "ushort"))
# do something to the shadows ... here we just brighten them a lot
lut = (lut < shadows).ifthenelse(lut * 100, lut)
# make sure our lut is back in the original format, then map the image through
# it
im = im.maplut(lut.cast(im.format))
im.write_to_file(sys.argv[2])