簡體   English   中英

在python / PIL中像ImageMagick的“-level”一樣嗎?

[英]Doing the same as ImageMagick's “-level” in python / PIL?

我想調整python中圖像的顏色級別。 我可以使用任何可以輕松安裝在我的Ubuntu桌面上的python庫。 我想和ImageMagick的-levelhttp://www.imagemagick.org/www/command-line-options.html#level )一樣。 PIL(Python圖像庫)似乎沒有它。 我一直在調用圖像convert然后再讀回文件,但這看起來很浪費。 有更好/更快的方式嗎?

如果我理解正確的-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→HSV轉換(反之亦然),那么可以分割成H,S,V波段,使用V波段的.point方法並轉換回RGB,加速這個過程很多; 但是,我還沒有找到這樣的方法。

為什么不使用PythonMagick 它是Image Magick的Python界面。

這是我使用的代碼。 級別在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)

在這里使用此鏈接的代碼

# Auto leveling for image

    def levels(data, all_same = 0, clip = 0): 

        if data.mode not in ['RGB', 'CMYK']: 
            return data 

        ## get redistriputed histogram scalled smoothly
        lut = _makelut(data, all_same, clip) 

        ## update image points using histogram
        data = data.point(lut) 

        return data 

    def _find_hi_lo(lut, clip): 
        min = None 
        max = None 

        for i in range(len(lut)): 
            if lut[i] > clip: 
                min = i 
                break 

        lut.reverse() 

        for i in range(len(lut)): 
            if lut[i] > clip: 
                max = 255 - i 
                break 

        return min, max 

    def _scale(channels, min, max): 
        lut = []
        # hefny fix
        ratio = float(max-min)
        if ratio == 0:
            ratio = 1

        for i in range (channels): 
            for i in range(256): 
                value = int((i - min)*(255.0/ratio)) 
                if value < 0: 
                    value = 0 
                if value > 255: 
                    value = 255 
                lut.append(value) 

        return lut 


    def _makelut(data, all_same, clip): 

        histogram = data.histogram() 

        lut = [] 
        r, g, b, k = [], [], [], [] 

        channels = len(histogram)/256 

        for i in range(256): 
            r.append(histogram[i]) 
            g.append(histogram[256+i]) 
            b.append(histogram[512+i]) 
        if channels == 4: 
            for i in range(256): 
                k.append(histogram[768+i]) 


        rmin, rmax = _find_hi_lo(r, clip) 
        gmin, gmax = _find_hi_lo(g, clip) 
        bmin, bmax = _find_hi_lo(b, clip) 
        if channels == 4: 
            kmin, kmax = _find_hi_lo(k) 
        else: 
            kmin, kmax = 128, 128 

        if all_same == 1: 

            min_max = [rmin, gmin, bmin, kmin, rmax, gmax, bmax, kmax] 
            min_max.sort() 
            lut = _scale(channels, min_max[0], min_max[-1]) 

        else: 

            r_lut = _scale(1, rmin, rmax) 
            g_lut = _scale(1, gmin, gmax) 
            b_lut = _scale(1, bmin, bmax) 
            if channels == 4: 
                k_lut = _scale(1, kmin, kmax) 

            lut = [] 

            for i in range (256): 
                lut.append(r_lut[i]) 
            for i in range (256): 
                lut.append(g_lut[i]) 
            for i in range (256): 
                lut.append(b_lut[i]) 
            if channels == 4: 
                for i in range (256): 
                    lut.append(k_lut[i]) 

        return lut 

from PIL import ImageEnhance , ImageDraw , Image
img = Image.open(file_path)
img2 = levels(img)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM