Outils pour utilisateurs

Outils du site


diy:projets:tiltshift

Ceci est une ancienne révision du document !


Introduction

Le Tilt Shift est un effet trompe-l’œil. Plus spécifiquement, il consiste à donner l'impression à l’œil qu'une photo prise à grande distance a en réalité été prise de très près. Cela donne ainsi l'impression de regarder une maquette plutôt qu'un véritable paysage.

Pour se faire, on va artificiellement réduire la profondeur en floutant les parties inférieures et supérieures de l'image (de manière très générale, plus un objet observé est proche, plus la profondeur de champ est faible).
Pour obtenir l'effet recherché, le flou doit être progressif. On ne doit pas avoir de coupure nette entre la zone nette et la zone floutée.
Qui plus est, du fait de son fonctionnement, le Tilt Shift ne donnera l'effet escompté que si l'image originale a été prise à grande distance. Cela n'est pas vraiment possible avec un Raspberry Pi. Il vaut mieux utiliser une caméra montée sur un drone ou installée sur un toit.

Cet effet peut aussi être appliqué à une vidéo, ce que nous ne ferons pas ici par manque de vidéo exploitable.

Explication

Le programme procède en 3 parties : on applique un flou, puis on génère un masque, et enfin on applique le masque pour fusionner l'image floutée et l'image originale.

Pour le flou, plutôt que d'appliquer un simple flou Gaussien, on va tenter de mieux répliquer l'effet produit par une caméra en appliquant d'abord un filtre bilatéral pour réduire le bruit avant d'appliquer un flou simple. On augmente aussi légèrement la valeur et la saturation de l'image.

def blur(image):
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    hue, saturation, value = cv2.split(hsv)
 
    saturation = np.array(saturation * 1.2, dtype=np.uint16)
    saturation = np.array(np.clip(saturation, 0, 255), dtype=np.uint8)
 
    value = np.array(value * 1.1, dtype=np.uint16)
    value = np.array(np.clip(value, 0, 255), dtype=np.uint8)
 
    image = cv2.cvtColor(cv2.merge((hue, saturation, value)), cv2.COLOR_HSV2BGR)
 
    image = cv2.bilateralFilter(image, 9, 150, 150)
    image = cv2.blur(image, (15, 15))
    return image

Pour appliquer le masque, on le parcourt pixel par pixel

def blend(original, blurred, mask):
    height, width, channels = original.shape
    output = np.zeros((height, width, 3), np.uint8)
    for i in range(0, height):
        for j in range(0, width):
            alpha = mask.item(i, j) / 255
            b_value = original.item(i, j, 0) * alpha + blurred.item(i, j, 0) * (1 - alpha)
            g_value = original.item(i, j, 1) * alpha + blurred.item(i, j, 1) * (1 - alpha)
            r_value = original.item(i, j, 2) * alpha + blurred.item(i, j, 2) * (1 - alpha)
            output.itemset((i, j, 0), b_value)
            output.itemset((i, j, 1), g_value)
            output.itemset((i, j, 2), r_value)
    return output
diy/projets/tiltshift.1527497759.txt.gz · Dernière modification : 2018/05/28 08:55 de ycaminade