1-Objectifs du projet 2-Description des étapes de l'algorithme 3-Utilisation de logiciel de rendu (Blender) 4-Améliorations
1-Objectifs du projet
Résultat d'un rendu final |
Pour plus de détails, voyez l'énoncé complet ICI !.
2-Description des étapes de l'algorithme
Étape 1 - Capturer la carte de radiance en haute plage dynamique
Étape 1 - Capturer la carte de radiance en haute plage dynamique
Tout d'abord, il faut capturer la carte de radiance en haute plage dynamique de la scène désirée. Pour ce faire, à l'aide d'une caméra standard (dont on peut modifier les temps d'exposition), il faut prendre plusieurs photos de la même scène, et ce pour différentes expositions. Plus la plage d'exposition sera grande et plus le nombre de photos exposées pendant des temps différents sera grand, meilleur le résultat sera. Pour de meilleurs résultats, il faut que les temps d'expositions maximal et minimal soit environ 4 fois plus grand que le taux d'exposition moyen (sur lequel on effectuera le rendu de la scène).
Exposition de 1/8s | Exposition de 8s | Image sans balle (vide) |
Afin de capter tous les rayons lumineux de la scène, on utilise un sphère métallique que l'on inclut dans la scène et qui fera en sorte de rediriger les rayons lumineux sur 360 degrés vers l'objectif de la caméra. Une fois les scènes prisent en photos, il suffit de prendre cette même scène, sans la boule métallique et il ne restera plus qu'à faire le redimensionnement des photos pour ne conserver que la balle métallique. Ces photos des différentes balles permettent donc de trouver l'image HDR et la scène vide servira d'arrière-plan pour notre scène.
Exposition de 1/8s | Exposition de 1/2s | Exposition de 1s | Exposition de 2s | Exposition de 4s | Exposition de 8s |
Pour couper les images, un script MATLAB à été conçu :
drawRect.m
Celui-ci permet de sélectionner un rectangle dans une image et de faire une image avec cette sélection. Par la suite, si toutes les images ne sont pas de la même taille, un autre
script à été conçu :
cutAll.m
qui permet de sélectionner une image et d'appliquer un redimensionnement pour toutes les images du même dossier (y compris l'image sélectionnée). Il faut dire que n'importe quel logiciel
de traitement d'image, tel que le fameux PAINT de Windows, aurait pu être utilisé.
Étape 2 - Construction de la carte de radiance (image HDR)
Pour reconstruire l'image HDR, l'algorithme présenté dans le document de Paul Debevec et Jitendra Malik a été utilisé.
D'abord, à l'aide de la fonction imfinfo.m
et exifread.m
il est aisé de déterminer le temps d'exposition (t) pour chacune des photos qui sera variable indispensable au
calcul de la carte. Puis, il nous faut déterminer Z(i,j) qui est la valeur de chacun des pixels de l'emplacement (i) dans l'image (j). Cette valeur servira à calculer g(z) et lE(i) soit l'exposition
soit l'exposition du pixel de valeur (z) et la radiance des pixels à l'emplacement (i). Ces valeurs seront déterminées à l'aide de la fonction fournie par Debevec :
[g, lE] = gsolve(Z,B,l,w)
*Ne pas oubliez que ces valeurs sont souvent logarithmiques.
Avec Z(i,j) de déterminés, B(j) qui correspond au logarithme du temps d'exposition de l'image (j), le lambda (l) qui est un facteur qui détermine la quantité de paufinage de l'image, il ne reste plus
qu'à déterminer (w) qui est la fonction de pondération de poids des pixels. Celle-ci permet de mettre l'emphase sur le paufinage de la courbe et de faire tendre les termes vers le milieu de la
courbe g(z); on s'éloigne donc des cas de saturation, car les pixels de sous-exposés auront un faible poids et les pixels surexposés seront ignorés (valeur infini)). La fonction suivante implémente la contribution des pixels :
weight = double(128-abs([z]-128));
où z correspond à la plage de valeur que peut prendre le pixel. Il faut également moyenner le tout.
Finalement, il faut choisir judicieusement le facteur lambda afin d'avoir un bon rendu d'image. On peut savoir si son choix est bon en évaluant la courbe g(z). Celle-ci devrait être le plus lisse possible.
Voici quelques résultats avec différentes valeurs de lambda. À noter que sa valeur est arbitraire et dépend beaucoup de la scène et surtout de la lumière. Le soleil est agréable sauf pour nos algorithmes !
Image HDR (lambda = 1) | Image HDR (lambda = 100) | Image HDR résultante |
Fonction g(z) (lambda = 1) | Fonction g(z) (lambda = 100) | Fonction g(z) (lambda = 1000) |
imgHDR = computeHDR(images, g, ln_t, w)
Cette fonction permet de passer au travers tous les pixels de de chacune des images pour y déterminer sont poids et sa contribution dans l'image HDR. Il faut prendre soin de bien calculer «g» pour chacun des canaux
de couleurs de l'image individuellement et donc de faire le calcul des poids des pixels (création de l'image HDR) pour les 3 canaux et les fusionner par la suite. Ceci donne de meilleurs résultats. Ne pas oublier de gérer
les cas de «sur et sous» saturation (soit des valeurs Nan ou Inf dans MATLAB). De plus il est nécessaire de faire la résolution de g(z) que pour un échantillon de pixels sinon la résolution va être très longue et risque
d'entraîner un manque de mémoire de l'ordinateur. Pour ce faire dans le script d'exécution, un rééchantillonnement de l'image à été fait selon un nombre de lignes et de colonnes. On réduit l'image en quelques sorte.
Étape 3 - Transformation panoramique
Avec l'image HDR de la sphère métallique, il est possible d'intégrer celle-ci dans un projet de modélisation afin de recréer la lumière de la scène. Cependant, il faut utiliser une des transformations suivantes :
Type de projection de lumière |
latlon = ball2LatLong(imageHDR)
L'algorithme va comme suit; on calcule d'abord les points de la sphère en coordonnées cartésienne (x,y) puis on détermine la valeur de notre valeur en «z» à l'aide de la formule x2+y2+z2 = r. On se
retrouve donc avec notre système d'équation cartésien en 3d (x,y,z). En déterminant pour chaque points, une normale N(x,y,z) et un vecteur de direction d'orientation V = (-1,0,0) qui est donc constant, on peut calculé les vecteurs de
réflexion à l'aide de l'équation suivante :
R = V - 2 .* dot(V,N) .* N
On s'assure ainsi de prendre qu'un rayon de 1 dans notre image et donc on élimine les pixels non essentiel à la création de l'image dans la domaine équirectangle tel que les coins qui sont en effet le fond de la scène. Puis il faut
déterminer les phis(φ) = atan(y/z) et theta(θ) = acos(y/x). On à donc tous les vecteurs pour construire l'image. Il faut par la suite utiliser la fonction suivante pour créer une image vide, de dimension 2X plus large qui
permettera d'accueillir les pixels de l'image de la sphère métallique dans le format cartésien :
[phis, thetas] = meshgrid([pi:pi/360:2*pi -pi/2:pi/360:pi/2], 0:pi/360:pi)
Finalement, on fait l'interpolation d'un domaine à l'autre et on écrit l'image HDR équirectangle à l'aide des fonctions suivantes :
scatteredInterpolant((φ),(θ),valeur du pixel)
latlon = hdrwrite(latlon, 'latlon.hdr')
3-Utilisation de logiciel de rendu (Blender)
Étape 1 - Modélisation de la scène et rendu d'images (ajout de plans et d'objets)
Étape 1 - Modélisation de la scène et rendu d'images (ajout de plans et d'objets)
Pour modéliser la scène à l'aide de Blender, il faut d'abord y insérer l'image de la scène (arrière-plan ou encore «background»). Et y ajouter une vue (caméra de sorte que celle-ci est orientée avec l'axe +z en haut et l'axe +x vers l'avant afin que la luminosité à base d'image soit correcte puisque nous utilisons cette technique pour effectuer/recréer l'éclairage de la scène.
Image d'arrière-plan |
Image du plan |
Image du plan (avec objets) |
Image du masque (objets VS scène) |
Étape 2 - Composition des images
La finalisation de l'image rendue finale est composée à partir des différentes images obtenues à l'étape précédente, soit, une image du plan, une image du plan avec les objets et le masque des objets. La technique employée se nomme
rendu différentiel qui peut être facilement résolue à l'aide de l'équation suivante :
composite = M.*R + (1-M).*I + (1-M).*(R-E).*c
où M est l'image du masque, R est le rendu de l'image AVEC les objets, E est le rendu d'image SANS les objets et I est l'image d'arrière-plan. Pour ce qui est du facteur «c» celui-ci détermine une certaine quantité d'effets d'illumination
provenant des objets et du plan. Si celui-ci est trop élevé, des effets indésirables apparaîtront au final. Ce paramètre doit être ajusté selon la prise de photo comme on peut le constater avec les photos suivantes :
Image rendu finale | Surplus d'effet d'illumination |
4-Améliorations
1- Il faut s'assurer de bien positionner la caméra dans le logiciel Blender afin de bien modéliser l'illumination de la scène. 2- L'utilisation d'une meilleure caméra permettant des temps d'exposition beaucoup plus courts et un peu plus long aurait été préférable. 3- Avoir une boule propre et exempt d'égratignures donnerait de meilleurs résultats car c'est la source de toute notre illumination. 4- Éviter d'avoir comme source de lumière, un soleil «tappant» directement sur la sphère métallique. 5- Utiliser un autre type de transformation pour l'image de l'illumination 6- Prendre 2 photos à 180 degrés de la sphère pour «effacer» la possible réflexion du photographe 7- Utiliser un reproduction tonale locale pour constituer l'image de haute plage dynamique 8- ETC :P !