00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "fvec4.h"
00021
00022 #include <assert.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00042 void homography4_from_4pt(const fvec4 x[2], const fvec4 y[2], const fvec4 z[2], const fvec4 w[2], fvec4 cgret[9])
00043 {
00044 fvec4 t1 = x[0];
00045 fvec4 t2 = z[0];
00046 fvec4 t4 = y[1];
00047 fvec4 t5 = t1 * t2 * t4;
00048 fvec4 t6 = w[1];
00049 fvec4 t7 = t1 * t6;
00050 fvec4 t8 = t2 * t7;
00051 fvec4 t9 = z[1];
00052 fvec4 t10 = t1 * t9;
00053 fvec4 t11 = y[0];
00054 fvec4 t14 = x[1];
00055 fvec4 t15 = w[0];
00056 fvec4 t16 = t14 * t15;
00057 fvec4 t18 = t16 * t11;
00058 fvec4 t20 = t15 * t11 * t9;
00059 fvec4 t21 = t15 * t4;
00060 fvec4 t24 = t15 * t9;
00061 fvec4 t25 = t2 * t4;
00062 fvec4 t26 = t6 * t2;
00063 fvec4 t27 = t6 * t11;
00064 fvec4 t28 = t9 * t11;
00065 fvec4 t30 = fvec4(1)/(t21 -t24 - t25 + t26 - t27 + t28);
00066 fvec4 t32 = t1 * t15;
00067 fvec4 t35 = t14 * t11;
00068 fvec4 t41 = t4 * t1;
00069 fvec4 t42 = t6 * t41;
00070 fvec4 t43 = t14 * t2;
00071 fvec4 t46 = t16 * t9;
00072 fvec4 t48 = t14 * t9 * t11;
00073 fvec4 t51 = t4 * t6 * t2;
00074 fvec4 t55 = t6 * t14;
00075 cgret[0] = -(t8 -t5 + t10 * t11 - t11 * t7 - t16 * t2 + t18 - t20 + t21 * t2) * t30;
00076 cgret[1] = (t5 - t8 - t32 * t4 + t32 * t9 + t18 - t2 * t35 + t27 * t2 - t20) * t30;
00077 cgret[2] = t1;
00078 cgret[3] = (-t9 * t7 + t42 + t43 * t4 - t16 * t4 + t46 - t48 + t27 * t9 - t51) * t30;
00079 cgret[4] = (-t42 + t41 * t9 - t55 * t2 + t46 - t48 + t55 * t11 + t51 - t21 * t9) * t30;
00080 cgret[5] = t14;
00081 cgret[6] = (-t10 + t41 + t43 - t35 + t24 - t21 - t26 + t27) * t30;
00082 cgret[7] = (-t7 + t10 + t16 - t43 + t27 - t28 - t21 + t25) * t30;
00083 cgret[8] = fvec4(1);
00084
00085 }
00086
00087 inline void homography_transform(const float a[2], const float H[3][3], float r[2])
00088 {
00089 float z = 1.0f/(H[2][0]*a[0] + H[2][1]*a[1] + H[2][2]);
00090 r[0] = (H[0][0]*a[0] + H[0][1]*a[1] + H[0][2])*z;
00091 r[1] = (H[1][0]*a[0] + H[1][1]*a[1] + H[1][2])*z;
00092 }
00093
00094
00095 inline void homography4_transform(const fvec4 a[2], const fvec4 H[3][3], fvec4 r[2])
00096 {
00097 fvec4 z = fvec4(1)/(H[2][0]*a[0] + H[2][1]*a[1] + H[2][2]);
00098 r[0] = (H[0][0]*a[0] + H[0][1]*a[1] + H[0][2])*z;
00099 r[1] = (H[1][0]*a[0] + H[1][1]*a[1] + H[1][2])*z;
00100 }
00101
00102 #ifdef DEBUG_CMPHOMO
00103 #include <iostream>
00104
00105 static bool eps_cmp2(const fvec4 a[2], const fvec4 b[2])
00106 {
00107 float eps = 1e-1;
00108 fvec4 dx = a[0]-b[0], dy =a[1]-b[1];
00109
00110 fvec4 dx2 = dx*dx;
00111 fvec4 dy2 = dy*dy;
00112 for (int i=0; i<fvec4::size; i++) {
00113 if (finite(dx2[i]) && finite(dy2[i]) &&
00114 dx2[i] > eps || dy2[i]>eps) {
00115 std::cout << "(" << a[0][i] << "," << a[1][i] << ") should be at (" << b[0][i] << "," << b[1][i] << ")\n";
00116 return false;
00117 }
00118 }
00119 return true;
00120
00121 }
00122 #endif
00123
00124 void homography4_from_4corresp(
00125 const fvec4 a[2], const fvec4 b[2], const fvec4 c[2], const fvec4 d[2],
00126 const fvec4 x[2], const fvec4 y[2], const fvec4 z[2], const fvec4 w[2], fvec4 R[3][3])
00127 {
00128 fvec4 Hr[3][3], Hl[3][3];
00129
00130 homography4_from_4pt(a,b,c,d,&Hr[0][0]);
00131 homography4_from_4pt(x,y,z,w,&Hl[0][0]);
00132
00133
00134 fvec4 t2 = Hr[1][1]-Hr[2][1]*Hr[1][2];
00135 fvec4 t4 = Hr[0][0]*Hr[1][1];
00136 fvec4 t5 = Hr[0][0]*Hr[1][2];
00137 fvec4 t7 = Hr[1][0]*Hr[0][1];
00138 fvec4 t8 = Hr[0][2]*Hr[1][0];
00139 fvec4 t10 = Hr[0][1]*Hr[2][0];
00140 fvec4 t12 = Hr[0][2]*Hr[2][0];
00141 fvec4 t15 = fvec4(1)/(t4-t5*Hr[2][1]-t7+t8*Hr[2][1]+t10*Hr[1][2]-t12*Hr[1][1]);
00142 fvec4 t18 = -Hr[1][0]+Hr[1][2]*Hr[2][0];
00143 fvec4 t23 = -Hr[1][0]*Hr[2][1]+Hr[1][1]*Hr[2][0];
00144 fvec4 t28 = -Hr[0][1]+Hr[0][2]*Hr[2][1];
00145 fvec4 t31 = Hr[0][0]-t12;
00146 fvec4 t35 = Hr[0][0]*Hr[2][1]-t10;
00147 fvec4 t41 = -Hr[0][1]*Hr[1][2]+Hr[0][2]*Hr[1][1];
00148 fvec4 t44 = t5-t8;
00149 fvec4 t47 = t4-t7;
00150 fvec4 t48 = t2*t15;
00151 fvec4 t49 = t28*t15;
00152 fvec4 t50 = t41*t15;
00153 R[0][0] = Hl[0][0]*t48+Hl[0][1]*(t18*t15)-Hl[0][2]*(t23*t15);
00154 R[0][1] = Hl[0][0]*t49+Hl[0][1]*(t31*t15)-Hl[0][2]*(t35*t15);
00155 R[0][2] = -Hl[0][0]*t50-Hl[0][1]*(t44*t15)+Hl[0][2]*(t47*t15);
00156 R[1][0] = Hl[1][0]*t48+Hl[1][1]*(t18*t15)-Hl[1][2]*(t23*t15);
00157 R[1][1] = Hl[1][0]*t49+Hl[1][1]*(t31*t15)-Hl[1][2]*(t35*t15);
00158 R[1][2] = -Hl[1][0]*t50-Hl[1][1]*(t44*t15)+Hl[1][2]*(t47*t15);
00159 R[2][0] = Hl[2][0]*t48+Hl[2][1]*(t18*t15)-t23*t15;
00160 R[2][1] = Hl[2][0]*t49+Hl[2][1]*(t31*t15)-t35*t15;
00161 R[2][2] = -Hl[2][0]*t50-Hl[2][1]*(t44*t15)+t47*t15;
00162
00163 #ifdef DEBUG_CMPHOMO
00164
00165 fvec4 uv[2];
00166 homography4_transform(a, R, uv);
00167 assert(eps_cmp2(uv,x));
00168
00169 homography4_transform(b, R, uv);
00170 assert(eps_cmp2(uv,y));
00171
00172 homography4_transform(c, R, uv);
00173 assert(eps_cmp2(uv,z));
00174
00175 homography4_transform(d, R, uv);
00176 assert(eps_cmp2(uv,w));
00177 #endif
00178 }
00179
00180 static inline float rand_range(unsigned long n) {
00181
00182 int rnd = rand();
00183 float r = (float)floor(double(n)*double(rnd)/(double(RAND_MAX)+1.0));
00184 return r;
00185 }
00186
00187 static inline fvec4 rand_range4(int n) {
00188 return fvec4( rand_range(n), rand_range(n), rand_range(n), rand_range(n) );
00189 }
00190
00191 static inline const float *row(int row, const float *array, int stride)
00192 {
00193 return (const float *)(((char*)array)+row*stride);
00194 }
00195
00196 static inline fvec4 dist2(const fvec4 a[2], const fvec4 b[2]) { fvec4 dx(a[0]-b[0]); fvec4 dy(a[1]-b[1]); return dx*dx + dy*dy; }
00197 static inline float dist2(const float a[2], const float b[2]) { float dx(a[0]-b[0]); float dy(a[1]-b[1]); return dx*dx + dy*dy; }
00198
00199 int ransac_h4(const float *uv1, int stride1, const float *uv2, int stride2, int n,
00200 int maxiter, float dist_threshold, int stop_support,
00201 float result[3][3], char *inliers_mask, float *inliers1, float *inliers2)
00202 {
00203 fvec4 bestH[3][3];
00204 fvec4 best_support(0);
00205 fvec4 threshold(dist_threshold*dist_threshold);
00206
00207 if (n<5) return 0;
00208
00209 for (int iter=0; iter<maxiter; ++iter) {
00210
00211 fvec4 corresp[4];
00212
00213 for (int i=0;i<4;i++) {
00214 corresp[i] = rand_range4(n-i);
00215
00216 for (int j=0; j<i; j++) {
00217 corresp[i] += ((corresp[j] <= corresp[i]) & fvec4(1));
00218 }
00219
00220 if (i==1) {
00221 fvec4 cmin = min(corresp[0],corresp[1]);
00222 fvec4 cmax = max(corresp[0],corresp[1]);
00223 corresp[0] = cmin;
00224 corresp[1] = cmax;
00225 }
00226 if (i==2) {
00227 fvec4 min01 = corresp[0];
00228 fvec4 max01 = corresp[1];
00229 fvec4 min12 = min(corresp[1],corresp[2]);
00230 fvec4 min02 = min(corresp[0],corresp[2]);
00231 corresp[0] = min(min01,corresp[2]);
00232 corresp[1] = max(max(min01,min12), min02);
00233 corresp[2]= max(max01,corresp[2]);
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244 fvec4 pts1[4][2];
00245 fvec4 pts2[4][2];
00246 for (int i=0; i<4; i++) {
00247 for (int j=0; j<fvec4::size; j++) {
00248 int r = (int)floorf(corresp[i][j]);
00249 assert (r>=0);
00250 assert (r<n);
00251 pts1[i][0][j] = row(r, uv1, stride1)[0];
00252 pts1[i][1][j] = row(r, uv1, stride1)[1];
00253 pts2[i][0][j] = row(r, uv2, stride2)[0];
00254 pts2[i][1][j] = row(r, uv2, stride2)[1];
00255 }
00256 }
00257
00258
00259 fvec4 H[3][3];
00260 homography4_from_4corresp(
00261 pts1[0], pts1[1], pts1[2], pts1[3],
00262 pts2[0], pts2[1], pts2[2], pts2[3],
00263 H);
00264
00265
00266 fvec4 support(0);
00267 for (int i=0; i<n; i++) {
00268 fvec4 p[2], g[2];
00269 p[0] = fvec4( row(i,uv1,stride1)[0] );
00270 p[1] = fvec4( row(i,uv1,stride1)[1] );
00271 g[0] = fvec4( row(i,uv2,stride2)[0] );
00272 g[1] = fvec4( row(i,uv2,stride2)[1] );
00273 fvec4 t[2];
00274 homography4_transform(p, H, t);
00275
00276 support += (dist2(t,g) < threshold) & fvec4(1);
00277 }
00278
00279
00280 fvec4 replace = support > best_support;
00281 fvec4 keep = replace ^ (fvec4(0)<fvec4(1));
00282 best_support = (support & replace) | (best_support & keep);
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 for (int i=0; i<3; i++)
00294 for (int j=0;j<3; j++)
00295 bestH[i][j] = (H[i][j] & replace) | (bestH[i][j] & keep);
00296
00297
00298
00299 if (best_support.horizontal_max() >= stop_support) break;
00300 }
00301
00302
00303 int s = best_support.horizontal_max_index();
00304 for (int i=0; i<3; i++)
00305 for (int j=0;j<3; j++)
00306 result[i][j] = bestH[i][j][s];
00307
00308 if (inliers_mask || inliers1 || inliers2) {
00309 float t2 = threshold[0];
00310
00311 float *in1 = inliers1;
00312 float *in2 = inliers2;
00313 for (int i=0; i<n; i++) {
00314 float t[2];
00315 homography_transform(row(i,uv1,stride1), result, t);
00316 bool inlier = dist2(t, row(i,uv2,stride2)) < t2;
00317
00318 if (inliers_mask) inliers_mask[i] = ( inlier ? 0xFF : 0);
00319 if (inlier) {
00320 if (inliers1) {
00321 *in1++ = row(i,uv1,stride1)[0];
00322 *in1++ = row(i,uv1,stride1)[1];
00323 }
00324 if (inliers2) {
00325 *in2++ = row(i,uv2,stride2)[0];
00326 *in2++ = row(i,uv2,stride2)[1];
00327 }
00328 }
00329 }
00330 }
00331
00332 return (int)best_support[s];
00333 }