Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle alpha values #3

Open
CairX opened this issue Aug 14, 2017 · 3 comments
Open

Handle alpha values #3

CairX opened this issue Aug 14, 2017 · 3 comments

Comments

@CairX
Copy link
Owner

CairX commented Aug 14, 2017

No description provided.

@arod40
Copy link

arod40 commented Jul 27, 2020

Hello,

I dont know if this is exactly what you are looking for here, but I got a use case when I had to get rid of background(alpha=0) pixels, a.k.a not to count their color, and I solved easily. I could make a PR if you want. Im gonna leave the code here in any case.

import collections

from PIL import Image, ImageDraw

from extcolors import conversion
from extcolors import difference

DEFAULT_TOLERANCE = 32


class Color:
    def __init__(self, rgb=None, lab=None, count=0):
        self.rgb = rgb
        self.lab = lab
        self.count = count
        self.compressed = False

    def __lt__(self, other):
        return self.count < other.count

def extract_from_image(img, tolerance=DEFAULT_TOLERANCE, limit=None, transparence=False):
    pixels = load(img, transparence)
    colors = count_colors(pixels)
    colors = compress(colors, tolerance)

    if limit:
        limit = min(int(limit), len(colors))
        colors = colors[:limit]

    colors = [(color.rgb, color.count) for color in colors]

    return colors, len(pixels)


def extract_from_path(path, tolerance=DEFAULT_TOLERANCE, limit=None, transparence=False):
    img = Image.open(path)
    return extract_from_image(img, tolerance, limit, transparence)


def load(img, transparence):
    if transparence:
        img = img.convert("RGBA")
        return list(filter(lambda x: x[3] > 0, img.getdata()))
    else:
        img = img.convert("RGB")
        return list(img.getdata())


def count_colors(pixels):
    counter = collections.defaultdict(int)
    for color in pixels:
        counter[color] += 1

    colors = []
    for rgb, count in counter.items():
        lab = conversion.rgb_lab(rgb)
        colors.append(Color(rgb=rgb, lab=lab, count=count))

    return colors


def compress(colors, tolerance):
    colors.sort(reverse=True)

    if tolerance <= 0:
        return colors

    i = 0
    while i < len(colors):
        larger = colors[i]

        if not larger.compressed:
            j = i + 1
            while j < len(colors):
                smaller = colors[j]

                if not smaller.compressed and difference.cie76(
                        larger.lab, smaller.lab) < tolerance:
                    larger.count += smaller.count
                    smaller.compressed = True

                j += 1
        i += 1

    colors = [color for color in colors if not color.compressed]
    colors.sort(reverse=True)

    return colors

This is the full code in the modified __init__.py file. Its quite silly actually, its just about adding a boolean transparent parameter and filtering the pixels.

@CairX
Copy link
Owner Author

CairX commented Jul 28, 2020

Thank you for sharing your solution, much appreciated. I like the idea to remove anything with zero alpha, it feels intuitive. I will use you idea to setup some tests and investigate further, hopefully I will have some time during the weekend.

I haven't had a use case for images with transparency yet and not sure what would be a desired way to handle alpha that isn't either zero or full. I imagine a blend option would be of interest to be able to decide how the result should be affected. Is this something you encounter in your scenario?

@CairX
Copy link
Owner Author

CairX commented Sep 7, 2020

@arod40 Sorry for not getting back to this sooner. Have now submitted 47f4ee9, that strips out pixels that are fully transparent which prevents the skew towards black in the result. The documentation has also been updated to explain that current status of transparency support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants