Table des matières Python

Mesures de couleurs de surface par spectrométrie

1. Montage expérimental

Une feuille de papier canson coloré est éclairée par une ampoule à incandescence de 40 W placée à environ 5 cm. L'extrémité de la fibre optique du spectromètre est placée en vis à vis du papier (à environ 1 cm) de manière à prélever la lumière diffusée.

2. Coefficient de réflexion

On compare le spectre de la lumière réfléchie par le papier rouge pourpre à celui de l'illuminant. On trace aussi le signal correspondant au bruit de fond du capteur CCD, obtenu en plaçant l'extrémité de la fibre optique dans l'obscurité et avec le même temps d'intégration (1500 ms).

from pylab import *
from Spectrometre import *
spectreIlluminant = Spectre("IlluminantTungstene.txt")
spectreRouge = Spectre("papierRougeIT.txt")
spectreFond = Spectre("bruitFond1500.txt")
clf()
xlabel('lambda (nm)')
ylabel('I')
plot(spectreIlluminant.Lambda,spectreIlluminant.I,c='k')
plot(spectreRouge.Lambda,spectreRouge.I,c='r')
plot(spectreFond.Lambda,spectreFond.I,c='y')
grid(True)
axis([400,700,0,20])
            
plotAplotA.pdf

L'illuminant est une ampoule à incandescence. Son spectre a été obtenu en plaçant la lampe à une distance de l'entrée de la fibre optique telle que la valeur obtenue à 700 nm soit identique à celle diffusée par le papier. Le temps d'intégration a été augmentée jusqu'à 1500 ms de manière à amplifier le signal dans la partie bleue du spectre, ce qui a pour effet de le saturer au delà de 750 nm, domaine qui n'a que peu d'effet sur les calculs des couleurs. On constate par ailleurs que le signal en dessous de 500 nm provient en fait du bruit de fond du capteur CCD. On corrige le spectre de la lumière diffusée en retranchant le bruit de fond.

for k in range(2048):
    spectreRouge.I[k] = spectreRouge.I[k] - spectreFond.I[k]
            

Le rapport des deux spectres définit le coefficient de réflexion du papier rouge, à une constante multiplicative près. Cette indétermination est sans conséquence sur le calcul des coordonnées trichromatiques, puisque seule la variation relative du coefficient avec la longueur d'onde détermine la couleur. On affecte une valeur 1 au coefficient de réflexion au delà de 700 nm.

def rapport(spectre1,spectre2): 
    L = spectre1.Lambda
    R = []
    for k in range(2048):
        if k < 1423: 
            R.append(spectre1.I[k]/spectre2.I[k])
        else:
            R.append(1)
    return [L,R]
[L,Rrouge] = rapport(spectreRouge,spectreIlluminant)
clf()
xlabel('lambda (nm)')
ylabel('R')
plot(L,Rrouge,c='r')
grid(True)
axis([400,700,0,1])
            
plotBplotB.pdf

On remarque la présence d'un bruit important en dessous de 550 nm, dû à la faiblesse de l'illuminant dans ce domaine. L'incertitude sur le coefficient de réflexion est de l'ordre de 10 %.

3. Coordonnées trichromatiques

La couleur de la surface éclairée par un illuminant déterminé est définie par les coordonnées trichromatiques. On utilise pour ce calcul l'illuminant D65, à ne pas confondre avec l'illuminant tungstène utilisé pour les mesures.

from CieXYZ import CIEXYZ
cie = CIEXYZ("../ciexyz/ciexyz31.txt") 
cie.readD65("../ciexyz/IlluminantD65.txt");
cie.setIlluminant("D65",0)
def Rf(l):
    k = spectreIlluminant.indiceLambda(l)  
    return Rrouge[k]
XYZ=cie.spectralF2XYZ(Rf) 
xyRouge=cie.XYZ2xy(XYZ[0],XYZ[1],XYZ[2])
                
print(xyRouge)
--> [0.4546381057945025, 0.31193913442497306]

4. Autres mesures

On reprend le traitement précédent pour un papier de couleur jaune :

spectreJaune = Spectre("papierJauneIT.txt")
for k in range(2048):
    spectreJaune.I[k] = spectreJaune.I[k] - spectreFond.I[k]
[L,Rjaune] = rapport(spectreJaune,spectreIlluminant)
clf()
xlabel('lambda (nm)')
ylabel('R')
plot(L,Rjaune,c='r')
axis([400,700,0,1])
grid(True)
                
plotCplotC.pdf
def Rf(l):
    k = spectreIlluminant.indiceLambda(l)  
    return Rjaune[k]
XYZ=cie.spectralF2XYZ(Rf) 
xyJaune=cie.XYZ2xy(XYZ[0],XYZ[1],XYZ[2])
                
print(xyJaune)
--> [0.425190730051117, 0.4155646159268138]

Le calcul suivant traite le cas d'un papier blanc :

 
spectreBlanc = Spectre("papierBlancIT.txt")
for k in range(2048):
    spectreBlanc.I[k] = spectreBlanc.I[k] - spectreFond.I[k]
[L,Rblanc] = rapport(spectreBlanc,spectreIlluminant)
clf()
xlabel('lambda (nm)')
ylabel('R')
plot(L,Rblanc,c='r')
axis([400,700,0,1])
grid(True)
                
plotDplotD.pdf
def Rf(l):
    k = spectreIlluminant.indiceLambda(l)  
    return Rblanc[k]
XYZ=cie.spectralF2XYZ(Rf) 
xyBlanc=cie.XYZ2xy(XYZ[0],XYZ[1],XYZ[2])
                
print(xyBlanc)
--> [0.32148945043708216, 0.32820444875711874]

5. Diagramme de chromaticité

Les mesures précédentes sont placées sur le diagramme de chromaticité :

from DiaChrom import *
diagram=DiaChrom(cie)
diagram.plotSpectre()
sRGB = XYZ2RGB([0.64,0.33],[0.3,0.6],[0.15,0.06],[0.3127,0.329])
diagram.paintRGB(sRGB,"sRGB",0.002)
figure(1,figsize=(9,8))
xlabel('x')
ylabel('y')
plot([xyRouge[0]],[xyRouge[1]],color="r",marker="o",label="Rouge")
plot([xyJaune[0]],[xyJaune[1]],color="y",marker="o",label="Jaune")
plot([xyBlanc[0]],[xyBlanc[1]],color="w",marker="o",label="Blanc")
legend();
axis([0,1,0,1])
grid(True)
                
plotEplotE.pdf
Creative Commons LicenseTextes et figures sont mis à disposition sous contrat Creative Commons.