Mise au point de la chambre noire « camera obscura »
Boite noire permettant de projeter le sujet sur un support qu'un peintre peut alors reproduire.
Invention du procédé photographique
Utilisation de résine d'origine minérale : l'asphalte ou bitume de Judée.
Première photographie noir & blanc
Chambre noire avec bitume. Temps de pose de plusieurs jours
Invention de la pellicule
Film photographique transparent en rouleaux sensibles à la lumière grâce au bromure d'argent : Argentique
Première vraie photographie en couleur
Autochromes à base de fécule de pomme de terre.
Apparition des premières pellicules couleur
Trois couches sensibles respectivement au rouge, au bleu et au vert.
Invention du capteur CCD
Transfert de charges électriques par effet photoélectrique.
Premier appareil photo numérique
Masse de 3,6 kg, image de 100x100 pixels, temps d'enregistrement de 23 secondes.
Premier réflex numérique
Capable de prendre de photo de 2,7 mégapixels à une vitesse de 4,5 images/seconde.
Premier téléphone faisant appareil photo numérique
Il embarque un capteur de 2 mégapixels avec optique Carl Zeiss, autofocus et flash LED.
Les réseaux sociaux tels que Snapchat proposent des filtres permettant entre autre de modifier les visages en y ajoutant des accessoires ou des effets. Comment peut-on faire ce type de traitements en utilisant le langage Python ?
(possibilité de visionner : sur Lumni)
Que se passe-t-il si on zoome sur une image ? Les points observés sont appelés pixels. On dit que l'image est matricielle car en mathématiques une matrice désigne un tableau de nombres.
Remarque : On parle aussi de «carte de points» (de l'anglais «bitmap»)
Voici l'agrandissement de l'image d'un écran LCD (Liquid Cristal Display). On peut distinguer les pixels qui la composent. Si on agrandit encore l'image, on peut voir que chaque pixel est subdivisé en 3 rectangles (un rouge, un vert et un bleu) : ce sont les sous-pixels (ou luminophores).
L'œil et le cerveau réalisent une synthèse additive des couleurs. Toute lumière colorée peut être reproduite en superposant, dans certaines proportions, trois faisceaux lumineux de couleurs rouge, verte et bleue (nos yeux ne sont sensibles qu'à ces trois couleurs).
Chaque pixel est codé par trois valeurs, une pour la composante rouge, une autre pour la composante verte et une troisième pour la composante bleue. On parle de code RVB. Chacune de ces trois couleurs peut prendre 256 valeurs différentes (de 0 à 255).
Pour pouvoir coder un nombre jusqu'à la valeur 255, il faut 8 bits, soit un octet à un ordinateur. L'octet 00000000 correspond à la valeur décimale 0 tandis que l'octet 11111111 correspond à la valeur décimale 255. Ainsi pour coder les trois couleurs d'un pixel, il faut 3 octets soit 24 bits.
from PIL import Image
img = Image.open("sernin.jpg")
largeur, hauteur = img.size
print("largeur de l'image :", largeur, "pixels")
print("hauteur de l'image :", hauteur, "pixels")
code_01.py
pour observer le résultat.chat.jpg
.
from PIL import Image
img = Image.open("chat.jpg")
largeur, hauteur = img.size
definition = largeur*longueur
print("largeur de l'image :", largeur, "pixels")
print("hauteur de l'image :", hauteur, "pixels")
print("définition de l'image :", definition, "pixels")
from PIL import Image
img = Image.open("couleur.png")
r, v, b = img.getpixel((0, 0))
print("RVB :", r, v, b)
Description des lignes du programme ci-dessus :
couleur.png
et l'affecte à la variable img.
from PIL import Image
img = Image.open("couleur.png")
for pixel in [(0,0), (15,0), (30,0), (0,30), (15,30), (30,30)] :
r, v, b = img.getpixel(pixel)
print("pixel :", pixel)
print("RVB :", r, v, b)
from PIL import Image
largeur = 200
hauteur = 100
img = Image.new('RGB', (largeur, hauteur))
# Balayage de tous les pixels de l'image
for y in range(hauteur): # Balayage des lignes
for x in range(largeur): # Balayage des colonnes
img.putpixel((x, y), (255, 0, 0))
img.show()
img.save("rectanglerouge.png", "PNG")
Description des lignes du programme ci-dessus :
//
)
from PIL import Image
largeur = 200
hauteur = 100
img = Image.new('RGB', (largeur, hauteur))
for y in range(hauteur):
for x in range(largeur):
img.putpixel((x, y), (0, 0, 255))
img.show()
img.save("rectanglebleu.png", "PNG")
from PIL import Image
largeur = 200
hauteur = 100
img = Image.new('RGB', (largeur, hauteur))
for y in range(hauteur):
for x in range(largeur):
img.putpixel((x, y), (255, 255, 0))
img.show()
img.save("rectanglejaune.png", "PNG")
from PIL import Image
largeur = 200
hauteur = 100
img = Image.new('RGB', (largeur, hauteur))
for y in range(hauteur//2):
for x in range(largeur):
img.putpixel((x, y), (255, 0, 0))
img.show()
img.save("rectanglerougeamoitie.png", "PNG")
Une technique pour convertir une image en niveau de gris est de réaliser la moyenne des trois composantes RVB du pixel et d'affecter cette moyenne aux trois composantes RVB.
Attention : Les composantes doivent être des nombres entiers. Pour cela il y a toujours le double-slash //
pour réaliser la division entière ou bien la fonction int()
qui renvoie la partie entière de ce qui lui ait donné en argument.
from PIL import Image
img = Image.open("occitanie.jpg")
largeur, hauteur = img.size
for y in range(hauteur):
for x in range(largeur):
r, v, b = img.getpixel((x, y))
r = r # Ligne à modifier
v = v # Ligne à modifier
b = b # Ligne à modifier
img.putpixel((x, y),(r, v, b))
img.show()
img.save("image_modif.png", "PNG")
from PIL import Image
img = Image.open("occitanie.jpg")
largeur, hauteur = img.size
for y in range(hauteur):
for x in range(largeur):
r, v, b = img.getpixel((x, y))
g = (r+v+b)//3
img.putpixel((x, y),(g, g, g))
img.show()
img.save("image_modif.png", "PNG")
Quand une voiture autonome est en mouvement, il est important qu'elle sache reconnaître les objets qui l'entourent : véhicules, piétons, cyclistes, les panneaux de signalisation. Pour suivre la route, elle doit savoir en particulier reconnaître les bordures, les lignes blanches, les trottoirs, etc.
Pour cela, les photos réalisées par ses capteurs sont traitées par des algorithmes qui permettent de détecter les contours des objets qu'elle rencontre. L'objectif de cette activité est de découvrir le fonctionnement d'un de ces algorithmes de détection de contours.
Pour repérer la position d'un pixel, on repère d'abord la colonne x à laquelle il appartient, puis la ligne y. Notons un tel pixel P(x, y) et NG(x, y) son niveau de gris.
Pour détecter si le pixel P(x, y) appartient ou non à un contour, la méthode consiste à chercher une rupture d'intensité entre 2 pixels symétriques par rapport à P(x, y), appelés pixel voisins. Pour cela on calcule la différence entre les niveaux de gris de 2 pixels voisins. Si cette différence est assez élevée, le pixel fait parti du contour.
Attention : En python le premier pixel en haut à gauche a pour coordonnées (0, 0) et non (1, 1).
(x,y) | ||
Dans l'exemple précédent, seul un couple de pixels voisins est pris en compte dans une unique direction. Pour détecter des contours sur deux directions différentes, il faut prendre en compte deux couples de pixels voisins (voir schéma).
Pour cela, il faut calculer pour chacun la différence des niveaux de gris et afin de pouvoir les ajouter sans que les différences s'annulent du fait des valeurs négatives, il faudra élever leur valeur au carré.
Programmation de la détection de contours dans une image
L'algorithme permettant d'afficher les contours des objets sur une image a été partiellement programmé en python dans l'éditeur ci-dessous.
from PIL import Image
def contour(filename): # Crée la fonction contour
im = Image.open(filename) # Ouvre le fichier image
im_contour = Image.new(im.mode, im.size) # Crée une image vide de même taille
colonne, ligne = im.size
for y in range(1, ligne-1): # Boucles pour balayer les pixels sauf en bordure
for x in range(1, colonne-1):
a = im.getpixel((x-1, y-1)) # pixel au dessus à gauche
b = im.getpixel(( ... , ... )) # pixel en dessous à droite
c = ... # pixel au dessus à droite
d = ... # pixel en dessous à gauche
formule = (a-b)**2 + (c-d)**2
if formule > 800: # Test de contour Si le résultat est supérieur à 800
im_contour.putpixel((x, y), 0) # Colore en noir
else : # Sinon
im_contour.putpixel((x, y), 255) # Colore en blanc
return im_contour # Renvoi l'image avec les contours
im = contour("route_01.png") # Appele la fonction pour l'appliquer
im.show() # Affichage de l'image
im.save("contour.png","PNG") # Sauvegarde de l'image
Les appareils photo numérique sont équipés de capteurs photographiques composés d'une matrice d'éléments qui réagissent à la quantité de lumière qu'ils reçoivent. Ce sont les photosites.
Le filtre de Bayer fait en sorte qu'un photosite ne reçoive qu'une seule couleur primaire. Il y a deux fois plus de photosites exposés au vert pour être adapté à l'œil humain qui est plus sensibles au vert qu'au rouge ou au bleu.
Attention : photosite ≠ pixel
Un photosite ne correspond pas à un pixel car il ne contient l'information que d'une seule couleur (Rouge ou Verte ou Bleue) alors qu'un pixel est codé avec trois valeurs. Le processeur d'image traite les données des photosites pour compléter l'image. En effet, pour chaque photosite, deux canaux colorés sont manquants. Une des techniques utilisées est de calculer la moyenne des valeurs obtenues par les photosites adjacents pour extrapoler les valeurs des deux canaux manquants.
En utilisant les informations des photosites rouges et bleus à proximité d'un photosite vert, le processeur compose un pixel, avec ses trois couleurs. L'image brute ainsi obtenue en sortie du capteur est souvent au format RAW.
En lumière faible, il est souvent nécessaire d'utiliser plus de photosites pour recomposer un seul pixel ce qui conduit à une perte de définition de l'image.
R0
, V0
et B0
du pixel central à partir des valeurs adjacentes.
Découverte :
Voir une des photos les plus définies du monde avec 195 milliards de pixels de Shangai.
On peut obtenir quelques informations, et en particulier les informations de géolocalisation, d'une photo en accédant à ses métadonnées EXIF. Cela est réalisable grâce au système d'exploitation de votre ordinateur.
Après avoir téléchargé les images sur votre ordinateur :Remarque : En procédant ainsi, les données affichées se limitent à quelques paramètres de prise de vue et informations sur le matériel. On peut obtenir plus d'information avec un logiciel de retouche photo ou grâce à des solutions en ligne comme : Verexif.
Après avoir trouver les valeurs de latitude et longitude, il est possible d'utiliser un site tel que Coordonnées GPS pour déterminer le lieu de la prise de vue.
Ces métadonnées associées aux images sont facilement manipulables à l'aide de petits logiciels disponibles gratuitement tel que Exif Pilot.
Mario a perdu la combinaison à 4 lettres du cadenas qui sécurise son coffre. Le code est caché dans une image numérique. C'est de la stéganographie.
Votre objectif : Utiliser le protocole de codage pour retrouver le code à 4 lettres.
pixel 1 | pixel 2 | pixel 3 | |||||||
---|---|---|---|---|---|---|---|---|---|
Image initiale | 138 | 65 | 23 | 234 | 87 | 34 | 126 | 90 | 40 |
Octet à cacher | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | |
Image modifiée | 138 | 65 | 24 | 235 | 88 | 35 | 127 | 90 | 40 |
En appliquant ce système de code à l'image de gauche, on obtient l'image de droite. On ne perçoit aucune différente à l'œil nu.
(Cliquer pour télécharger)Caractère ASCII | Nombre binaire sur un octet |
---|---|
A | 1000001 |
B | 1000010 |
C | 1000011 |
D | 1000100 |
E | 1000101 |
F | 1000110 |
G | 1000111 |
H | 1001000 |
I | 1001001 |
J | 1001010 |
K | 1001011 |
L | 1001100 |
M | 1001101 |
N | 1001110 |
O | 1001111 |
P | 1010000 |
Q | 1010001 |
R | 1010010 |
S | 1010011 |
T | 1010100 |
U | 1010101 |
V | 1010110 |
W | 1010111 |
X | 1011000 |
Y | 1011001 |
Z | 1011010 |