代码之家  ›  专栏  ›  技术社区  ›  Amandasaurus

在python/pil中执行与imagemagick的“-level”相同的操作?

  •  3
  • Amandasaurus  · 技术社区  · 14 年前

    我想在python中调整图像的颜色级别。我可以使用任何可以轻松安装在我的Ubuntu桌面上的python库。我想和ImageMagick的一样 -level ( http://www.imagemagick.org/www/command-line-options.html#level )pil(python图像库)似乎没有。我一直在打电话 convert 在图像上再重新读取文件,但这似乎是浪费。有更好/更快的方法吗?

    3 回复  |  直到 6 年前
        1
  •  6
  •   tzot    14 年前

    如果我理解正确 -level 选择ImageMagick,然后 level_image 我提供的功能应该满足您的需要。

    需要注意的两件事:

    • 速度肯定可以提高
    • 它目前只适用于RGB图像
    • 该算法通过HSV颜色空间,只影响V(亮度)分量。

    代码:

    import colorsys
    
    class Level(object):
    
        def __init__(self, minv, maxv, gamma):
            self.minv= minv/255.0
            self.maxv= maxv/255.0
            self._interval= self.maxv - self.minv
            self._invgamma= 1.0/gamma
    
        def new_level(self, value):
            if value <= self.minv: return 0.0
            if value >= self.maxv: return 1.0
            return ((value - self.minv)/self._interval)**self._invgamma
    
        def convert_and_level(self, band_values):
            h, s, v= colorsys.rgb_to_hsv(*(i/255.0 for i in band_values))
            new_v= self.new_level(v)
            return tuple(int(255*i)
                    for i
                    in colorsys.hsv_to_rgb(h, s, new_v))
    
    def level_image(image, minv=0, maxv=255, gamma=1.0):
        """Level the brightness of image (a PIL.Image instance)
        All values ≤ minv will become 0
        All values ≥ maxv will become 255
        gamma controls the curve for all values between minv and maxv"""
    
        if image.mode != "RGB":
            raise ValueError("this works with RGB images only")
    
        new_image= image.copy()
    
        leveller= Level(minv, maxv, gamma)
        levelled_data= [
            leveller.convert_and_level(data)
            for data in image.getdata()]
        new_image.putdata(levelled_data)
        return new_image
    

    如果有某种方法可以使用pil进行rgb__h s v转换(反之亦然),那么可以将其拆分为H、S、V波段,使用 .point 方法的V波段和转换回RGB,大大加快了进程,但我没有找到这样的方法。

        2
  •  3
  •   Niki Yoshiuchi    14 年前

    为什么不使用 PythonMagick ?它是一个到图像magick的python接口。

        3
  •  0
  •   quickbug    6 年前

    这是我使用的代码。级别完成,1)在HSV图像的亮度通道上,2)根据结果中所需的黑白像素量。

    由于opencv使用numpy数组作为内部数据,因此可以修改代码以避免使用枕头。如果这样做,请注意opencv本机颜色空间是bgr。您必须相应地更改对cv.cvtcolor()的调用。

    from PIL import Image
    import numpy as np
    import cv2 as cv
    
    fileName = 'foo.JPG'
    fileOut = 'bar.JPG'
    imgPil = Image.open(fileName) 
    imgCV = np.asarray(imgPil, np.uint8)
    hsv = cv.cvtColor(imgCV, cv.COLOR_RGB2HSV)
    h,s,v = cv.split(hsv)
    ceil = np.percentile(v,95) # 5% of pixels will be white
    floor = np.percentile(v,5) # 5% of pixels will be black
    a = 255/(ceil-floor)
    b = floor*255/(floor-ceil)
    v = np.maximum(0,np.minimum(255,v*a+b)).astype(np.uint8)
    hsv = cv.merge((h,s,v))
    rgb = cv.cvtColor(hsv, cv.COLOR_HSV2RGB)
    imgPil = Image.fromarray(rgb)
    imgPil.save(fileOut)