1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18 #sourcefile  vp_motionmodel.h
19 #category    warp
20 #description general motion model for tranlation/affine/projective
21 #title       motion-model
22 #parentlink  hindex.html
23 *
24 * Copyright 1998 Sarnoff Corporation
25 * All Rights Reserved
26 *
27 * Modification History
28 *      Date: 02/13/98
29 *      Author: supuns
30 *      Shop Order: 15491 001
31 *              @(#) $Id: vp_motionmodel.h,v 1.4 2011/06/17 14:04:33 mbansal Exp $
32 */
33 
34 #ifndef VP_MOTIONMODEL_H
35 #define VP_MOTIONMODEL_H
36 #include <stdio.h>
37 
38 #define         FALSE           0
39 #define         TRUE            1
40 
41 #if 0 /* Moved mottomat.c and mattomot_d.c from vpmotion.h to vpcompat.h
42      in order to remove otherwise unnecessary dependency of vpmotion,
43      vpwarp, and newvpio on vpmath */
44 #ifndef VPMATH_H
45 #include "vpmath.h"
46 #endif
47 #endif
48 
49 #if 0
50 #ifndef VP_WARP_H
51 #include "vp_warp.h"
52 #endif
53 #endif
54 /*
55 
56 #htmlstart
57 # ===================================================================
58 #h 1 Introduction
59 
60   This defines a motion model that can describe translation,
61   affine, and projective projective 3d and 3d view transforms.
62 
63   The main structure VP_MOTION contains a 16 parameter array (That
64   can be considered as elements of a 4x4 matrix) and a type field
65   which can be one of VP_MOTION_NONE,VP_MOTION_TRANSLATION,
66   VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE,VP_MOTION_PROJ_3D or
67   VP_MOTION_VIEW_3D. (These are defined using enums with gaps of 10
68   so that subsets of these motions that are still consistant can be
69   added in between. Motion models that are inconsistant with this set
70   should be added at the end so the routines can hadle them
71   independently.
72 
73   The transformation VP_MOTION_NONE,VP_MOTION_TRANSLATION,
74   VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE, VP_MOTION_PROJ_3D and
75   VP_MOTION_SEMI_PROJ_3D would map a point P={x,y,z,w} to a new point
76   P'={x',y',z',w'} using a motion model M such that P'= M.par * P.
77   Where M.par is thought of as  elements of a 4x4 matrix ordered row
78   by row. The interpretation of all models except VP_MOTION_SEMI_PROJ_3D
79   is taken to be mapping of a 3d point P"={x",y",z"} which is obtained
80   from the normalization {x'/w',y'/w',z'/w'}. In the VP_MOTION_SEMI_PROJ_3D
81   the mapping to a point P"={x",y",z"} is obtained from the normalization
82   {x'/w',y'/w',z'}. All these motion models have the property that they
83   can be inverted using 4x4 matrices. Except for the VP_MOTION_SEMI_PROJ_3D all
84   other types can also be cascaded using 4x4 matrices.
85 
86   Specific macros and functions have been provided to handle 2d instances
87   of these functions. As the parameter interpretations can change when adding
88   new motion models it is HIGHLY RECOMMENDED that you use the macros MXX,MXY..
89   ect. to interpret each motion component.
90 #pre
91 */
92 
93 /*
94 #endpre
95 # ===================================================================
96 #h 1 Typedef and Struct Declarations
97 #pre
98 */
99 
100 #define VP_MAX_MOTION_PAR 16
101 
102 typedef double VP_PAR;
103 typedef VP_PAR VP_TRS[VP_MAX_MOTION_PAR];
104 
105 /* Do not add any motion models before VP_MOTION_PROJECTIVE */
106 /* The order is assumed in vp functions */
107 enum VP_MOTION_MODEL {
108   VP_MOTION_NONE=0,
109   VP_MOTION_TRANSLATION=10,
110   VP_MOTION_SCALE=11,
111   VP_MOTION_ROTATE=12,
112   VP_MOTION_X_SHEAR=13,
113   VP_MOTION_Y_SHEAR=14,
114   VP_MOTION_SIMILARITY=15,
115   VP_MOTION_AFFINE=20,
116   VP_MOTION_PROJECTIVE=30,
117   VP_MOTION_PROJ_3D=40,
118   VP_MOTION_SEMI_PROJ_3D=80,
119   VP_SIMILARITY=100,
120   VP_VFE_AFFINE=120
121 };
122 
123 #define VP_REFID -1   /* Default ID used for reference frame */
124 
125 typedef struct {
126   VP_TRS par;            /* Contains the motion paramerers.
127                 For the standard motion types this is
128                 represented as 16 number that refer
129                 to a 4x4 matrix */
130   enum VP_MOTION_MODEL type;
131   int refid;            /* Reference frame ( takes a point in refid frame
132                and moves it by the par to get a point in insid
133                frame ) */
134   int insid;            /* Inspection frame */
135 } VP_MOTION;
136 
137 //typedef VP_LIST VP_MOTION_LIST;
138 /*
139 #endpre
140 # ===================================================================
141 #h 1 Constant Declarations
142 */
143 
144 /* Macros related to the 4x4 matrix parameters */
145 #define MXX(m) (m).par[0]
146 #define MXY(m) (m).par[1]
147 #define MXZ(m) (m).par[2]
148 #define MXW(m) (m).par[3]
149 #define MYX(m) (m).par[4]
150 #define MYY(m) (m).par[5]
151 #define MYZ(m) (m).par[6]
152 #define MYW(m) (m).par[7]
153 #define MZX(m) (m).par[8]
154 #define MZY(m) (m).par[9]
155 #define MZZ(m) (m).par[10]
156 #define MZW(m) (m).par[11]
157 #define MWX(m) (m).par[12]
158 #define MWY(m) (m).par[13]
159 #define MWZ(m) (m).par[14]
160 #define MWW(m) (m).par[15]
161 
162 /* The do {...} while (0) technique creates a statement that can be used legally
163    in an if-else statement.  See "Swallowing the semicolon",
164    http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC23 */
165 /* Initialize the Motion to be Identity */
166 #define VP_MOTION_ID(m) do {\
167   MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \
168   MXY(m)=MXZ(m)=MXW(m)=(VP_PAR)0.0; \
169   MYX(m)=MYZ(m)=MYW(m)=(VP_PAR)0.0; \
170   MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \
171   MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \
172 (m).type = VP_MOTION_TRANSLATION; } while (0)
173 
174 /* Initialize without altering the translation components */
175 #define VP_KEEP_TRANSLATION_3D(m) do {\
176   MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \
177   MXY(m)=MXZ(m)=(VP_PAR)0.0; \
178   MYX(m)=MYZ(m)=(VP_PAR)0.0; \
179   MZX(m)=MZY(m)=(VP_PAR)0.0; \
180   MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \
181   (m).type = VP_MOTION_PROJ_3D; } while (0)
182 
183 /* Initialize without altering the 2d translation components */
184 #define VP_KEEP_TRANSLATION_2D(m) do {\
185   VP_KEEP_TRANSLATION_3D(m); MZW(m)=(VP_PAR)0.0; (m).type= VP_MOTION_TRANSLATION;} while (0)
186 
187 /* Initialize without altering the affine & translation components */
188 #define VP_KEEP_AFFINE_3D(m) do {\
189   MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; MWW(m)=(VP_PAR)1.0; \
190   (m).type = VP_MOTION_PROJ_3D; } while (0)
191 
192 /* Initialize without altering the 2d affine & translation components */
193 #define VP_KEEP_AFFINE_2D(m) do {\
194   VP_KEEP_AFFINE_3D(m); \
195   MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \
196   MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \
197   (m).type = VP_MOTION_AFFINE; } while (0)
198 
199 /* Initialize without altering the 2d projective parameters */
200 #define VP_KEEP_PROJECTIVE_2D(m) do {\
201   MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \
202   MZX(m)=MZY(m)=MZW(m)=MWZ(m)=(VP_PAR)0.0; \
203   (m).type = VP_MOTION_PROJECTIVE; } while (0)
204 
205 /* Warp a 2d point (assuming the z component is zero) */
206 #define VP_WARP_POINT_2D(inx,iny,m,outx,outy) do {\
207   VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWW(m); \
208   outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXW(m))/vpTmpWarpPnt___; \
209   outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYW(m))/vpTmpWarpPnt___; } while (0)
210 
211 /* Warp a 3d point */
212 #define VP_WARP_POINT_3D(inx,iny,inz,m,outx,outy,outz) do {\
213   VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWZ(m)*((VP_PAR)inz)+MWW(m); \
214   outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXZ(m)*((VP_PAR)inz)+MXW(m))/vpTmpWarpPnt___; \
215   outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYZ(m)*((VP_PAR)inz)+MYW(m))/vpTmpWarpPnt___; \
216   outz = MZX(m)*((VP_PAR)inx)+MZY(m)*((VP_PAR)iny)+MZZ(m)*((VP_PAR)inz)+MZW(m); \
217   if ((m).type==VP_MOTION_PROJ_3D) outz/=vpTmpWarpPnt___; } while (0)
218 
219 /* Projections of each component */
220 #define VP_PROJW_3D(m,x,y,z,f)   ( MWX(m)*(x)+MWY(m)*(y)+MWZ(m)*(z)+MWW(m) )
221 #define VP_PROJX_3D(m,x,y,z,f,w) ((MXX(m)*(x)+MXY(m)*(y)+MXZ(m)*(z)+MXW(m))/(w))
222 #define VP_PROJY_3D(m,x,y,z,f,w) ((MYX(m)*(x)+MYY(m)*(y)+MYZ(m)*(z)+MYW(m))/(w))
223 #define VP_PROJZ_3D(m,x,y,z,f,w) ((MZX(m)*(x)+MZY(m)*(y)+MZZ(m)*(z)+MZW(m))/(w))
224 
225 /* Scale Down a matrix by Sfactor */
226 #define VP_SCALEDOWN(m,Sfactor) do { \
227   MXW(m) /= (VP_PAR)Sfactor; MWX(m) *= (VP_PAR)Sfactor; \
228   MYW(m) /= (VP_PAR)Sfactor; MWY(m) *= (VP_PAR)Sfactor; \
229   MZW(m) /= (VP_PAR)Sfactor; MWZ(m) *= (VP_PAR)Sfactor; } while (0)
230 
231 /* Scale Up a matrix by Sfactor */
232 #define VP_SCALEUP(m,Sfactor) do { \
233   MXW(m) *= (VP_PAR)Sfactor; MWX(m) /= (VP_PAR)Sfactor; \
234   MYW(m) *= (VP_PAR)Sfactor; MWY(m) /= (VP_PAR)Sfactor; \
235   MZW(m) *= (VP_PAR)Sfactor; MWZ(m) /= (VP_PAR)Sfactor; } while (0)
236 
237 /* Normalize the transformation matrix so that MWW is 1 */
238 #define VP_NORMALIZE(m) if (MWW(m)!=(VP_PAR)0.0) do { \
239   MXX(m)/=MWW(m); MXY(m)/=MWW(m); MXZ(m)/=MWW(m); MXW(m)/= MWW(m); \
240   MYX(m)/=MWW(m); MYY(m)/=MWW(m); MYZ(m)/=MWW(m); MYW(m)/= MWW(m); \
241   MZX(m)/=MWW(m); MZY(m)/=MWW(m); MZZ(m)/=MWW(m); MZW(m)/= MWW(m); \
242   MWX(m)/=MWW(m); MWY(m)/=MWW(m); MWZ(m)/=MWW(m); MWW(m) = (VP_PAR)1.0; } while (0)
243 
244 #define VP_PRINT_TRANS(msg,b) do { \
245   fprintf(stderr, \
246       "%s\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", \
247       msg, \
248       MXX(b),MXY(b),MXZ(b),MXW(b),  \
249       MYX(b),MYY(b),MYZ(b),MYW(b),  \
250       MZX(b),MZY(b),MZZ(b),MZW(b),  \
251       MWX(b),MWY(b),MWZ(b),MWW(b)); \
252 } while (0)
253 
254 /* w' projection given a point x,y,0,f */
255 #define VP_PROJZ(m,x,y,f) ( \
256     MWX(m)*((VP_PAR)x)+MWY(m)*((VP_PAR)y)+MWW(m)*((VP_PAR)f))
257 
258 /* X Projection given a point x,y,0,f and w' */
259 #define VP_PROJX(m,x,y,w,f) (\
260    (MXX(m)*((VP_PAR)x)+MXY(m)*((VP_PAR)y)+MXW(m)*((VP_PAR)f))/((VP_PAR)w))
261 
262 /* Y Projection given a point x,y,0,f and the w' */
263 #define VP_PROJY(m,x,y,w,f) (\
264   (MYX(m)*((VP_PAR)x)+MYY(m)*((VP_PAR)y)+MYW(m)*((VP_PAR)f))/((VP_PAR)w))
265 
266 /* Set the reference id for a motion */
267 #define VP_SET_REFID(m,id) do { (m).refid=id; } while (0)
268 
269 /* Set the inspection id for a motion */
270 #define VP_SET_INSID(m,id) do { (m).insid=id; } while (0)
271 
272 void vp_copy_motion  (const VP_MOTION *src, VP_MOTION *dst);
273 int vp_invert_motion(const VP_MOTION* in,VP_MOTION* out);
274 int vp_cascade_motion(const VP_MOTION* InAB, const VP_MOTION* InBC,VP_MOTION* OutAC);
275 int vp_zoom_motion2d(VP_MOTION* in, VP_MOTION* out,
276               int n, int w, int h, double zoom);
277 double vp_motion_cornerdiff(const VP_MOTION *mot_a, const VP_MOTION *mot_b,
278                      int xo, int yo, int w, int h);
279 
280 #endif /* VP_MOTIONMODEL_H */
281 /* =================================================================== */
282 /* end vp_motionmodel.h */
283