[英]Doing the same as ImageMagick's “-level” in python / PIL?
我想調整python中圖像的顏色級別。 我可以使用任何可以輕松安裝在我的Ubuntu桌面上的python庫。 我想和ImageMagick的-level
( http://www.imagemagick.org/www/command-line-options.html#level )一樣。 PIL(Python圖像庫)似乎沒有它。 我一直在調用圖像convert
然后再讀回文件,但這看起來很浪費。 有更好/更快的方式嗎?
如果我理解正確的-level
的ImageMagick的選項,那么level_image
功能我提供應該做你想要什么。
有兩點需要注意:
編碼:
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.