Recadrer vos images
#Ingénierie
Lors que nous réalisons des sites internet, nous avons besoin d'afficher des images qui seront redimensionnées automatiquement en fonction de chacune des tailles de support (Navigateurs, tablettes, mobiles).
Prenons par exemple un carousel imaginé par le graphiste
Maintenant si on imagine cette image sur un écran de taille différente en utilisant notre habituelle recadrage CSS background-size: cover
on aura sur certaines résolutions des résultats ressemblant à :
Le premier réflexe serait donc de changer la background-position
mais si nous changeons d'image en laissant l'utilisateur charger ses propres images cela ne fonctionnera pas.
Une idée
Après réflexion, nous nous sommes dit que l'idéal serait d'être capable de définir une zone "chaude" sur l'image, c'est-à-dire une zone que l'on voudrait à tout prix conserver.
Sur une photo avec un visage, nous avons déterminé qu'il serait donc intéressant de toujours avoir le visage visible.
Une détection automatisée
Grace aux solutions AWS Rekognition ou Google Vision nous pouvons récupérer de nombreuses informations sur les images (Mots clés, images similaires, position des visages, et bien plus encore).
Nous avons donc mis en place ces deux plateformes pour comparer leur performance sur la détection des visages. Un léger avantage est donné à AWS qui a la capacité de reconnaitre les visages plus discrets (petits ou collés à un autre élément) tel que sur l'image ci-dessus.
Repositionner la zone chaude
Une fois la box du visage principal detectée grâce à la réponse AWS
BoundingBox": {
"Top": 0.10033445060253143,
"Left": 0.6947891116142273,
"Height": 0.2829945981502533,
"Width": 0.13647642731666565
}
Nous savons que le visage est à 10% du haut de l'image, 69.4% de la gauche et mesure 28.29% par 13.6%.
Nous allons donc positionner l'image dans un container
de hauteur auto
et de largeur 100%
.
Si le container
est plus haut que l'image, nous allons inverser les valeurs : hauteur=100% et largeur=auto.
Enfin en fonction de l'écart de taille entre la largeur / hauteur de l'image et celle du container, nous allons repositionner le visage de manière à ce qu'il reste toujours au même pourcentage (haut gauche de l'image) dans la limite du container pour ne pas créer d'espace blanc.
Ok ce n'est pas très clair de prime abord, mais c'est assez simple, en bon français cela donne :
var box = {
"Top": 0.10033445060253143,
"Left": 0.6947891116142273,
"Height": 0.2829945981502533,
"Width": 0.13647642731666565
};
if (containerHeight > imgHeight) {
var zoom = (containerHeight - imgHeight) / imgHeight;
var newPositionLeft = (1 + zoom) * positionLeft;
var newPositionTop = (1 + zoom) * positionTop;
// On agrandi la largeur
img.style.height = containerHeight + "px";
img.style.width = "auto";
var rect = img.getBoundingClientRect();
if (box) {
var idealLeft = box.BoundingBox.Left * rect.width - box.BoundingBox.Left * containerWidth;
} else {
var idealLeft = 0;
}
idealLeft = -idealLeft;
var maxLeft = containerWidth - rect.width;
img.style.left = Math.min(0, Math.max(idealLeft, maxLeft)) + 'px';
} else {
// ....
}
Concrètement cela ressemble à quoi ?
Démo en ligne :
Vous pouvez télécharger / contribuer au code ici : https://github.com/donkeycode/images-detection