Blog

Recadrer vos images

#Ingénierie

Illustration de Recadrer vos images

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