Outils pour utilisateurs

Outils du site


diy:projets:tiltshift

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
diy:projets:tiltshift [2018/05/24 09:16] – créée ycaminadediy:projets:tiltshift [2018/05/28 09:33] (Version actuelle) – [Explication] ycaminade
Ligne 7: Ligne 7:
  
 Cet effet peut aussi être appliqué à une vidéo, ce que nous ne ferons pas ici par manque de vidéo exploitable. 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 [[https://en.wikipedia.org/wiki/Bilateral_filter|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.
 +<code python>
 +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
 +
 +</code>
 +
 +Pour appliquer le masque, on le parcourt simplement pixel par pixel et on se sert du niveau de gris comme coefficient pour mélanger les couleurs sur l'original et de la version floutée.
 +
 +<code python>
 +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
 +</code>
 +
 +On se sert des deux fonctions précédentes pour obtenir l'effet désiré : D'abord, on lit l'image en entrée, puis on applique la fonction permettant de la flouter pour obtenir une seconde image.\\
 +On génère ensuite un masque simple. On créé une image noire de taille adaptée, on rajoute une bande blanche au centre, puis on applique un flou sur le résultat pour obtenir un dégradé. On peut maintenant fusionner les deux images en se servant de la fonction //blend// décrite précédemment.
 +
 +<code python>
 +if (len(sys.argv) == 2):
 +    pic = cv2.imread(sys.argv[1])
 +
 +    b_pic = blur(pic)
 +
 +    height, width, channels = pic.shape
 +    mask = np.zeros((height, width, 1), float)
 +    mask[0.4*height:0.6*height] = 255
 +    mask = cv2.blur(mask, (150, 150))
 +    shifted = blend(pic, b_pic, mask)
 +    cv2.imwrite('tshift.jpg', shifted)
 +</code>
diy/projets/tiltshift.1527153398.txt.gz · Dernière modification : 2018/05/24 09:16 de ycaminade