SoC 2008 Project OpenGL Preview

From PanoTools.org Wiki
(Difference between revisions)
Jump to: navigation, search
(Intro, started explaning image transformations)
 
(Update since GSOC is complete. Links to soon-to-be new pages added.)
 
(6 intermediate revisions by one user not shown)
Line 1: Line 1:
The OpenGL Preview project aims to create a fast previewer for Hugin, reducing the time taken to redraw the preview to real time rates. After that, the new previewer can be made more interactive than the current one.
+
[[Hugin]]'s OpenGL Preview is a fast but approximate previewer, which is more interactive than the previous one. It was James Legg's [[SoC 2008 overview|Google Summer of Code 2008]] project, mentored by Pablo d'Angelo.
  
 
==Image Transformations==
 
==Image Transformations==
The new previewer will have to approximate the transformations of the images to fit on low resolution meshes. There are two methods for this:
+
The new previewer will have to approximate the [[remapping]] of the images to fit on low resolution meshes. There are two methods it uses for this:
  
 
===Remapping Vertices===
 
===Remapping Vertices===
 +
[[Image:Blend_project_mesh.jpg|thumb|Example of using vertices of a mesh to remap an image]]
 +
 
Taking a point in the input image, we can find where the point is transformed to on the final panorama. Therefore, we can take a uniform grid over an input image, and create a mesh that shows remaps this grid into the output projection.
 
Taking a point in the input image, we can find where the point is transformed to on the final panorama. Therefore, we can take a uniform grid over an input image, and create a mesh that shows remaps this grid into the output projection.
  
This method suffers when the input image crosses certain points in the panorama. For example over the +/-180&deg boundary in a equirectangular image, there will be faces connecting one end to the other, and nothing between the edges of those faces and the actual boundary. Also the poles of an equirectangular image will cause similar problems.
+
'''Disadvantages''':
 +
*This method suffers when the input image crosses over the +/-180° boundary in projections such as [[Equirectangular Projection]], as there will be faces with vertices on either side of the seam. In this case the previewer replaces the face with two faces, one for each side.
 +
*The poles of an equirectangular image will also cause similar problems. At a pole, the image should cover the whole width of the panorama, but this is only one point in the input image. Vertices in the mesh near the pole are define a face that does not cover the whole row. Also the outer rings of disk like projections are poorly done.
 +
*The detail in the faces might not match up well with the area of the panorama. The faces are all of different sizes and some mappings may put the details in parts that can't be seen as easily as the lower resolution parts.
 +
 
 +
'''Advantages''':
 +
*The mesh resembles the output projection well, and covers up roughly the same area as the correct projection. The edges of the mesh lies along the edges of the image, so we don't need to worry about what happens outside of it (except with circular cropping). Most warped images can be displayed reasonably well using this method.
 +
 
 +
'''Implementation''':
 +
This is implemented in the VertexCoordRemapper object. It is used for most images.
  
 
===Remapping Texture Coordinates===
 
===Remapping Texture Coordinates===
 +
[[Image:Blend_project_UV.jpg|thumb|Example of using the texture coordinates of a mesh to remap an image. The internal repetitions are caused by wrapping the texture in the vertical direction; there should be hole there, but the mesh goes through regardless.]]
 
Alternatively, given a point on the final panorama, we can calculate what part of an input image belongs there. Therefore, we can take a uniform grid over the panorama, and map the input image across it.
 
Alternatively, given a point on the final panorama, we can calculate what part of an input image belongs there. Therefore, we can take a uniform grid over the panorama, and map the input image across it.
  
This does not suffer from problems at poles or borders of the panorama, but instead it breaks down at the borders of the input image.
+
'''Disadvantages''':
 +
*This mapping breaks down at the borders of the input image. The borders of the input image may cross the output mesh at any position. We clip the faces to the input image to avoid this problem.
 +
*This is inefficient for small images, as they do not cover much of the panorama. Many faces are considered outside of the input image and dropped during clipping.
 +
*The quality of the shape of curved images is a little lower than with the vertex coordinate remapping.
 +
 
 +
'''Advantages''':
 +
*There are no problems at the poles and edges of the panorama.
 +
*The output is of uniform quality throughout, as the faces always have the same density.
 +
 
 +
'''Implementation''':
 +
This is implemented in the TexCoordRemapper object. It is used for images that cross the poles in many cylinderical type projections, or the outer ring of disk like projections (e.g. fisheye) also uses this. It is also used in Alber's equal area conic projection since the +/- 180° boundary correction is difficult to implement, and the poles need it anyway.
  
 
===Distortions Comparison===
 
===Distortions Comparison===
To check that these transformation methods do not distort the image to much, I devised a test.
+
To check that these transformation methods do not distort the image too much, I devised a test.
Using nona to produce a mapping from input image coordinates to output image coordinates, and also creating a projection that goes the other way, I tried this in Blender.
+
Using [[Nona]] to produce a coordinate transformation map from input image coordinates to output image coordinates, and similarly creating a projection that goes the other way, I tried these transformations in Blender.
 +
 
 +
I projected a [[Cylindrical Projection|cylindrical]] panorama, 360° wide, and with a pixel resolution 4 times as wide as it is tall, into a [[Fisheye Projection|fisheye]] image pointing at the lower pole of the input image, 270° wide, and square.
 +
 
 +
{| border="1"
 +
|+'''Comparison of Image Transformation Approximations'''
 +
|-valign="top"
 +
|[[Image:Blender_mesh_transform_output.jpg|left|256px|Mesh transformation]]
 +
|[[Image:Blender_transform_Nona_comparison.jpg|left|256px|Transformation using Nona]]
 +
|[[Image:Blender_UV_transform_output.jpg|left|256px|Texture Coordinate transformation]]
 +
|-valign="top"
 +
|'''Vertex mapping Approximate Transformation'''
 +
 
 +
This mesh has 32 columns of faces, and 8 rows, across the input image. Since the image is 4 times as wide as it is tall, this means there are 256 faces which cover an equal amount of the input image.
 +
|'''Transformation with Nona'''
 +
 
 +
This is the remapping that the other images are approximating.
 +
|'''Texture Coordinate mapping Approximate Transformation'''
 +
 
 +
This mesh has 16 rows of faces and 16 columns, spread equally over the output panorama, so there are 256 faces which cover an equal amount of the output.
 +
 
 +
Note that for these images I have not attempted to correct the texture coordinates around the boundary of the input image.
 +
|}
 +
 
 +
Another test performed was mapping a rectilinear image to the zenith of an equirectangular image.
 +
{| border="1"
 +
|[[Image:Blender_zenith_mesh_transform.png]]
 +
 
 +
'''Vertex mapping Approximate Transformation'''
 +
 
 +
This is the transformation performed by arranging vertices that cover a uniform grid along the input image. The mesh was 32 faces wide and 16 faces tall, and covered an input image that was 4:3. I removed a row of faces that went right across the image, connecting the left edge to the right edge. This was there since the left and right edge represent the same line through the input image, and the mapping ignores the discontinuity across that edge. If I use this method, I will have to draw the faces of that row twice, once for each side, using some extra vertices somewhere off the sides of the output, so that the mapping is continuous and the corners are not missing.
 +
 
 +
|-
 +
|[[Image:Blender_zenith_transform_nona_output.png]]
 +
 
 +
'''Transformation with Nona'''
 +
 
 +
This is the mapping the other images are approximating.
 +
 
 +
|-
 +
|[[Image:Blender_zenith_tex_coord_transform.png]]
 +
 
 +
'''Texture Coordinate mapping Approximate Transformation'''
 +
 
 +
This is the transformation performed by finding the points on the input image that are at the points on a grid over the output image. The grid was 64 faces wide and 8 tall. Two of the edges are bad because I couldn't get the negative coordinates (they were clamped to 0), the other two are reasonable because the grid points mapped to the correct places, even though some of them were outside of the input image. If I use this method, I should be able to get the negative coordinates easily and therefore the poles will work without much effort.
 +
 
 +
|}
 +
 
 +
==Modules==
 +
See main article: [[Hugin's OpenGL preview system overview]]
 +
 
 +
==Building and Usage==
 +
The OpenGL preview is not in the main Hugin branch yet. If you wish to experiment, and don't mind compiling it yourself, you can check out the latest version using svn with:
 +
<source lang="bash">
 +
svn co https://hugin.svn.sourceforge.net/svnroot/hugin/hugin/branches/gsoc2008_opengl_preview hugin
 +
</source>
 +
For help compiling, you might want to read [[Hugin Compiling OSX]] or [[Hugin Compiling Windows]] depending on you operating system. The preview adds extra dependencies, firstly you'll need [http://glew.sourceforge.net glew], and also the wxGLCanvas object in the [http://www.wxwidgets.org wxWidgets] library (which is not compiled by default on Windows).
 +
 
 +
See [[Hugin Fast Preview window]] for usage instructions.
 +
 
 +
[[Category:Community:Project]]

Latest revision as of 18:46, 21 August 2008

Hugin's OpenGL Preview is a fast but approximate previewer, which is more interactive than the previous one. It was James Legg's Google Summer of Code 2008 project, mentored by Pablo d'Angelo.

Contents

[edit] Image Transformations

The new previewer will have to approximate the remapping of the images to fit on low resolution meshes. There are two methods it uses for this:

[edit] Remapping Vertices

Example of using vertices of a mesh to remap an image

Taking a point in the input image, we can find where the point is transformed to on the final panorama. Therefore, we can take a uniform grid over an input image, and create a mesh that shows remaps this grid into the output projection.

Disadvantages:

  • This method suffers when the input image crosses over the +/-180° boundary in projections such as Equirectangular Projection, as there will be faces with vertices on either side of the seam. In this case the previewer replaces the face with two faces, one for each side.
  • The poles of an equirectangular image will also cause similar problems. At a pole, the image should cover the whole width of the panorama, but this is only one point in the input image. Vertices in the mesh near the pole are define a face that does not cover the whole row. Also the outer rings of disk like projections are poorly done.
  • The detail in the faces might not match up well with the area of the panorama. The faces are all of different sizes and some mappings may put the details in parts that can't be seen as easily as the lower resolution parts.

Advantages:

  • The mesh resembles the output projection well, and covers up roughly the same area as the correct projection. The edges of the mesh lies along the edges of the image, so we don't need to worry about what happens outside of it (except with circular cropping). Most warped images can be displayed reasonably well using this method.

Implementation: This is implemented in the VertexCoordRemapper object. It is used for most images.

[edit] Remapping Texture Coordinates

Example of using the texture coordinates of a mesh to remap an image. The internal repetitions are caused by wrapping the texture in the vertical direction; there should be hole there, but the mesh goes through regardless.

Alternatively, given a point on the final panorama, we can calculate what part of an input image belongs there. Therefore, we can take a uniform grid over the panorama, and map the input image across it.

Disadvantages:

  • This mapping breaks down at the borders of the input image. The borders of the input image may cross the output mesh at any position. We clip the faces to the input image to avoid this problem.
  • This is inefficient for small images, as they do not cover much of the panorama. Many faces are considered outside of the input image and dropped during clipping.
  • The quality of the shape of curved images is a little lower than with the vertex coordinate remapping.

Advantages:

  • There are no problems at the poles and edges of the panorama.
  • The output is of uniform quality throughout, as the faces always have the same density.

Implementation: This is implemented in the TexCoordRemapper object. It is used for images that cross the poles in many cylinderical type projections, or the outer ring of disk like projections (e.g. fisheye) also uses this. It is also used in Alber's equal area conic projection since the +/- 180° boundary correction is difficult to implement, and the poles need it anyway.

[edit] Distortions Comparison

To check that these transformation methods do not distort the image too much, I devised a test. Using Nona to produce a coordinate transformation map from input image coordinates to output image coordinates, and similarly creating a projection that goes the other way, I tried these transformations in Blender.

I projected a cylindrical panorama, 360° wide, and with a pixel resolution 4 times as wide as it is tall, into a fisheye image pointing at the lower pole of the input image, 270° wide, and square.

Comparison of Image Transformation Approximations
Mesh transformation
Transformation using Nona
Texture Coordinate transformation
Vertex mapping Approximate Transformation

This mesh has 32 columns of faces, and 8 rows, across the input image. Since the image is 4 times as wide as it is tall, this means there are 256 faces which cover an equal amount of the input image.

Transformation with Nona

This is the remapping that the other images are approximating.

Texture Coordinate mapping Approximate Transformation

This mesh has 16 rows of faces and 16 columns, spread equally over the output panorama, so there are 256 faces which cover an equal amount of the output.

Note that for these images I have not attempted to correct the texture coordinates around the boundary of the input image.

Another test performed was mapping a rectilinear image to the zenith of an equirectangular image.

Blender zenith mesh transform.png

Vertex mapping Approximate Transformation

This is the transformation performed by arranging vertices that cover a uniform grid along the input image. The mesh was 32 faces wide and 16 faces tall, and covered an input image that was 4:3. I removed a row of faces that went right across the image, connecting the left edge to the right edge. This was there since the left and right edge represent the same line through the input image, and the mapping ignores the discontinuity across that edge. If I use this method, I will have to draw the faces of that row twice, once for each side, using some extra vertices somewhere off the sides of the output, so that the mapping is continuous and the corners are not missing.

Blender zenith transform nona output.png

Transformation with Nona

This is the mapping the other images are approximating.

Blender zenith tex coord transform.png

Texture Coordinate mapping Approximate Transformation

This is the transformation performed by finding the points on the input image that are at the points on a grid over the output image. The grid was 64 faces wide and 8 tall. Two of the edges are bad because I couldn't get the negative coordinates (they were clamped to 0), the other two are reasonable because the grid points mapped to the correct places, even though some of them were outside of the input image. If I use this method, I should be able to get the negative coordinates easily and therefore the poles will work without much effort.

[edit] Modules

See main article: Hugin's OpenGL preview system overview

[edit] Building and Usage

The OpenGL preview is not in the main Hugin branch yet. If you wish to experiment, and don't mind compiling it yourself, you can check out the latest version using svn with: <source lang="bash"> svn co https://hugin.svn.sourceforge.net/svnroot/hugin/hugin/branches/gsoc2008_opengl_preview hugin </source> For help compiling, you might want to read Hugin Compiling OSX or Hugin Compiling Windows depending on you operating system. The preview adds extra dependencies, firstly you'll need glew, and also the wxGLCanvas object in the wxWidgets library (which is not compiled by default on Windows).

See Hugin Fast Preview window for usage instructions.

Personal tools
Namespaces

Variants
Actions
Navigation
tools
Tools