Gå til innhold

[Python] RGB --> CIELAB/CIELCH


Anbefalte innlegg

Edit: tror jeg har fått det til å fungere. Resultat hvis noen er interesserte:

 

 

from numpy import matrix
from math import sqrt, sin, cos, atan2, pi, degrees, radians
from collections import defaultdict

def MostSimilar(reference, keys):
   """Take a reference colour and return its similarity to a list of colours

   Takes a reference (R, G, B) colour (0-255) and a list [(R1, G1, B1), ... (RN, GN, BN)]
   of colours (0-255) and returns a dictionary of type {difference : Colour}
   where Colour is one of the N colours from the provided list and difference is the difference
   between Colour and the provided reference colour
   """
   def RGB2Lch(rgb):
       #Convert to sRGB
       R, G, B = float(rgb[0]), float(rgb[1]), float(rgb[2])
       sRGB = (R/255., G/255., B/255.)

       #Convert to CIE XYZ
       C_LIN = []
       a = 0.055
       for C in sRGB:
           if C <= 0.04045:
               C_LIN.append(C/12.92)
           elif C > 0.04045:
               C_LIN.append(((C+a)/(1.+a))**2.4)
       C_LIN = matrix([[C_LIN[0]], [C_LIN[1]], [C_LIN[2]]])
       VALS  = matrix([[0.4124, 0.3576, 0.1805], 
                       [0.2126, 0.7152, 0.0722], 
                       [0.0193, 0.1192, 0.9505]])
       XYZ = (VALS*C_LIN).tolist()
       X, Y, Z = XYZ[0][0], XYZ[1][0], XYZ[2][0]

       #Convert to CIELAB
       def ft(t):
           if t > ((6./29.)**(3.)):
               return (t**(1./3.))
           elif t <= ((6./29.)**3):
               return ((1./3.)*((29./6.)**(2.))*t+(4./29.))

       Xn, Yn, Zn = 0.95047, 1.00000, 1.08883 #(*100 ? )

       L = 116.*ft(Y/Yn)-16
       A = 500.*(ft(X/Xn) - ft(Y/Yn))
       B = 200.*(ft(Y/Yn) - ft(Z/Zn))

       #Convert to CIE Lch
       #L = L
       C = sqrt((A**2)+(B**2))
       H = atan2(B,A)

       return L, A, B, C, H

   def dE(rLCH, rLAB, pLCH, pLAB):
       """reference and poll are two colours to compare"""
       L1, A1, B1, C1, H1 = rLAB[0], rLAB[1], rLAB[2], rLCH[1], rLCH[2]
       L2, A2, B2, C2, H2 = pLAB[0], pLAB[1], pLAB[2], pLCH[1], pLCH[2]

       dLd = L2-L1
       Lbar = (L1+L2)/2.
       Cbar = (C1+C2)/2.

       A1d = A1 + ((A1/2.)*(1-sqrt((Cbar**7)/((Cbar**7)+(25**7)))))
       A2d = A2 + ((A2/2.)*(1-sqrt((Cbar**7)/((Cbar**7)+(25**7)))))

       C1d = sqrt((A1d**2.)+(B1**2.))
       C2d = sqrt((A2d**2.)+(B2**2.))
       dCd = C1d - C2d
       Cbard = (C1d+C2d)/2.

       H1d = atan2(B1, A1d) % (2.*pi)
       H2d = atan2(B2, A2d) % (2.*pi)

       def find_dhd(H1d, H2d):
           diff1 = H1d-H2d
           diff2 = H2d-H1d
           if abs(diff1) <= pi:
               return diff2
           if abs(diff1) > pi:
               if H2d <= H1d:
                   return diff2+(2*pi)
               if H2d > H1d:
                   return diff2-(2*pi)

       #Note the difference between dhd and dHd
       dhd = find_dhd(H1d, H2d)
       dHd = 2*sqrt(C1d*C2d)*sin(dhd/2.)
       def find_Hbard(H1d, H2d):
           diff = H1d-H2d
           if diff <= pi:
               return (H1d+H2d)/2.
           if diff > pi:
               return (H1d+H2d+(2*pi))/2.

       Hbard = find_Hbard(H1d, H2d)

       T = 1-0.17*cos(Hbard-(pi/6.))+0.24*cos(2*Hbard)+0.32*cos(3*Hbard+(pi/30.))-0.20*cos(4*Hbard-((21.*pi)/60.))

       Sl = 1 + ((0.015*((Lbar-50.)**2))/(sqrt(20+((Lbar-50.)**2))))
       Sc = 1 + 0.045*Cbard
       Sh = 1 + 0.015*Cbard*T

       Rt = (-2.)*sqrt((Cbard**7.)/((Cbard**7.)+(25.**7.)))*sin((pi/6.)**(-(((Hbard-radians(275.))/25.)**2)))

       Empfindung = sqrt(((dLd/Sl)**2) + ((dCd/Sc)**2) + ((dHd/Sh)**2) + (Rt*(dCd/Sc)*(dHd/Sh)))
       return Empfindung

   rL, rA, rB, rC, rH = RGB2Lch(reference)
   values = defaultdict(list)
   for colour in keys:
       if colour == reference:
           continue
       pL, pA, pB, pC, pH = RGB2Lch(colour)
       values[dE((rL, rC, rH), (rL, rA, rB), (pL, pC, pH), (pL, pA, pB))].append(colour)

   return values

#Example:
#MostSimilar((173, 255, 14), [(1, 2, 3), (255, 255, 0), (203, 255, 0), (255, 255, 254), (0, 0, 0)])

 

 


 

Opprinnelig inlegg:

 

Forsøker å konverte en RGB farge til en farge i CIELCH for å finne fargedifferanser

http://en.wikipedia.org/wiki/Color_difference#CIEDE2000

 

Jeg (tror) jeg så langt har kommet frem til CIE XYZ og skal til å konvertere til CIELAB, men har støtt på et problem - Mer spesifikt er jeg ikke sikker på hva XYZ er, da artikkelen om å konvertere til CIELAB nevner to forskjellige XYZ tupler. (X, Y, Z og Xn, Yn, Zn). Jeg finner ingen forklaring på hva XYZ er, bare Xn Yn Zn (tristimulus verdiene, som er verdiene jeg tror jeg har funnet).

 

(Jeg er også usikker på om jeg har gjort noe feil i konverteringen fra RGB til sRGB).

 

Uansett, jeg står fast på omgjøringen fra CIE XYZ til CIELAB.

 

Dersom jeg ikke har gjort noe veldig feil, har jeg så langt:

*Omgjort fra RGB til sRGB

*Omgjort fra sRGB til CIE XYZ

 

 

import sys
from numpy import matrix

def deltaE(rgb):
   #Convert to sRGB
   R, G, B = float(rgb[0]), float(rgb[1]), float(rgb[2])
   sRGB = (R/255, G/255, B/255)

   #Convert to CIE XYZ
   C_LIN = []
   a = 0.055
   for C in sRGB:
       if C <= 0.04045:
           C_LIN.append(C/12.92)
       elif C > 0.04045:
           C_LIN.append(((C+a)/(1.+a))**2.4)
   C_LIN = matrix([[C_LIN[0]], [C_LIN[1]], [C_LIN[2]]])
   VALS  = matrix([[0.4124, 0.3576, 0.1805], 
                   [0.2126, 0.7152, 0.0722], 
                   [0.0193, 0.1192, 0.9505]])
   XYZ = (VALS*C_LIN).tolist()
   X, Y, Z = XYZ[0][0], XYZ[1][0], XYZ[2][0]

   #Convert to CIELAB
   #http://en.wikipedia.org/wiki/Lab_color_space#The_forward_transformation

deltaE((255, 0, 0))
sys.exit()

Endret av Yumekui
Lenke til kommentar
Videoannonse
Annonse

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...