Hugin trunk 0.1
Loading...
Searching...
No Matches
TexCoordRemapper.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
23#include "panoinc_WX.h"
24#include "panoinc.h"
25#include "TexCoordRemapper.h"
27#include "ViewState.h"
28
29// higher values make the mesh more detailed, but slower and using more memory:
30// Value is in faces per pixel in each direction, so it should be positive and
31// less than 1. Faces will be around this size, approximately square.
32const double mesh_frequency = 0.07;
33
36 VisualizationState *visualization_state)
37 : MeshRemapper(m_pano, image, visualization_state)
38{
39
40}
41
43{
44 // work what area we should cover in what detail.
45 SetSize();
46 // we want to make a remapped mesh, get the transformation we need:
47// HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
49// DEBUG_INFO("updating mesh for image " << image_number
50// << ", using faces spaced about " << scale << " units apart.\n");
51 // fill the map with transformed points.
52 for (unsigned int x = 0; x < divisions_x; x++)
53 {
54 for (unsigned int y = 0; y < divisions_y; y++)
55 {
57 map[x][y].y,
58 (double) x * face_width + start_x,
59 (double) y * face_height + start_y);
60 // texture coordinates on the image range from 0 to 1.
61 map[x][y].x /= width;
62 map[x][y].y /= height;
63 }
64 }
65 face_index = 0;
66 SetCrop();
67}
68
70{
71 result->tex_c = texture_coords;
72 result->vertex_c = vertex_coords;
73 // return any remaining results of a previous clipping operation.
74 if (GiveClipFaceResult(result)) return true;
75 // try to find a face that is at least partly covered by the image.
76 while (true)
77 {
78 if (face_index == number_of_faces) return false;
79 unsigned int x_f = face_index % (divisions_x - 1),
80 y_f = face_index / (divisions_x - 1);
81 bool all_left = true, all_right = true,
82 all_above = true, all_below = true;
83 for (unsigned short int x = 0; x < 2; x++)
84 {
85 for (unsigned short int y = 0; y < 2; y++)
86 {
87 unsigned int xt = x_f + x, yt = y_f + y;
88 if (map[xt][yt].x > crop_x1) all_left = false;
89 if (map[xt][yt].x < crop_x2) all_right = false;
90 if (map[xt][yt].y > crop_y1) all_above = false;
91 if (map[xt][yt].y < crop_y2) all_below = false;
92 }
93 }
94 /* check if this quad shows any of the input image.
95 * We could possibly drop some more faces, but this is a pretty good
96 * optimisation by itself. Proper clipping will alert us otherwise.
97 */
98 if (!(all_left || all_right || all_above || all_below)) break;
99 face_index++;
100 }
101 // now set the coordinates.
102 unsigned int x_f = face_index % (divisions_x - 1),
103 y_f = face_index / (divisions_x - 1);
104 for (unsigned short int x = 0; x < 2; x++)
105 {
106 for (unsigned short int y = 0; y < 2; y++)
107 {
108 unsigned int xt = x_f + x, yt = y_f + y;
109 result->tex_c[x][y][0] = map[xt][yt].x;
110 result->tex_c[x][y][1] = map[xt][yt].y;
111 result->vertex_c[x][y][0] = (double) xt * face_width + start_x;
112 result->vertex_c[x][y][1] = (double) yt * face_height + start_y;
113 }
114 }
115 face_index++;
116 /* Since we only crop to convex regions, having all four points inside the
117 * wanted region implies we don't need to do any clipping. It should be
118 * faster to test for this and skip full clipping in that case, as the vast
119 * majority of faces will not need any clipping or fail the test above.
120 */
121// HuginBase::SrcPanoImage *src_img = visualization_state->GetSrcImage(image_number);
122 if ( image->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width),
123 int(result->tex_c[0][0][1] * height)))
124 && image->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width),
125 int(result->tex_c[0][1][1] * height)))
126 && image->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width),
127 int(result->tex_c[1][0][1] * height)))
128 && image->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width),
129 int(result->tex_c[1][1][1] * height))))
130 {
131 // all inside, doesn't need clipping.
132 /* FIXME Alber's equal area conic projection needs to be clipped to the
133 * sides space in the output that maps to the panorama...
134 */
135 return true;
136 }
137 /* We have to clip the face to the source image. This may produce many faces
138 * or none, so we store a list and pop elements off it until the list is
139 * empty, or try from the top in the case we get none.
140 */
141 ClipFace(result);
142 if (GiveClipFaceResult(result))
143 {
144 return true;
145 } else {
146 return GetNextFaceCoordinates(result);
147 }
148}
149
151{
152// const HuginBase::SrcPanoImage *src = visualization_state->GetSrcImage(image_number);
153 width = (double) image->getSize().width();
154 height = (double) image->getSize().height();
155 // set the bounding rectangle.
156 // FIXME
157 // 1. If there is an efficient way to find a good bounding rectangle, use it
158 // (I had a look at ComputeImageROI but seemed a bit brute force)
159 // 2. With zooming, we could clip the stuff off the edge of the screen.
160 // For now we stick with everything that is visible.
161 vigra::Rect2D visible_area = visualization_state->GetVisibleArea();
162 start_x = (double) visible_area.left() - 0.5;
163 start_y = (double) visible_area.top() - 0.5;
164 end_x = (double) visible_area.right() - 0.5;
165 end_y = (double) visible_area.bottom() - 0.5;
168 // use the scale to determine edge lengths in pixels for subdivision
170 // round the number of divisions we need to get a whole number of faces
171 divisions_x = (int) ((end_x - start_x) * scale + 0.5);
172 if (divisions_x < 2) divisions_x = 2;
173 divisions_y = (int) ((end_y - start_y) * scale + 0.5);
174 if (divisions_y < 2) divisions_y = 2;
175 // the face height and width uses the rounded number, we don't want gaps at
176 // the edges of the panorama. Therefore scale is approximate now.
177 /* FIXME there is a line on the bottom edge when an image covers the top
178 * pole in equirectangular sometimes. These will get clipped, but it means
179 * extra stuff is being done along a wrong edge.
180 */
181 // the minus 1 is because we need the last division to cover the far edge.
182 // note we have divisions_x - 1 faces to cover the divisions_x vertices.
185 // work out the number of faces.
187 // resize our data stucture for holding the vertex locations.
188 map.resize(divisions_x);
189 for (unsigned int column = 0; column < divisions_x; column++)
190 {
191 map[column].resize(divisions_y);
192 }
193}
194
const double mesh_frequency
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano->image transformation
Model for a panorama.
Definition Panorama.h:153
All variables of a source image.
bool isInside(vigra::Point2D p, bool ignoreMasks=false) const
check if a coordinate is inside the source image
A class for exchanging pointers to coordinates.
double(* vertex_c)[2][2]
The coordinate in the panorama, in its pixel space.
double(* tex_c)[2][2]
The coordinate in the source image ranging from 0 to 1.
An abstract base class for objects that calculate an approximate remap specified by quadrilatrials.
HuginBase::SrcPanoImage * image
void ClipFace(Coords *face)
Crop a face to the source image, return true if there is anything left.
HuginBase::PTools::Transform transform
A transform to use to remap the images.
bool GiveClipFaceResult(Coords *result)
Get a face that was produced by ClipFace.
double height
The sizes of the input images in pixels.
float scale
The number number of units between vertex coorinates that gives a pixel in the display.
VisualizationState * visualization_state
void SetCrop()
Fill the crop values of the MeshRemapper from the source image.
TexCoordRemapper(HuginBase::Panorama *m_pano, HuginBase::SrcPanoImage *image, VisualizationState *visualization_state)
std::vector< std::vector< hugin_utils::FDiff2D > > map
double texture_coords[2][2][2]
virtual void UpdateAndResetIndex()
unsigned int divisions_x
unsigned int face_index
unsigned int divisions_y
unsigned int number_of_faces
virtual bool GetNextFaceCoordinates(Coords *result)
Get the texture and vertex coordinates for the next face.
double vertex_coords[2][2][2]
vigra::Rect2D GetVisibleArea()
Definition ViewState.h:222
virtual HuginBase::PanoramaOptions * GetOptions()
include file for the hugin project
include file for the hugin project
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41