First and foremost, in order to realistically insert virtual objects into a photograph, we need to extract the lighting
environment from where the image is taken. This is done so that we can later light our objects as if they
were present at the moment the picture was taken. To capture the lighting of the scene we use a spherical
mirror because it is able to map the light information coming from every direction unto its surface.
Furthermore, in order to capture all the nuances of the lighting, we will create a High Dynamic Range radiance map. This is achieved by taking
several pictures of the same scene using different exposure times, this allows us to better capture the true intensity of the light present in the scene.
What we want to do with these images is get the 'radiance' from each pixel, where the radiance is defined like so:
Ei = exp(∑[j=1 to P](w(Zij )*(g(Zij)-ln Δtj ) / ∑[j=1 to P](w(Zij))
where E is the radiance value for pixel i, Z is the intensity of pixel i in picture j, P is the number of pictures
, w(z) is a triangular function with a slope of 1/128 and g(Z) is the function lnƒ-1 where Zij=ƒ(Ei*Δtj)
From these Low Dynamic Range images we then use the algorithm described by Debevec and Malik in their
1997 paper to
compute the 'g' response curve for the RGB colour channels and then solve the preceding equation for each pixel of our image.
The resulting radiance map has values much higher than the 8-bit 255 limit of a standard RGB colour image, so in order to display it
we normalize it using the Reinhardt operation with a 0.2 scale factor: pixel_intensity = 0.2*Ei/(1+0.2*Ei)
The left image is this normalized radiance map represented with false colours and the image on the right is a regular image with correct
exposure time, we can easily see that there is much less saturated pixels in the HDR map than in the normal image.
Now that we have our radiance map we need to transform it to a panoramic 360 degree view so that it can be processed by a render engine.
We start by selecting only the section of our radiance map that contains the sphere and we unwrap the sphere unto a rectangular plane. This is
done by using the Cartesian coordinates of each pixel on our sphere and transforming them to spherical coordinates. To do this we assume the z-axis
points up, the y-axis points right and x-axis points towards the camera, we normalize z and y to the range [-1,1] and then use the equation of a sphere
to get the x coordinate: x = sqrt(r2-y2-z2) with r=1. All those resulting coordinates are the normal vectors of every pixel
of the sphere. Now, since we want to create a panoramic view of the environment we need to know where each light vector hitting the sphere and reaching
the camera originates from. Since we chose the x-axis as pointing towards the camera, we know that every reflected light ray that reaches the camera has a vector
of [1,0,0]. To find where that light ray comes from we use 'vision vectors' of [-1,0,0] which will go from the camera to the point in the real world.
Knowing both the normal and the incident vector of every pixel it is easy to find the reflected ray simply by subtracting the projection of
the incident vector unto the normal to the incident vector twice: reflected = incident - 2*(incident • normal)*normalized normal
We then convert the Cartesian coordinate of the reflected vectors to spherical coordinate using the equations:
φ = atan2(z,√(x2+y2))
θ = atan2(y,x)
We then associate the Cartesian pixel values to their corresponding spherical coordinate and finally interpolate pixel values to
fill our new (-π/2:π/2)X(0:-π π:0) equirectangular image, with column representing θ values and the rows being the φ values.
The left of the rectangle corresponds to the front left side of the sphere, the middle corresponds to the back of the sphere and
the right side corresponds to the front right side of the sphere.
For this project, Blender 2.74 was used to render the objects unto the photographs and our equirectangular HDR radiance map
was used as light source. A plane was used to simulate the table on which the object rested. Since the table is made of white glass
the material of the plane had to be able to show shadows as well as the reflection of the objects unto the table, so a mixed shader
was used with both having a weight of 50%, the first was a Glass material with an IOR of 0.85 and the second was a white Diffuse material.
In order to make this image we first needed to render the object resting on their plane, then we render the plane by itself and finally a mask of
the objects.
Then using the mask and the objects render we create an image containing only the objects. After we use the inverse mask to create the background
without the pixels where the objects will be. Finally, we subtract the plane to the object render and apply the inverse mask to only keep the
interaction between the objects and the plane. Using these three image, we can simply add them to create the result above.