Seite 1 von 1

HSV (Saettigung) eines Bildes veraendern

Verfasst: Freitag 7. April 2006, 18:56
von HappyMonk
Hallo erstmal,

ich experimentiere z. Zt. mit Pil herum und versuche die Saettigung eines Bildes zu veraendern, kann aber dazu nichts genaueres finden. Ich hab schon danach gegoogled und hier im forum gesucht aber ich kann dazu nichts finden. Das Ziel ist es die Saettigung eines Bildes um 200% zu erhoehen. Bin fuer jede Antwort dankbar...

HappyMonk

Verfasst: Sonntag 9. April 2006, 00:06
von BlackJack
Ich weiss nicht, ob's im HSV Farbmodell operiert, aber es macht Bilder "doppelt so bunt":

Code: Alles auswählen

import Image, ImageEnhance

image = Image.open('test.jpg')
enhancer = ImageEnhance.Color(image)
enhanced_image = enhancer.enhance(2)
enhanced_image.show()

Verfasst: Sonntag 9. April 2006, 00:28
von HappyMonk
@ Black_Jack: Ist zwar nicht genau das was ich gesucht habe aber das sieht schon recht vielversprechend aus. Vielen Dank...

Verfasst: Sonntag 9. April 2006, 08:42
von henning
Man müsste die RGB-Werte nach HSV und zurück rechnen können.
Ich bin uach sicher irgendwo schonmal Python-Code dafür gesehen zu haben, weiß aber nicht mehr wo. Entweder wars tatsächlich die PIL selbst oder es war soya.

Mathematisch suchst du ja "nur" nach bestimmten Basisvektoren für den "Farbvektorraum" der mit den Vektoren R, G und B aufgespannt wird 8)

Ansonsten einfach mal googlen, da findet man bestimmt ein bisschen pseudocode zu dem thema

Verfasst: Montag 10. April 2006, 23:11
von BlackJack
Komplett braucht man die Umrechnung gar nicht machen, wenn man nur die Sättigung ändern möchte. Hier ist ein wenig Quelltext um die Sättigung eines RGB-Bildes zu verändern.

Einmal eine reine Python-Variante, die natürlich nicht so besonders schnell ist. Mit psyco lief's bei mir ca. 50% schneller. Und dann gibt's weiter unten noch eine Pyrex-Variante, die sehr flott ist.

Code: Alles auswählen

from __future__ import division
import Image
# import _test

# import psyco
# psyco.full()

def change_saturation(rgb, factor):
    """Change the saturation of a RGB pixel.
    
    This function takes an RGB pixel as tuple and returns an RGB pixel with its
    saturation changed by a given `factor`.  Saturation means saturation in the
    HSV color model.  A factor of ``0.0`` results in a grey pixel and a factor
    of ``1.0`` returns the values unchanged.  For higher factors the new pixels
    saturation value is clipped to ``1.0``.
    """
    max_value = max(rgb)
    if max_value:
        min_value = min(rgb)
        length = max_value - min_value
        new_saturation = (length / max_value) * factor
        if new_saturation > 1:
            new_saturation = 1
        new_min_value = int(max_value * (1 - new_saturation))
        new_rgb = list()
        for component in rgb:
            if component == min_value:
                component = new_min_value
            elif component != max_value:
                component = int(((component - min_value) / length)
                                * (max_value - new_min_value) + new_min_value)
            new_rgb.append(component)
        return tuple(new_rgb)
    else:
        return rgb


def double_saturation():
    image = Image.open('gfx/test.jpg')
    image.putdata([change_saturation(pixel, 2) for pixel in image.getdata()])
    # _test.change_saturation(image, 2)
    image.show()


if __name__ == '__main__':
    double_saturation()
Und hier der Pyrex-Quelltext:

Code: Alles auswählen

import array


cdef void _change_saturation(unsigned char *image_data,
                             unsigned int pixel_count,
                             double factor):
    cdef unsigned char *new_rgb
    cdef unsigned char max_value, min_value, new_min_value
    cdef unsigned char component
    cdef unsigned int dummy, i
    cdef double length, new_saturation

    new_rgb = image_data
    for dummy from 0 <= dummy < pixel_count:
        min_value = max_value = new_rgb[0]
        for i from 1 <= i < 3:
            if new_rgb[i] < min_value:
                min_value = new_rgb[i]
            elif new_rgb[i] > max_value:
                max_value = new_rgb[i]
        
        if max_value:
            length = max_value - min_value
            new_saturation = (length / max_value) * factor
            if new_saturation > 1:
                new_saturation = 1
            new_min_value = max_value * (1 - new_saturation)
            for i from 0 <= i < 3:
                component = new_rgb[i]
                if component == min_value:
                    component = new_min_value
                elif component != max_value:
                    component = (((component - min_value) / length)
                                 * (max_value - new_min_value) + new_min_value)
                new_rgb[i] = component
        new_rgb = new_rgb + 3


def change_saturation(object image, double factor):
    """Change the saturation of `image` by `factor`.
    
    The `image` has to be in RGB mode.  Otherwise the result is undefined and
    may look funny.
    
    :TODO: Handle other modes than RGB.  At least RGBA, RGBX, BGR and P.
    """
    cdef unsigned int data_ptr, size
    
    data = array.array('c', image.tostring())
    data_ptr, size = data.buffer_info()
    _change_saturation(<unsigned char*> data_ptr, size / 3, factor)
    image.fromstring(data.tostring())
Übersetzt habe ich den mit:

Code: Alles auswählen

pyrexc _test.pyx
gcc -O6 -shared -fPIC -I/usr/include/python2.4/ -o _test.so _test.c

Verfasst: Dienstag 11. April 2006, 05:59
von modelnine
gcc -O6
-O3 hätte es auch getan, alle -Oi für i > 3 wird vom gcc als -O3 behandelt...

Verfasst: Mittwoch 12. April 2006, 14:52
von HappyMonk
Danke fuer die vielen Antworten : )