Question

Comment calculer la similarité entre deux couleurs dans l'espace de couleurs RGBA? (où la couleur de fond est inconnu bien sûr)

Je dois remapper une image RGBA à une palette de couleurs RGBA en trouvant le meilleur entrée de la palette pour chaque pixel dans l'image *.

Dans l'espace colorimétrique RVB la couleur la plus similaire peut être considéré comme celui qui a la plus petite distance euclidienne. Cependant, cette approche ne fonctionne pas dans RGBA, par exemple, la distance euclidienne de rgba(0,0,0,0) à rgba(0,0,0,50%) est plus petit que de rgba(100%,100%,100%,1%), mais celui-ci est beaucoup mieux.

J'utilise l'espace couleur prémultipliée RGBA:

r = r×a
g = g×a
b = b×a

et j'ai essayé cette formule ( modifier: Voir la réponse ci-dessous pour une meilleure formule ):

Δr² + Δg² + Δb² + 3 × Δa²

mais il n'a pas voir optimale - en images avec des gradients semi-transparents, il trouve les mauvaises couleurs qui provoquent des discontinuités / arêtes vives. proportions linéaires entre couleurs opaques et alpha semble louche.

Quelle est la formule optimale?


*) pour la simplicité de cette question, je suis ignorant la diffusion d'erreur, les espaces de couleur gamma et psychovisuelle.


Un peu lié: si vous voulez trouver la couleur la plus proche dans cet espace RGBA non-euclidienne, vp arbres sont les meilleurs.

Était-ce utile?

La solution

Enfin, je l'ai trouvé! Après des tests approfondis et d'expérimentation mes conclusions sont les suivantes:

  • La bonne façon consiste à calculer au maximum différence possible entre les deux couleurs.
    Les formules avec tout type de différence moyenne / typique estimée avait la place pour discontinuités.

  • Je ne pouvais pas trouver une formule de travail qui calcule la distance sans mélange des couleurs RGBA avec des arrière-plans.

  • Il n'y a pas besoin de prendre toutes possible la couleur de fond en compte. Il peut être simplifié au maximum vers le bas pour le mélange et le minimum séparément pour chacun des canaux R / G / B:

    1. mélanger le canal dans les deux couleurs avec chaîne = 0 comme arrière-plan, mesurer la différence quadratique
    2. Assemblage du canal dans les deux couleurs avec chaîne = max comme arrière-plan, mesurer la différence quadratique
    3. prendre plus des deux.

Heureusement le mélange avec « blanc » et « noir » est trivial lorsque vous utilisez prémultipliée alpha (r = r×a).

La formule complète est:

max((r₁-r₂)², (r₁-r₂ - a₁+a₂)²) +
max((g₁-g₂)², (g₁-g₂ - a₁+a₂)²) +
max((b₁-b₂)², (b₁-b₂ - a₁+a₂)²)

C Source, y compris la mise en œuvre SSE2 .

Autres conseils

Plusieurs principes:

  1. Lorsque deux couleurs ont la même alpha, rgbaDistance = rgbDistance * (alpha / 255). Compatible avec l'algorithme de distance de couleur RVB lorsque les deux alpha sont 255.
  2. Toutes les couleurs avec une très faible alpha sont similaires.
  3. Le rgbaDistance entre deux couleurs avec la même RVB dépend linéairement de delta Alpha.
double DistanceSquared(Color a, Color b)
{
    int deltaR = a.R - b.R;
    int deltaG = a.G - b.G;
    int deltaB = a.B - b.B;
    int deltaAlpha = a.A - B.A;
    double rgbDistanceSquared = (deltaR * deltaR + deltaG * deltaG + deltaB * deltaB) / 3;
    return deltaAlpha * deltaAlpha / 2.0 + rgbDistanceSquared * a.A * b.A / (255 * 255);
}

Mon idée est d'intégrer une fois sur toutes les couleurs de fond possibles et en moyenne l'erreur quadratique.

i.e.. calculer pour chaque composant (en utilisant le canal rouge comme exemple ici)

entier de 0 à 1 ((r1 * a1 + rB * (1-a1)) - (r2 * a2 + rB * (1-a2))) ^ 2 * DRB

qui, si je calcule correctement évalue à:

dA=a1-a2
dRA=r1*a1-r2*a2
errorR=dRA^2+dA*dRA+dA^2/3

Et puis on additionne ces sur R, G et B.

Tout d'abord, un problème très intéressant :)
Je n'ai pas une solution complète (du moins pas encore), mais il y a 2 cas extrêmes évidentes, nous devrions considérer:
Lorsque Δa==0 le problème est similaire à l'espace RVB
Lorsque Δa==1 le problème est que sur l'espace alpha 1-dim
Ainsi, la formule (qui est très similaire à celui que vous dites) qui satisferait qui est:
(Δr² + Δg² + Δb²) × (1-(1-Δa)²) + Δa² ou (Δr² + Δg² + Δb²) × (1-Δa²) + Δa²

Dans tous les cas, il serait probablement quelque chose comme (Δr² + Δg² + Δb²) × f(Δa) + Δa²

Si je vous, je voudrais essayer de simuler avec différentes paires de RGBA et différentes couleurs de fond pour trouver la meilleure fonction f(Δa). Pas très mathematic, mais vous donnera une réponse assez proche

Je ne l'ai jamais fait, mais la théorie et la pratique de dire que la conversion des valeurs RVB dans l'image et la palette luminance-chrominance vous aidera à trouver les meilleurs matchs. Je laisser seul le canal alpha, la transparence devrait avoir peu à rien à voir avec la partie « recherche mieux ».

Ce xmass j'ai fait quelques photomosaïques pour des cadeaux en utilisant un logiciel open-source correspondant à des fragments de l'image originale à une collection d'images. Cela semble un problème plus difficile que celui que vous essayez de résoudre. L'un d'eux était des programmes metapixel .

Enfin, la meilleure option devrait être d'utiliser une bibliothèque existante pour convertir l'image en un format, comme PNG, où vous pouvez contrôler la palette.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top