Делать так же, как "-уровень" ImageMagick в Python / PIL? - PullRequest
3 голосов
/ 24 июня 2010

Я хочу настроить цветовые уровни изображения в Python. Я могу использовать любую библиотеку Python, которую можно легко установить на моем рабочем столе Ubuntu. Я хочу сделать то же самое, что и ImageMagick -level (http://www.imagemagick.org/www/command-line-options.html#level). PIL (библиотека изображений Python), похоже, не имеет его. Я звоню convert на изображение и затем снова читаю в файле, но это кажется расточительным. Есть ли лучший / более быстрый способ?

Ответы [ 3 ]

6 голосов
/ 27 июня 2010

Если я правильно понял параметр -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

Если есть какой-либо способ выполнить преобразование RGB → HSV (и наоборот) с использованием PIL, то можно разделить на полосы H, S, V, использовать метод .point для полосы V и преобразовать обратно в RGB, значительно ускоряющий процесс; Однако я не нашел такой способ.

3 голосов
/ 24 июня 2010

Почему бы не использовать PythonMagick ? Это интерфейс Python для Image Magick.

0 голосов
/ 12 декабря 2018

Это код, который я использую. Уровни сделаны, 1) на канале яркости изображения HSV и, 2) в соответствии с желаемым количеством черных и белых пикселей в результате.

Код можно изменить, чтобы избежать использования подушки, поскольку openCV использует в качестве внутренних данных пустые массивы. Если вы делаете это, имейте в виду, что родное цветовое пространство 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)
...