00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "matcher.h"
00023 #include "triangle.h"
00024 #include "filter.h"
00025
00026 using namespace std;
00027
00029
00031
00032
00033 Matcher::Matcher(parameters param) : param(param) {
00034
00035
00036 m1p1 = 0; n1p1 = 0;
00037 m1p2 = 0; n1p2 = 0;
00038 m2p1 = 0; n2p1 = 0;
00039 m2p2 = 0; n2p2 = 0;
00040 m1c1 = 0; n1c1 = 0;
00041 m1c2 = 0; n1c2 = 0;
00042 m2c1 = 0; n2c1 = 0;
00043 m2c2 = 0; n2c2 = 0;
00044 I1p = 0; I2p = 0;
00045 I1c = 0; I2c = 0;
00046 I1p_du = 0; I1p_dv = 0;
00047 I2p_du = 0; I2p_dv = 0;
00048 I1c_du = 0; I1c_dv = 0;
00049 I2c_du = 0; I2c_dv = 0;
00050 I1p_du_full = 0; I1p_dv_full = 0;
00051 I2p_du_full = 0; I2p_dv_full = 0;
00052 I1c_du_full = 0; I1c_dv_full = 0;
00053 I2c_du_full = 0; I2c_dv_full = 0;
00054
00055
00056 margin = 5+1;
00057
00058
00059 if (param.half_resolution)
00060 this->param.match_radius /= 2;
00061 }
00062
00063
00064 Matcher::~Matcher() {
00065 if (I1p) _mm_free(I1p);
00066 if (I2p) _mm_free(I2p);
00067 if (I1c) _mm_free(I1c);
00068 if (I2c) _mm_free(I2c);
00069 if (m1p1) _mm_free(m1p1);
00070 if (m1p2) _mm_free(m1p2);
00071 if (I1p_du) _mm_free(I1p_du);
00072 if (I1p_dv) _mm_free(I1p_dv);
00073 if (I1p_du_full) _mm_free(I1p_du_full);
00074 if (I1p_dv_full) _mm_free(I1p_dv_full);
00075 if (m2p1) _mm_free(m2p1);
00076 if (m2p2) _mm_free(m2p2);
00077 if (I2p_du) _mm_free(I2p_du);
00078 if (I2p_dv) _mm_free(I2p_dv);
00079 if (I2p_du_full) _mm_free(I2p_du_full);
00080 if (I2p_dv_full) _mm_free(I2p_dv_full);
00081 if (m1c1) _mm_free(m1c1);
00082 if (m1c2) _mm_free(m1c2);
00083 if (I1c_du) _mm_free(I1c_du);
00084 if (I1c_dv) _mm_free(I1c_dv);
00085 if (I1c_du_full) _mm_free(I1c_du_full);
00086 if (I1c_dv_full) _mm_free(I1c_dv_full);
00087 if (m2c1) _mm_free(m2c1);
00088 if (m2c2) _mm_free(m2c2);
00089 if (I2c_du) _mm_free(I2c_du);
00090 if (I2c_dv) _mm_free(I2c_dv);
00091 if (I2c_du_full) _mm_free(I2c_du_full);
00092 if (I2c_dv_full) _mm_free(I2c_dv_full);
00093 }
00094
00095 void Matcher::pushBack (uint8_t *I1,uint8_t* I2,int32_t* dims,const bool replace) {
00096
00097
00098 int32_t width = dims[0];
00099 int32_t height = dims[1];
00100 int32_t bpl = dims[2];
00101
00102
00103 if (width<=0 || height<=0 || bpl<width || I1==0) {
00104 cerr << "ERROR: Image dimension mismatch!" << endl;
00105 return;
00106 }
00107
00108 if (replace) {
00109 if (I1c) _mm_free(I1c);
00110 if (I2c) _mm_free(I2c);
00111 if (m1c1) _mm_free(m1c1);
00112 if (m1c2) _mm_free(m1c2);
00113 if (I1c_du) _mm_free(I1c_du);
00114 if (I1c_dv) _mm_free(I1c_dv);
00115 if (I1c_du_full) _mm_free(I1c_du_full);
00116 if (I1c_dv_full) _mm_free(I1c_dv_full);
00117 if (m2c1) _mm_free(m2c1);
00118 if (m2c2) _mm_free(m2c2);
00119 if (I2c_du) _mm_free(I2c_du);
00120 if (I2c_dv) _mm_free(I2c_dv);
00121 if (I2c_du_full) _mm_free(I2c_du_full);
00122 if (I2c_dv_full) _mm_free(I2c_dv_full);
00123 } else {
00124 if (I1p) _mm_free(I1p);
00125 if (I2p) _mm_free(I2p);
00126 if (m1p1) _mm_free(m1p1);
00127 if (m1p2) _mm_free(m1p2);
00128 if (I1p_du) _mm_free(I1p_du);
00129 if (I1p_dv) _mm_free(I1p_dv);
00130 if (I1p_du_full) _mm_free(I1p_du_full);
00131 if (I1p_dv_full) _mm_free(I1p_dv_full);
00132 if (m2p1) _mm_free(m2p1);
00133 if (m2p2) _mm_free(m2p2);
00134 if (I2p_du) _mm_free(I2p_du);
00135 if (I2p_dv) _mm_free(I2p_dv);
00136 if (I2p_du_full) _mm_free(I2p_du_full);
00137 if (I2p_dv_full) _mm_free(I2p_dv_full);
00138 m1p1 = m1c1; n1p1 = n1c1;
00139 m1p2 = m1c2; n1p2 = n1c2;
00140 m2p1 = m2c1; n2p1 = n2c1;
00141 m2p2 = m2c2; n2p2 = n2c2;
00142 I1p = I1c;
00143 I2p = I2c;
00144 I1p_du = I1c_du;
00145 I1p_dv = I1c_dv;
00146 I1p_du_full = I1c_du_full;
00147 I1p_dv_full = I1c_dv_full;
00148 I2p_du = I2c_du;
00149 I2p_dv = I2c_dv;
00150 I2p_du_full = I2c_du_full;
00151 I2p_dv_full = I2c_dv_full;
00152 dims_p[0] = dims_c[0];
00153 dims_p[1] = dims_c[1];
00154 dims_p[2] = dims_c[2];
00155 }
00156
00157
00158 dims_c[0] = width;
00159 dims_c[1] = height;
00160 dims_c[2] = width + 15-(width-1)%16;
00161
00162
00163 I1c = (uint8_t*)_mm_malloc(dims_c[2]*dims_c[1]*sizeof(uint8_t),16);
00164 I2c = (uint8_t*)_mm_malloc(dims_c[2]*dims_c[1]*sizeof(uint8_t),16);
00165 if (dims_c[2]==bpl) {
00166 memcpy(I1c,I1,dims_c[2]*dims_c[1]*sizeof(uint8_t));
00167 if (I2!=0)
00168 memcpy(I2c,I2,dims_c[2]*dims_c[1]*sizeof(uint8_t));
00169 } else {
00170 for (int32_t v=0; v<height; v++) {
00171 memcpy(I1c+v*dims_c[2],I1+v*bpl,dims_c[0]*sizeof(uint8_t));
00172 if (I2!=0)
00173 memcpy(I2c+v*dims_c[2],I2+v*bpl,dims_c[0]*sizeof(uint8_t));
00174 }
00175 }
00176
00177
00178 computeFeatures(I1c,dims_c,m1c1,n1c1,m1c2,n1c2,I1c_du,I1c_dv,I1c_du_full,I1c_dv_full);
00179 if (I2!=0)
00180 computeFeatures(I2c,dims_c,m2c1,n2c1,m2c2,n2c2,I2c_du,I2c_dv,I2c_du_full,I2c_dv_full);
00181 }
00182
00183 void Matcher::matchFeatures(int32_t method, Matrix *Tr_delta) {
00184
00186
00188
00189
00190 if (method==0) {
00191 if (m1p2==0 || n1p2==0 || m1c2==0 || n1c2==0)
00192 return;
00193 if (param.multi_stage)
00194 if (m1p1==0 || n1p1==0 || m1c1==0 || n1c1==0)
00195 return;
00196
00197
00198 } else if (method==1) {
00199 if (m1c2==0 || n1c2==0 || m2c2==0 || n2c2==0)
00200 return;
00201 if (param.multi_stage)
00202 if (m1c1==0 || n1c1==0 || m2c1==0 || n2c1==0)
00203 return;
00204
00205
00206 } else {
00207 if (m1p2==0 || n1p2==0 || m2p2==0 || n2p2==0 || m1c2==0 || n1c2==0 || m2c2==0 || n2c2==0)
00208 return;
00209 if (param.multi_stage)
00210 if (m1p1==0 || n1p1==0 || m2p1==0 || n2p1==0 || m1c1==0 || n1c1==0 || m2c1==0 || n2c1==0)
00211 return;
00212 }
00213
00214
00215 p_matched_1.clear();
00216 p_matched_2.clear();
00217
00218
00219 if (param.multi_stage) {
00220
00221
00222 matching(m1p1,m2p1,m1c1,m2c1,n1p1,n2p1,n1c1,n2c1,p_matched_1,method,false,Tr_delta);
00223 removeOutliers(p_matched_1,method);
00224
00225
00226 computePriorStatistics(p_matched_1,method);
00227
00228
00229 matching(m1p2,m2p2,m1c2,m2c2,n1p2,n2p2,n1c2,n2c2,p_matched_2,method,true,Tr_delta);
00230 if (param.refinement>0)
00231 refinement(p_matched_2,method);
00232 removeOutliers(p_matched_2,method);
00233
00234
00235 } else {
00236 matching(m1p2,m2p2,m1c2,m2c2,n1p2,n2p2,n1c2,n2c2,p_matched_2,method,false,Tr_delta);
00237 if (param.refinement>0)
00238 refinement(p_matched_2,method);
00239 removeOutliers(p_matched_2,method);
00240 }
00241 }
00242
00243 void Matcher::bucketFeatures(int32_t max_features,float bucket_width,float bucket_height) {
00244
00245
00246 float u_max = 0;
00247 float v_max = 0;
00248 for (vector<p_match>::iterator it = p_matched_2.begin(); it!=p_matched_2.end(); it++) {
00249 if (it->u1c>u_max) u_max=it->u1c;
00250 if (it->v1c>v_max) v_max=it->v1c;
00251 }
00252
00253
00254 int32_t bucket_cols = (int32_t)floor(u_max/bucket_width)+1;
00255 int32_t bucket_rows = (int32_t)floor(v_max/bucket_height)+1;
00256 vector<p_match> *buckets = new vector<p_match>[bucket_cols*bucket_rows];
00257
00258
00259 for (vector<p_match>::iterator it=p_matched_2.begin(); it!=p_matched_2.end(); it++) {
00260 int32_t u = (int32_t)floor(it->u1c/bucket_width);
00261 int32_t v = (int32_t)floor(it->v1c/bucket_height);
00262 buckets[v*bucket_cols+u].push_back(*it);
00263 }
00264
00265
00266 p_matched_2.clear();
00267 for (int32_t i=0; i<bucket_cols*bucket_rows; i++) {
00268
00269
00270 std::random_shuffle(buckets[i].begin(),buckets[i].end());
00271
00272
00273 int32_t k=0;
00274 for (vector<p_match>::iterator it=buckets[i].begin(); it!=buckets[i].end(); it++) {
00275 p_matched_2.push_back(*it);
00276 k++;
00277 if (k>=max_features)
00278 break;
00279 }
00280 }
00281
00282
00283 delete []buckets;
00284 }
00285
00286 float Matcher::getGain (vector<int32_t> inliers) {
00287
00288
00289 if (I1p==0 || I1c==0 || p_matched_2.size()==0 || inliers.size()==0)
00290 return 1;
00291
00292 int32_t window_size = 3;
00293 float gain = 0;
00294 int32_t num = 0;
00295 int32_t u_min,u_max,v_min,v_max;
00296 float mean_prev,mean_curr;
00297
00298 for (vector<int32_t>::iterator it=inliers.begin(); it!=inliers.end(); it++) {
00299 if (*it<(int32_t)p_matched_2.size()) {
00300
00301
00302 u_min = min(max((int32_t)p_matched_2[*it].u1p-window_size,0),dims_p[0]);
00303 u_max = min(max((int32_t)p_matched_2[*it].u1p+window_size,0),dims_p[0]);
00304 v_min = min(max((int32_t)p_matched_2[*it].v1p-window_size,0),dims_p[1]);
00305 v_max = min(max((int32_t)p_matched_2[*it].v1p+window_size,0),dims_p[1]);
00306 mean_prev = mean(I1p,dims_p[2],u_min,u_max,v_min,v_max);
00307
00308
00309 u_min = min(max((int32_t)p_matched_2[*it].u1c-window_size,0),dims_p[0]);
00310 u_max = min(max((int32_t)p_matched_2[*it].u1c+window_size,0),dims_p[0]);
00311 v_min = min(max((int32_t)p_matched_2[*it].v1c-window_size,0),dims_p[1]);
00312 v_max = min(max((int32_t)p_matched_2[*it].v1c+window_size,0),dims_p[1]);
00313 mean_curr = mean(I1c,dims_c[2],u_min,u_max,v_min,v_max);
00314
00315 if (mean_prev>10) {
00316 gain += mean_curr/mean_prev;
00317 num++;
00318 }
00319 }
00320 }
00321
00322 if (num>0) return gain/=(float)num;
00323 else return 1;
00324 }
00325
00327
00329
00330 void Matcher::nonMaximumSuppression (int16_t* I_f1,int16_t* I_f2,const int32_t* dims,vector<Matcher::maximum> &maxima,int32_t nms_n) {
00331
00332
00333 int32_t width = dims[0];
00334 int32_t height = dims[1];
00335 int32_t bpl = dims[2];
00336 int32_t n = nms_n;
00337 int32_t tau = param.nms_tau;
00338
00339
00340 int32_t f1mini,f1minj,f1maxi,f1maxj,f2mini,f2minj,f2maxi,f2maxj;
00341 int32_t f1minval,f1maxval,f2minval,f2maxval,currval;
00342 int32_t addr;
00343
00344 for (int32_t i=n+margin; i<width-n-margin;i+=n+1) {
00345 for (int32_t j=n+margin; j<height-n-margin;j+=n+1) {
00346
00347 f1mini = i; f1minj = j; f1maxi = i; f1maxj = j;
00348 f2mini = i; f2minj = j; f2maxi = i; f2maxj = j;
00349
00350 addr = getAddressOffsetImage(i,j,bpl);
00351 f1minval = *(I_f1+addr);
00352 f1maxval = f1minval;
00353 f2minval = *(I_f2+addr);
00354 f2maxval = f2minval;
00355
00356 for (int32_t i2=i; i2<=i+n; i2++) {
00357 for (int32_t j2=j; j2<=j+n; j2++) {
00358 addr = getAddressOffsetImage(i2,j2,bpl);
00359 currval = *(I_f1+addr);
00360 if (currval<f1minval) {
00361 f1mini = i2;
00362 f1minj = j2;
00363 f1minval = currval;
00364 } else if (currval>f1maxval) {
00365 f1maxi = i2;
00366 f1maxj = j2;
00367 f1maxval = currval;
00368 }
00369 currval = *(I_f2+addr);
00370 if (currval<f2minval) {
00371 f2mini = i2;
00372 f2minj = j2;
00373 f2minval = currval;
00374 } else if (currval>f2maxval) {
00375 f2maxi = i2;
00376 f2maxj = j2;
00377 f2maxval = currval;
00378 }
00379 }
00380 }
00381
00382
00383 for (int32_t i2=f1mini-n; i2<=min(f1mini+n,width-1-margin); i2++) {
00384 for (int32_t j2=f1minj-n; j2<=min(f1minj+n,height-1-margin); j2++) {
00385 currval = *(I_f1+getAddressOffsetImage(i2,j2,bpl));
00386 if (currval<f1minval && (i2<i || i2>i+n || j2<j || j2>j+n))
00387 goto failed_f1min;
00388 }
00389 }
00390 if (f1minval<=-tau)
00391 maxima.push_back(Matcher::maximum(f1mini,f1minj,f1minval,0));
00392 failed_f1min:;
00393
00394
00395 for (int32_t i2=f1maxi-n; i2<=min(f1maxi+n,width-1-margin); i2++) {
00396 for (int32_t j2=f1maxj-n; j2<=min(f1maxj+n,height-1-margin); j2++) {
00397 currval = *(I_f1+getAddressOffsetImage(i2,j2,bpl));
00398 if (currval>f1maxval && (i2<i || i2>i+n || j2<j || j2>j+n))
00399 goto failed_f1max;
00400 }
00401 }
00402 if (f1maxval>=tau)
00403 maxima.push_back(Matcher::maximum(f1maxi,f1maxj,f1maxval,1));
00404 failed_f1max:;
00405
00406
00407 for (int32_t i2=f2mini-n; i2<=min(f2mini+n,width-1-margin); i2++) {
00408 for (int32_t j2=f2minj-n; j2<=min(f2minj+n,height-1-margin); j2++) {
00409 currval = *(I_f2+getAddressOffsetImage(i2,j2,bpl));
00410 if (currval<f2minval && (i2<i || i2>i+n || j2<j || j2>j+n))
00411 goto failed_f2min;
00412 }
00413 }
00414 if (f2minval<=-tau)
00415 maxima.push_back(Matcher::maximum(f2mini,f2minj,f2minval,2));
00416 failed_f2min:;
00417
00418
00419 for (int32_t i2=f2maxi-n; i2<=min(f2maxi+n,width-1-margin); i2++) {
00420 for (int32_t j2=f2maxj-n; j2<=min(f2maxj+n,height-1-margin); j2++) {
00421 currval = *(I_f2+getAddressOffsetImage(i2,j2,bpl));
00422 if (currval>f2maxval && (i2<i || i2>i+n || j2<j || j2>j+n))
00423 goto failed_f2max;
00424 }
00425 }
00426 if (f2maxval>=tau)
00427 maxima.push_back(Matcher::maximum(f2maxi,f2maxj,f2maxval,3));
00428 failed_f2max:;
00429 }
00430 }
00431 }
00432
00433 inline void Matcher::computeDescriptor (const uint8_t* I_du,const uint8_t* I_dv,const int32_t &bpl,const int32_t &u,const int32_t &v,uint8_t *desc_addr) {
00434
00435
00436 int32_t addr_m1 = getAddressOffsetImage(u,v-1,bpl);
00437 int32_t addr_m3 = addr_m1-2*bpl;
00438 int32_t addr_m5 = addr_m3-2*bpl;
00439 int32_t addr_p1 = addr_m1+2*bpl;
00440 int32_t addr_p3 = addr_p1+2*bpl;
00441 int32_t addr_p5 = addr_p3+2*bpl;
00442
00443
00444 uint32_t k = 0;
00445 desc_addr[k++] = I_du[addr_m1-3];
00446 desc_addr[k++] = I_dv[addr_m1-3];
00447 desc_addr[k++] = I_du[addr_p1-3];
00448 desc_addr[k++] = I_dv[addr_p1-3];
00449 desc_addr[k++] = I_du[addr_m1-1];
00450 desc_addr[k++] = I_dv[addr_m1-1];
00451 desc_addr[k++] = I_du[addr_p1-1];
00452 desc_addr[k++] = I_dv[addr_p1-1];
00453 desc_addr[k++] = I_du[addr_m1+3];
00454 desc_addr[k++] = I_dv[addr_m1+3];
00455 desc_addr[k++] = I_du[addr_p1+3];
00456 desc_addr[k++] = I_dv[addr_p1+3];
00457 desc_addr[k++] = I_du[addr_m1+1];
00458 desc_addr[k++] = I_dv[addr_m1+1];
00459 desc_addr[k++] = I_du[addr_p1+1];
00460 desc_addr[k++] = I_dv[addr_p1+1];
00461 desc_addr[k++] = I_du[addr_m5-1];
00462 desc_addr[k++] = I_dv[addr_m5-1];
00463 desc_addr[k++] = I_du[addr_p5-1];
00464 desc_addr[k++] = I_dv[addr_p5-1];
00465 desc_addr[k++] = I_du[addr_m5+1];
00466 desc_addr[k++] = I_dv[addr_m5+1];
00467 desc_addr[k++] = I_du[addr_p5+1];
00468 desc_addr[k++] = I_dv[addr_p5+1];
00469 desc_addr[k++] = I_du[addr_m3-5];
00470 desc_addr[k++] = I_dv[addr_m3-5];
00471 desc_addr[k++] = I_du[addr_p3-5];
00472 desc_addr[k++] = I_dv[addr_p3-5];
00473 desc_addr[k++] = I_du[addr_m3+5];
00474 desc_addr[k++] = I_dv[addr_m3+5];
00475 desc_addr[k++] = I_du[addr_p3+5];
00476 desc_addr[k++] = I_dv[addr_p3+5];
00477 }
00478
00479 inline void Matcher::computeSmallDescriptor (const uint8_t* I_du,const uint8_t* I_dv,const int32_t &bpl,const int32_t &u,const int32_t &v,uint8_t *desc_addr) {
00480
00481
00482 int32_t addr2 = getAddressOffsetImage(u,v,bpl);
00483 int32_t addr1 = addr2-bpl;
00484 int32_t addr0 = addr1-bpl;
00485 int32_t addr3 = addr2+bpl;
00486 int32_t addr4 = addr3+bpl;
00487
00488
00489 uint32_t k = 0;
00490 desc_addr[k++] = I_du[addr0];
00491 desc_addr[k++] = I_du[addr1-2];
00492 desc_addr[k++] = I_du[addr1];
00493 desc_addr[k++] = I_du[addr1+2];
00494 desc_addr[k++] = I_du[addr2-1];
00495 desc_addr[k++] = I_du[addr2];
00496 desc_addr[k++] = I_du[addr2];
00497 desc_addr[k++] = I_du[addr2+1];
00498 desc_addr[k++] = I_du[addr3-2];
00499 desc_addr[k++] = I_du[addr3];
00500 desc_addr[k++] = I_du[addr3+2];
00501 desc_addr[k++] = I_du[addr4];
00502 desc_addr[k++] = I_dv[addr1];
00503 desc_addr[k++] = I_dv[addr2-1];
00504 desc_addr[k++] = I_dv[addr2+1];
00505 desc_addr[k++] = I_dv[addr3];
00506 }
00507
00508 void Matcher::computeDescriptors (uint8_t* I_du,uint8_t* I_dv,const int32_t bpl,std::vector<Matcher::maximum> &maxima) {
00509
00510
00511 int32_t u,v;
00512 uint8_t *desc_addr;
00513
00514
00515 for (vector<Matcher::maximum>::iterator it=maxima.begin(); it!=maxima.end(); it++) {
00516 u = (*it).u;
00517 v = (*it).v;
00518 desc_addr = (uint8_t*)(&((*it).d1));
00519 computeDescriptor(I_du,I_dv,bpl,u,v,desc_addr);
00520 }
00521 }
00522
00523 inline uint8_t Matcher::saturate (int16_t in) {
00524 if (in<0) return 0;
00525 if (in>255) return 255;
00526 return in;
00527 }
00528
00529 void Matcher::filterImageAll (uint8_t* I,uint8_t* I_du,uint8_t* I_dv,int16_t* I_f1,int16_t* I_f2,const int* dims) {
00530
00531
00532 const int32_t height = dims[1];
00533 const int32_t bpl = dims[2];
00534
00535
00536 const uint8_t* p00 = I + 0;
00537 const uint8_t* p01 = I + 1;
00538 const uint8_t* p02 = I + 2;
00539 const uint8_t* p03 = I + 3;
00540 const uint8_t* p04 = I + 4;
00541 const uint8_t* p10 = I + 0 + bpl;
00542 const uint8_t* p11 = I + 1 + bpl;
00543 const uint8_t* p12 = I + 2 + bpl;
00544 const uint8_t* p13 = I + 3 + bpl;
00545 const uint8_t* p14 = I + 4 + bpl;
00546 const uint8_t* p20 = I + 0 + 2*bpl;
00547 const uint8_t* p21 = I + 1 + 2*bpl;
00548 const uint8_t* p22 = I + 2 + 2*bpl;
00549 const uint8_t* p23 = I + 3 + 2*bpl;
00550 const uint8_t* p24 = I + 4 + 2*bpl;
00551 const uint8_t* p30 = I + 0 + 3*bpl;
00552 const uint8_t* p31 = I + 1 + 3*bpl;
00553 const uint8_t* p32 = I + 2 + 3*bpl;
00554 const uint8_t* p33 = I + 3 + 3*bpl;
00555 const uint8_t* p34 = I + 4 + 3*bpl;
00556 const uint8_t* p40 = I + 0 + 4*bpl;
00557 const uint8_t* p41 = I + 1 + 4*bpl;
00558 const uint8_t* p42 = I + 2 + 4*bpl;
00559 const uint8_t* p43 = I + 3 + 4*bpl;
00560 const uint8_t* p44 = I + 4 + 4*bpl;
00561
00562
00563 uint8_t* result_du = I_du + bpl + 1;
00564 uint8_t* result_dv = I_dv + bpl + 1;
00565 int16_t* result_f1 = I_f1 + 2*bpl + 2;
00566 int16_t* result_f2 = I_f2 + 2*bpl + 2;
00567
00568
00569 const uint8_t* end_input = I + bpl*height;
00570
00571
00572 for( ; p44 != end_input; p00++, p01++, p02++, p03++, p04++,
00573 p10++, p11++, p12++, p13++, p14++,
00574 p20++, p21++, p22++, p23++, p24++,
00575 p30++, p31++, p32++, p33++, p34++,
00576 p40++, p41++, p42++, p43++, p44++,
00577 result_du++, result_dv++, result_f1++, result_f2++ ) {
00578 int16_t temp_du = - *p00 - 2 * *p10 - *p20 + *p02 + 2 * *p12 + *p22;
00579 int16_t temp_dv = - *p00 - 2 * *p01 - *p02 + *p20 + 2 * *p21 + *p22;
00580 *result_du = saturate( temp_du/4 + 128 );
00581 *result_dv = saturate( temp_dv/4 + 128 );
00582 *result_f1 = - *p00 - *p01 - *p02 - *p03 - *p04
00583 - *p10 + *p11 + *p12 + *p13 - *p14
00584 - *p20 + *p21 + 8 * *p22 + *p23 - *p24
00585 - *p30 + *p31 + *p32 + *p33 - *p34
00586 - *p40 - *p41 - *p42 - *p43 - *p44;
00587 *result_f2 = - *p00 - *p01 + *p03 + *p04
00588 - *p10 - *p11 + *p13 + *p14
00589 + *p30 + *p31 - *p33 - *p34
00590 + *p40 + *p41 - *p43 - *p44;
00591 }
00592 }
00593
00594 void Matcher::filterImageSobel (uint8_t* I,uint8_t* I_du,uint8_t* I_dv,const int* dims) {
00595
00596
00597 const int32_t height = dims[1];
00598 const int32_t bpl = dims[2];
00599
00600
00601 const uint8_t* p00 = I + 0;
00602 const uint8_t* p01 = I + 1;
00603 const uint8_t* p02 = I + 2;
00604 const uint8_t* p10 = I + 0 + bpl;
00605 const uint8_t* p11 = I + 1 + bpl;
00606 const uint8_t* p12 = I + 2 + bpl;
00607 const uint8_t* p20 = I + 0 + 2*bpl;
00608 const uint8_t* p21 = I + 1 + 2*bpl;
00609 const uint8_t* p22 = I + 2 + 2*bpl;
00610
00611
00612 uint8_t* result_du = I_du + bpl + 1;
00613 uint8_t* result_dv = I_dv + bpl + 1;
00614
00615
00616 const uint8_t* end_input = I + bpl*height;
00617
00618
00619 for( ; p22 != end_input; p00++, p01++, p02++,
00620 p10++, p11++, p12++,
00621 p20++, p21++, p22++,
00622 result_du++, result_dv++) {
00623 int16_t temp_du = - *p00 - 2 * *p10 - *p20 + *p02 + 2 * *p12 + *p22;
00624 int16_t temp_dv = - *p00 - 2 * *p01 - *p02 + *p20 + 2 * *p21 + *p22;
00625 *result_du = saturate( temp_du/4 + 128 );
00626 *result_dv = saturate( temp_dv/4 + 128 );
00627 }
00628 }
00629
00630 void Matcher::getHalfResolutionDimensions(const int32_t *dims,int32_t *dims_half) {
00631 dims_half[0] = dims[0]/2;
00632 dims_half[1] = dims[1]/2;
00633 dims_half[2] = dims_half[0]+15-(dims_half[0]-1)%16;
00634 }
00635
00636 uint8_t* Matcher::createHalfResolutionImage(uint8_t *I,const int32_t* dims) {
00637 int32_t dims_half[3];
00638 getHalfResolutionDimensions(dims,dims_half);
00639 uint8_t* I_half = (uint8_t*)_mm_malloc(dims_half[2]*dims_half[1]*sizeof(uint8_t),16);
00640 for (int32_t v=0; v<dims_half[1]; v++)
00641 for (int32_t u=0; u<dims_half[0]; u++)
00642 I_half[v*dims_half[2]+u] = (uint8_t)(((int32_t)I[(v*2+0)*dims[2]+u*2+0]+
00643 (int32_t)I[(v*2+0)*dims[2]+u*2+1]+
00644 (int32_t)I[(v*2+1)*dims[2]+u*2+0]+
00645 (int32_t)I[(v*2+1)*dims[2]+u*2+1])/4);
00646 return I_half;
00647 }
00648
00649 void Matcher::computeFeatures (uint8_t *I,const int32_t* dims,int32_t* &max1,int32_t &num1,int32_t* &max2,int32_t &num2,uint8_t* &I_du,uint8_t* &I_dv,uint8_t* &I_du_full,uint8_t* &I_dv_full) {
00650
00651 int16_t *I_f1;
00652 int16_t *I_f2;
00653
00654 int32_t dims_matching[3];
00655 memcpy(dims_matching,dims,3*sizeof(int32_t));
00656
00657
00658 if (!param.half_resolution) {
00659 I_du = (uint8_t*)_mm_malloc(dims[2]*dims[1]*sizeof(uint8_t*),16);
00660 I_dv = (uint8_t*)_mm_malloc(dims[2]*dims[1]*sizeof(uint8_t*),16);
00661 I_f1 = (int16_t*)_mm_malloc(dims[2]*dims[1]*sizeof(int16_t),16);
00662 I_f2 = (int16_t*)_mm_malloc(dims[2]*dims[1]*sizeof(int16_t),16);
00663 filter::sobel5x5(I,I_du,I_dv,dims[2],dims[1]);
00664 filter::blob5x5(I,I_f1,dims[2],dims[1]);
00665 filter::checkerboard5x5(I,I_f2,dims[2],dims[1]);
00666 } else {
00667 uint8_t* I_matching = createHalfResolutionImage(I,dims);
00668 getHalfResolutionDimensions(dims,dims_matching);
00669 I_du = (uint8_t*)_mm_malloc(dims_matching[2]*dims_matching[1]*sizeof(uint8_t*),16);
00670 I_dv = (uint8_t*)_mm_malloc(dims_matching[2]*dims_matching[1]*sizeof(uint8_t*),16);
00671 I_f1 = (int16_t*)_mm_malloc(dims_matching[2]*dims_matching[1]*sizeof(int16_t),16);
00672 I_f2 = (int16_t*)_mm_malloc(dims_matching[2]*dims_matching[1]*sizeof(int16_t),16);
00673 I_du_full = (uint8_t*)_mm_malloc(dims[2]*dims[1]*sizeof(uint8_t*),16);
00674 I_dv_full = (uint8_t*)_mm_malloc(dims[2]*dims[1]*sizeof(uint8_t*),16);
00675 filter::sobel5x5(I_matching,I_du,I_dv,dims_matching[2],dims_matching[1]);
00676 filter::sobel5x5(I,I_du_full,I_dv_full,dims[2],dims[1]);
00677 filter::blob5x5(I_matching,I_f1,dims_matching[2],dims_matching[1]);
00678 filter::checkerboard5x5(I_matching,I_f2,dims_matching[2],dims_matching[1]);
00679 _mm_free(I_matching);
00680 }
00681
00682
00683 vector<Matcher::maximum> maxima1;
00684 if (param.multi_stage) {
00685 int32_t nms_n_sparse = param.nms_n*3;
00686 if (nms_n_sparse>10)
00687 nms_n_sparse = max(param.nms_n,10);
00688 nonMaximumSuppression(I_f1,I_f2,dims_matching,maxima1,nms_n_sparse);
00689 computeDescriptors(I_du,I_dv,dims_matching[2],maxima1);
00690 }
00691
00692
00693 vector<Matcher::maximum> maxima2;
00694 nonMaximumSuppression(I_f1,I_f2,dims_matching,maxima2,param.nms_n);
00695 computeDescriptors(I_du,I_dv,dims_matching[2],maxima2);
00696
00697
00698 _mm_free(I_f1);
00699 _mm_free(I_f2);
00700
00701
00702 num1 = maxima1.size();
00703 num2 = maxima2.size();
00704 max1 = 0;
00705 max2 = 0;
00706
00707 int32_t s = 1;
00708 if (param.half_resolution)
00709 s = 2;
00710
00711
00712 if (num1!=0) {
00713 max1 = (int32_t*)_mm_malloc(sizeof(Matcher::maximum)*num1,16);
00714 int32_t k=0;
00715 for (vector<Matcher::maximum>::iterator it=maxima1.begin(); it!=maxima1.end(); it++) {
00716 *(max1+k++) = it->u*s; *(max1+k++) = it->v*s; *(max1+k++) = 0; *(max1+k++) = it->c;
00717 *(max1+k++) = it->d1; *(max1+k++) = it->d2; *(max1+k++) = it->d3; *(max1+k++) = it->d4;
00718 *(max1+k++) = it->d5; *(max1+k++) = it->d6; *(max1+k++) = it->d7; *(max1+k++) = it->d8;
00719 }
00720 }
00721
00722
00723 if (num2!=0) {
00724 max2 = (int32_t*)_mm_malloc(sizeof(Matcher::maximum)*num2,16);
00725 int32_t k=0;
00726 for (vector<Matcher::maximum>::iterator it=maxima2.begin(); it!=maxima2.end(); it++) {
00727 *(max2+k++) = it->u*s; *(max2+k++) = it->v*s; *(max2+k++) = 0; *(max2+k++) = it->c;
00728 *(max2+k++) = it->d1; *(max2+k++) = it->d2; *(max2+k++) = it->d3; *(max2+k++) = it->d4;
00729 *(max2+k++) = it->d5; *(max2+k++) = it->d6; *(max2+k++) = it->d7; *(max2+k++) = it->d8;
00730 }
00731 }
00732 }
00733
00734 void Matcher::computePriorStatistics (vector<Matcher::p_match> &p_matched,int32_t method) {
00735
00736
00737 int32_t u_bin_num = (int32_t)ceil((float)dims_c[0]/(float)param.match_binsize);
00738 int32_t v_bin_num = (int32_t)ceil((float)dims_c[1]/(float)param.match_binsize);
00739 int32_t bin_num = v_bin_num*u_bin_num;
00740
00741
00742 int32_t num_stages = 2;
00743 if (method==2)
00744 num_stages = 4;
00745
00746
00747 vector<Matcher::delta> *delta_accu = new vector<Matcher::delta>[bin_num];
00748
00749
00750 Matcher::delta delta_curr;
00751 for (vector<Matcher::p_match>::iterator it=p_matched.begin(); it!=p_matched.end(); it++) {
00752
00753
00754 if (method==0) {
00755 delta_curr.val[0] = it->u1p - it->u1c;
00756 delta_curr.val[1] = it->v1p - it->v1c;
00757 delta_curr.val[2] = it->u1c - it->u1p;
00758 delta_curr.val[3] = it->v1c - it->v1p;
00759
00760
00761 } else if (method==1) {
00762 delta_curr.val[0] = it->u2c - it->u1c;
00763 delta_curr.val[1] = 0;
00764 delta_curr.val[2] = it->u1c - it->u2c;
00765 delta_curr.val[3] = 0;
00766
00767
00768 } else {
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 delta_curr.val[0] = it->u2p - it->u1p;
00779 delta_curr.val[1] = 0;
00780 delta_curr.val[2] = it->u2c - it->u2p;
00781 delta_curr.val[3] = it->v2c - it->v2p;
00782 delta_curr.val[4] = it->u1c - it->u2c;
00783 delta_curr.val[5] = 0;
00784 delta_curr.val[6] = it->u1p - it->u1c;
00785 delta_curr.val[7] = it->v1p - it->v1c;
00786 }
00787
00788
00789 int32_t u_bin_min,u_bin_max,v_bin_min,v_bin_max;
00790
00791
00792 if (method<2) {
00793 u_bin_min = min(max((int32_t)floor(it->u1c/(float)param.match_binsize)-1,0),u_bin_num-1);
00794 u_bin_max = min(max((int32_t)floor(it->u1c/(float)param.match_binsize)+1,0),u_bin_num-1);
00795 v_bin_min = min(max((int32_t)floor(it->v1c/(float)param.match_binsize)-1,0),v_bin_num-1);
00796 v_bin_max = min(max((int32_t)floor(it->v1c/(float)param.match_binsize)+1,0),v_bin_num-1);
00797
00798
00799 } else {
00800 u_bin_min = min(max((int32_t)floor(it->u1p/(float)param.match_binsize)-1,0),u_bin_num-1);
00801 u_bin_max = min(max((int32_t)floor(it->u1p/(float)param.match_binsize)+1,0),u_bin_num-1);
00802 v_bin_min = min(max((int32_t)floor(it->v1p/(float)param.match_binsize)-1,0),v_bin_num-1);
00803 v_bin_max = min(max((int32_t)floor(it->v1p/(float)param.match_binsize)+1,0),v_bin_num-1);
00804 }
00805
00806
00807 for (int32_t v_bin=v_bin_min; v_bin<=v_bin_max; v_bin++)
00808 for (int32_t u_bin=u_bin_min; u_bin<=u_bin_max; u_bin++)
00809 delta_accu[v_bin*u_bin_num+u_bin].push_back(delta_curr);
00810 }
00811
00812
00813 ranges.clear();
00814
00815
00816 for (int32_t v_bin=0; v_bin<v_bin_num; v_bin++) {
00817 for (int32_t u_bin=0; u_bin<u_bin_num; u_bin++) {
00818
00819
00820 delta delta_min(-param.match_radius);
00821 delta delta_max(+param.match_radius);
00822
00823
00824 if (delta_accu[v_bin*u_bin_num+u_bin].size()>0) {
00825
00826
00827 delta_min = delta(+1000000);
00828 delta_max = delta(-1000000);
00829
00830
00831 for (vector<Matcher::delta>::iterator it=delta_accu[v_bin*u_bin_num+u_bin].begin();
00832 it!=delta_accu[v_bin*u_bin_num+u_bin].end(); it++) {
00833 for (int32_t i=0; i<num_stages*2; i++) {
00834 if (it->val[i]<delta_min.val[i]) delta_min.val[i] = it->val[i];
00835 if (it->val[i]>delta_max.val[i]) delta_max.val[i] = it->val[i];
00836 }
00837 }
00838 }
00839
00840
00841 range r;
00842 for (int32_t i=0; i<num_stages; i++) {
00843
00844
00845 float delta_u = delta_max.val[i*2+0]-delta_min.val[i*2+0];
00846 if (delta_u<20) {
00847 delta_min.val[i*2+0] -= ceil((20-delta_u)/2);
00848 delta_max.val[i*2+0] += ceil((20-delta_u)/2);
00849 }
00850 float delta_v = delta_max.val[i*2+1]-delta_min.val[i*2+1];
00851 if (delta_v<20) {
00852 delta_min.val[i*2+1] -= ceil((20-delta_v)/2);
00853 delta_max.val[i*2+1] += ceil((20-delta_v)/2);
00854 }
00855
00856
00857 r.u_min[i] = delta_min.val[i*2+0];
00858 r.u_max[i] = delta_max.val[i*2+0];
00859 r.v_min[i] = delta_min.val[i*2+1];
00860 r.v_max[i] = delta_max.val[i*2+1];
00861 }
00862 ranges.push_back(r);
00863 }
00864 }
00865
00866
00867 delete []delta_accu;
00868 }
00869
00870 void Matcher::createIndexVector (int32_t* m,int32_t n,vector<int32_t> *k,const int32_t &u_bin_num,const int32_t &v_bin_num) {
00871
00872
00873 int32_t step_size = sizeof(Matcher::maximum)/sizeof(int32_t);
00874
00875
00876 for (int32_t i=0; i<n; i++) {
00877
00878
00879 int32_t u = *(m+step_size*i+0);
00880 int32_t v = *(m+step_size*i+1);
00881 int32_t c = *(m+step_size*i+3);
00882
00883
00884 int32_t u_bin = min((int32_t)floor((float)u/(float)param.match_binsize),u_bin_num-1);
00885 int32_t v_bin = min((int32_t)floor((float)v/(float)param.match_binsize),v_bin_num-1);
00886
00887
00888 k[(c*v_bin_num+v_bin)*u_bin_num+u_bin].push_back(i);
00889 }
00890 }
00891
00892 inline void Matcher::findMatch (int32_t* m1,const int32_t &i1,int32_t* m2,const int32_t &step_size,vector<int32_t> *k2,
00893 const int32_t &u_bin_num,const int32_t &v_bin_num,const int32_t &stat_bin,
00894 int32_t& min_ind,int32_t stage,bool flow,bool use_prior,double u_,double v_) {
00895
00896
00897 min_ind = 0;
00898 double min_cost = 10000000;
00899 int32_t u1 = *(m1+step_size*i1+0);
00900 int32_t v1 = *(m1+step_size*i1+1);
00901 int32_t c = *(m1+step_size*i1+3);
00902 __m128i xmm1 = _mm_load_si128((__m128i*)(m1+step_size*i1+4));
00903 __m128i xmm2 = _mm_load_si128((__m128i*)(m1+step_size*i1+8));
00904
00905 float u_min,u_max,v_min,v_max;
00906
00907
00908 if (use_prior) {
00909 u_min = u1+ranges[stat_bin].u_min[stage];
00910 u_max = u1+ranges[stat_bin].u_max[stage];
00911 v_min = v1+ranges[stat_bin].v_min[stage];
00912 v_max = v1+ranges[stat_bin].v_max[stage];
00913
00914
00915 } else {
00916 u_min = u1-param.match_radius;
00917 u_max = u1+param.match_radius;
00918 v_min = v1-param.match_radius;
00919 v_max = v1+param.match_radius;
00920 }
00921
00922
00923 if (!flow) {
00924 v_min = v1-param.match_disp_tolerance;
00925 v_max = v1+param.match_disp_tolerance;
00926 }
00927
00928
00929 int32_t u_bin_min = min(max((int32_t)floor(u_min/(float)param.match_binsize),0),u_bin_num-1);
00930 int32_t u_bin_max = min(max((int32_t)floor(u_max/(float)param.match_binsize),0),u_bin_num-1);
00931 int32_t v_bin_min = min(max((int32_t)floor(v_min/(float)param.match_binsize),0),v_bin_num-1);
00932 int32_t v_bin_max = min(max((int32_t)floor(v_max/(float)param.match_binsize),0),v_bin_num-1);
00933
00934
00935 for (int32_t u_bin=u_bin_min; u_bin<=u_bin_max; u_bin++) {
00936 for (int32_t v_bin=v_bin_min; v_bin<=v_bin_max; v_bin++) {
00937 int32_t k2_ind = (c*v_bin_num+v_bin)*u_bin_num+u_bin;
00938 for (vector<int32_t>::const_iterator i2_it=k2[k2_ind].begin(); i2_it!=k2[k2_ind].end(); i2_it++) {
00939 int32_t u2 = *(m2+step_size*(*i2_it)+0);
00940 int32_t v2 = *(m2+step_size*(*i2_it)+1);
00941 if (u2>=u_min && u2<=u_max && v2>=v_min && v2<=v_max) {
00942 __m128i xmm3 = _mm_load_si128((__m128i*)(m2+step_size*(*i2_it)+4));
00943 __m128i xmm4 = _mm_load_si128((__m128i*)(m2+step_size*(*i2_it)+8));
00944 xmm3 = _mm_sad_epu8 (xmm1,xmm3);
00945 xmm4 = _mm_sad_epu8 (xmm2,xmm4);
00946 xmm4 = _mm_add_epi16(xmm3,xmm4);
00947 double cost = (double)(_mm_extract_epi16(xmm4,0)+_mm_extract_epi16(xmm4,4));
00948
00949 if (u_>=0 && v_>=0) {
00950 double du = (double)u2-u_;
00951 double dv = (double)v2-v_;
00952 double dist = sqrt(du*du+dv*dv);
00953 cost += 4*dist;
00954 }
00955
00956 if (cost<min_cost) {
00957 min_ind = *i2_it;
00958 min_cost = cost;
00959 }
00960 }
00961 }
00962 }
00963 }
00964 }
00965
00966 void Matcher::matching (int32_t *m1p,int32_t *m2p,int32_t *m1c,int32_t *m2c,
00967 int32_t n1p,int32_t n2p,int32_t n1c,int32_t n2c,
00968 vector<Matcher::p_match> &p_matched,int32_t method,bool use_prior,Matrix *Tr_delta) {
00969
00970
00971 int32_t step_size = sizeof(Matcher::maximum)/sizeof(int32_t);
00972
00973
00974 int32_t u_bin_num = (int32_t)ceil((float)dims_c[0]/(float)param.match_binsize);
00975 int32_t v_bin_num = (int32_t)ceil((float)dims_c[1]/(float)param.match_binsize);
00976 int32_t bin_num = 4*v_bin_num*u_bin_num;
00977
00978
00979 vector<int32_t> *k1p = new vector<int32_t>[bin_num];
00980 vector<int32_t> *k2p = new vector<int32_t>[bin_num];
00981 vector<int32_t> *k1c = new vector<int32_t>[bin_num];
00982 vector<int32_t> *k2c = new vector<int32_t>[bin_num];
00983
00984
00985 int32_t* M = (int32_t*)calloc(dims_c[0]*dims_c[1],sizeof(int32_t));
00986 int32_t i1p,i2p,i1c,i2c,i1c2,i1p2;
00987 int32_t u1p,v1p,u2p,v2p,u1c,v1c,u2c,v2c;
00988
00989 double t00,t01,t02,t03,t10,t11,t12,t13,t20,t21,t22,t23;
00990 if (Tr_delta) {
00991 t00 = Tr_delta->val[0][0];
00992 t01 = Tr_delta->val[0][1];
00993 t02 = Tr_delta->val[0][2];
00994 t03 = Tr_delta->val[0][3];
00995 t10 = Tr_delta->val[1][0];
00996 t11 = Tr_delta->val[1][1];
00997 t12 = Tr_delta->val[1][2];
00998 t13 = Tr_delta->val[1][3];
00999 t20 = Tr_delta->val[2][0];
01000 t21 = Tr_delta->val[2][1];
01001 t22 = Tr_delta->val[2][2];
01002 t23 = Tr_delta->val[2][3];
01003 }
01004
01006
01007 if (method==0) {
01008
01009
01010 createIndexVector(m1p,n1p,k1p,u_bin_num,v_bin_num);
01011 createIndexVector(m1c,n1c,k1c,u_bin_num,v_bin_num);
01012
01013
01014 for (i1c=0; i1c<n1c; i1c++) {
01015
01016
01017 u1c = *(m1c+step_size*i1c+0);
01018 v1c = *(m1c+step_size*i1c+1);
01019
01020
01021 int32_t u_bin = min((int32_t)floor((float)u1c/(float)param.match_binsize),u_bin_num-1);
01022 int32_t v_bin = min((int32_t)floor((float)v1c/(float)param.match_binsize),v_bin_num-1);
01023 int32_t stat_bin = v_bin*u_bin_num+u_bin;
01024
01025
01026 findMatch(m1c,i1c,m1p,step_size,k1p,u_bin_num,v_bin_num,stat_bin,i1p, 0,true,use_prior);
01027 findMatch(m1p,i1p,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c2,1,true,use_prior);
01028
01029
01030 if (i1c2==i1c) {
01031
01032
01033 u1p = *(m1p+step_size*i1p+0);
01034 v1p = *(m1p+step_size*i1p+1);
01035
01036
01037 if (*(M+getAddressOffsetImage(u1c,v1c,dims_c[0]))==0) {
01038 p_matched.push_back(Matcher::p_match(u1p,v1p,i1p,-1,-1,-1,u1c,v1c,i1c,-1,-1,-1));
01039 *(M+getAddressOffsetImage(u1c,v1c,dims_c[0])) = 1;
01040 }
01041 }
01042 }
01043
01045
01046 } else if (method==1) {
01047
01048
01049 createIndexVector(m1c,n1c,k1c,u_bin_num,v_bin_num);
01050 createIndexVector(m2c,n2c,k2c,u_bin_num,v_bin_num);
01051
01052
01053 for (i1c=0; i1c<n1c; i1c++) {
01054
01055
01056 u1c = *(m1c+step_size*i1c+0);
01057 v1c = *(m1c+step_size*i1c+1);
01058
01059
01060 int32_t u_bin = min((int32_t)floor((float)u1c/(float)param.match_binsize),u_bin_num-1);
01061 int32_t v_bin = min((int32_t)floor((float)v1c/(float)param.match_binsize),v_bin_num-1);
01062 int32_t stat_bin = v_bin*u_bin_num+u_bin;
01063
01064
01065 findMatch(m1c,i1c,m2c,step_size,k2c,u_bin_num,v_bin_num,stat_bin,i2c, 0,false,use_prior);
01066 findMatch(m2c,i2c,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c2,1,false,use_prior);
01067
01068
01069 if (i1c2==i1c) {
01070
01071
01072 u2c = *(m2c+step_size*i2c+0);
01073 v2c = *(m2c+step_size*i2c+1);
01074
01075
01076 if (u1c>=u2c) {
01077
01078
01079 if (*(M+getAddressOffsetImage(u1c,v1c,dims_c[0]))==0) {
01080 p_matched.push_back(Matcher::p_match(-1,-1,-1,-1,-1,-1,u1c,v1c,i1c,u2c,v2c,i2c));
01081 *(M+getAddressOffsetImage(u1c,v1c,dims_c[0])) = 1;
01082 }
01083 }
01084 }
01085 }
01086
01088
01089 } else {
01090
01091
01092 createIndexVector(m1p,n1p,k1p,u_bin_num,v_bin_num);
01093 createIndexVector(m2p,n2p,k2p,u_bin_num,v_bin_num);
01094 createIndexVector(m1c,n1c,k1c,u_bin_num,v_bin_num);
01095 createIndexVector(m2c,n2c,k2c,u_bin_num,v_bin_num);
01096
01097
01098 for (i1p=0; i1p<n1p; i1p++) {
01099
01100
01101 u1p = *(m1p+step_size*i1p+0);
01102 v1p = *(m1p+step_size*i1p+1);
01103
01104
01105 int32_t u_bin = min((int32_t)floor((float)u1p/(float)param.match_binsize),u_bin_num-1);
01106 int32_t v_bin = min((int32_t)floor((float)v1p/(float)param.match_binsize),v_bin_num-1);
01107 int32_t stat_bin = v_bin*u_bin_num+u_bin;
01108
01109
01110 findMatch(m1p,i1p,m2p,step_size,k2p,u_bin_num,v_bin_num,stat_bin,i2p, 0,false,use_prior);
01111
01112 u2p = *(m2p+step_size*i2p+0);
01113 v2p = *(m2p+step_size*i2p+1);
01114
01115 if (Tr_delta) {
01116
01117 double d = max((double)u1p-(double)u2p,1.0);
01118 double x1p = ((double)u1p-param.cu)*param.base/d;
01119 double y1p = ((double)v1p-param.cv)*param.base/d;
01120 double z1p = param.f*param.base/d;
01121
01122 double x2c = t00*x1p + t01*y1p + t02*z1p + t03 - param.base;
01123 double y2c = t10*x1p + t11*y1p + t12*z1p + t13;
01124 double z2c = t20*x1p + t21*y1p + t22*z1p + t23;
01125
01126 double u2c_ = param.f*x2c/z2c+param.cu;
01127 double v2c_ = param.f*y2c/z2c+param.cv;
01128
01129 findMatch(m2p,i2p,m2c,step_size,k2c,u_bin_num,v_bin_num,stat_bin,i2c, 1,true ,use_prior,u2c_,v2c_);
01130 } else {
01131 findMatch(m2p,i2p,m2c,step_size,k2c,u_bin_num,v_bin_num,stat_bin,i2c, 1,true ,use_prior);
01132 }
01133 findMatch(m2c,i2c,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c, 2,false,use_prior);
01134 if (Tr_delta)
01135 findMatch(m1c,i1c,m1p,step_size,k1p,u_bin_num,v_bin_num,stat_bin,i1p2,3,true ,use_prior,u1p,v1p);
01136 else
01137 findMatch(m1c,i1c,m1p,step_size,k1p,u_bin_num,v_bin_num,stat_bin,i1p2,3,true ,use_prior);
01138
01139
01140 if (i1p2==i1p) {
01141
01142
01143 u2c = *(m2c+step_size*i2c+0); v2c = *(m2c+step_size*i2c+1);
01144 u1c = *(m1c+step_size*i1c+0); v1c = *(m1c+step_size*i1c+1);
01145
01146
01147 if (u1p>=u2p && u1c>=u2c) {
01148
01149
01150 p_matched.push_back(Matcher::p_match(u1p,v1p,i1p,u2p,v2p,i2p,
01151 u1c,v1c,i1c,u2c,v2c,i2c));
01152 }
01153 }
01154 }
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 }
01199
01200
01201 free(M);
01202 delete []k1p;
01203 delete []k2p;
01204 delete []k1c;
01205 delete []k2c;
01206 }
01207
01208 void Matcher::removeOutliers (vector<Matcher::p_match> &p_matched,int32_t method) {
01209
01210
01211 if (p_matched.size()<=3)
01212 return;
01213
01214
01215 struct triangulateio in, out;
01216
01217
01218 in.numberofpoints = p_matched.size();
01219 in.pointlist = (float*)malloc(in.numberofpoints*2*sizeof(float));
01220 int32_t k=0;
01221
01222
01223
01224 vector<Matcher::p_match> p_matched_copy;
01225 vector<int32_t> num_support;
01226 for (vector<Matcher::p_match>::iterator it=p_matched.begin(); it!=p_matched.end(); it++) {
01227 p_matched_copy.push_back(*it);
01228 num_support.push_back(0);
01229 in.pointlist[k++] = it->u1c;
01230 in.pointlist[k++] = it->v1c;
01231 }
01232
01233
01234 in.numberofpointattributes = 0;
01235 in.pointattributelist = NULL;
01236 in.pointmarkerlist = NULL;
01237 in.numberofsegments = 0;
01238 in.numberofholes = 0;
01239 in.numberofregions = 0;
01240 in.regionlist = NULL;
01241
01242
01243 out.pointlist = NULL;
01244 out.pointattributelist = NULL;
01245 out.pointmarkerlist = NULL;
01246 out.trianglelist = NULL;
01247 out.triangleattributelist = NULL;
01248 out.neighborlist = NULL;
01249 out.segmentlist = NULL;
01250 out.segmentmarkerlist = NULL;
01251 out.edgelist = NULL;
01252 out.edgemarkerlist = NULL;
01253
01254
01255
01256 char parameters[] = "zQB";
01257 triangulate(parameters, &in, &out, NULL);
01258
01259
01260 for (int32_t i=0; i<out.numberoftriangles; i++) {
01261
01262
01263 int32_t p1 = out.trianglelist[i*3+0];
01264 int32_t p2 = out.trianglelist[i*3+1];
01265 int32_t p3 = out.trianglelist[i*3+2];
01266
01267
01268 if (method==0) {
01269
01270
01271 float p1_flow_u = p_matched_copy[p1].u1c-p_matched_copy[p1].u1p;
01272 float p1_flow_v = p_matched_copy[p1].v1c-p_matched_copy[p1].v1p;
01273
01274
01275 float p2_flow_u = p_matched_copy[p2].u1c-p_matched_copy[p2].u1p;
01276 float p2_flow_v = p_matched_copy[p2].v1c-p_matched_copy[p2].v1p;
01277
01278
01279 float p3_flow_u = p_matched_copy[p3].u1c-p_matched_copy[p3].u1p;
01280 float p3_flow_v = p_matched_copy[p3].v1c-p_matched_copy[p3].v1p;
01281
01282
01283 if (fabs(p1_flow_u-p2_flow_u)+fabs(p1_flow_v-p2_flow_v)<param.outlier_flow_tolerance) {
01284 num_support[p1]++;
01285 num_support[p2]++;
01286 }
01287
01288
01289 if (fabs(p2_flow_u-p3_flow_u)+fabs(p2_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01290 num_support[p2]++;
01291 num_support[p3]++;
01292 }
01293
01294
01295 if (fabs(p1_flow_u-p3_flow_u)+fabs(p1_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01296 num_support[p1]++;
01297 num_support[p3]++;
01298 }
01299
01300
01301 } else if (method==1) {
01302
01303
01304 float p1_disp = p_matched_copy[p1].u1c-p_matched_copy[p1].u2c;
01305
01306
01307 float p2_disp = p_matched_copy[p2].u1c-p_matched_copy[p2].u2c;
01308
01309
01310 float p3_disp = p_matched_copy[p3].u1c-p_matched_copy[p3].u2c;
01311
01312
01313 if (fabs(p1_disp-p2_disp)<param.outlier_disp_tolerance) {
01314 num_support[p1]++;
01315 num_support[p2]++;
01316 }
01317
01318
01319 if (fabs(p2_disp-p3_disp)<param.outlier_disp_tolerance) {
01320 num_support[p2]++;
01321 num_support[p3]++;
01322 }
01323
01324
01325 if (fabs(p1_disp-p3_disp)<param.outlier_disp_tolerance) {
01326 num_support[p1]++;
01327 num_support[p3]++;
01328 }
01329
01330
01331 } else {
01332
01333
01334 float p1_flow_u = p_matched_copy[p1].u1c-p_matched_copy[p1].u1p;
01335 float p1_flow_v = p_matched_copy[p1].v1c-p_matched_copy[p1].v1p;
01336 float p1_disp = p_matched_copy[p1].u1p-p_matched_copy[p1].u2p;
01337
01338
01339 float p2_flow_u = p_matched_copy[p2].u1c-p_matched_copy[p2].u1p;
01340 float p2_flow_v = p_matched_copy[p2].v1c-p_matched_copy[p2].v1p;
01341 float p2_disp = p_matched_copy[p2].u1p-p_matched_copy[p2].u2p;
01342
01343
01344 float p3_flow_u = p_matched_copy[p3].u1c-p_matched_copy[p3].u1p;
01345 float p3_flow_v = p_matched_copy[p3].v1c-p_matched_copy[p3].v1p;
01346 float p3_disp = p_matched_copy[p3].u1p-p_matched_copy[p3].u2p;
01347
01348
01349 if (fabs(p1_disp-p2_disp)<param.outlier_disp_tolerance && fabs(p1_flow_u-p2_flow_u)+fabs(p1_flow_v-p2_flow_v)<param.outlier_flow_tolerance) {
01350 num_support[p1]++;
01351 num_support[p2]++;
01352 }
01353
01354
01355 if (fabs(p2_disp-p3_disp)<param.outlier_disp_tolerance && fabs(p2_flow_u-p3_flow_u)+fabs(p2_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01356 num_support[p2]++;
01357 num_support[p3]++;
01358 }
01359
01360
01361 if (fabs(p1_disp-p3_disp)<param.outlier_disp_tolerance && fabs(p1_flow_u-p3_flow_u)+fabs(p1_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01362 num_support[p1]++;
01363 num_support[p3]++;
01364 }
01365 }
01366 }
01367
01368
01369 p_matched.clear();
01370 for (int i=0; i<in.numberofpoints; i++)
01371 if (num_support[i]>=4)
01372 p_matched.push_back(p_matched_copy[i]);
01373
01374
01375 free(in.pointlist);
01376 free(out.pointlist);
01377 free(out.trianglelist);
01378 }
01379
01380 bool Matcher::parabolicFitting(const uint8_t* I1_du,const uint8_t* I1_dv,const int32_t* dims1,
01381 const uint8_t* I2_du,const uint8_t* I2_dv,const int32_t* dims2,
01382 const float &u1,const float &v1,
01383 float &u2,float &v2,
01384 Matrix At,Matrix AtA,
01385 uint8_t* desc_buffer) {
01386
01387
01388 if (u2-3<margin || u2+3>dims2[0]-1-margin || v2-3<margin || v2+3>dims2[1]-1-margin)
01389 return false;
01390
01391
01392 __m128i xmm1,xmm2;
01393 computeSmallDescriptor(I1_du,I1_dv,dims1[2],(int32_t)u1,(int32_t)v1,desc_buffer);
01394 xmm1 = _mm_load_si128((__m128i*)(desc_buffer));
01395
01396
01397 int32_t cost[49];
01398 for (int32_t dv=0; dv<7; dv++) {
01399 for (int32_t du=0; du<7; du++) {
01400 computeSmallDescriptor(I2_du,I2_dv,dims2[2],(int32_t)u2+du-3,(int32_t)v2+dv-3,desc_buffer);
01401 xmm2 = _mm_load_si128((__m128i*)(desc_buffer));
01402 xmm2 = _mm_sad_epu8(xmm1,xmm2);
01403 cost[dv*7+du] = _mm_extract_epi16(xmm2,0)+_mm_extract_epi16(xmm2,4);
01404 }
01405 }
01406
01407
01408 int32_t min_ind = 0;
01409 int32_t min_cost = cost[0];
01410 for (int32_t i=1; i<49; i++) {
01411 if (cost[i]<min_cost) {
01412 min_ind = i;
01413 min_cost = cost[i];
01414 }
01415 }
01416
01417
01418 int32_t du = min_ind%7;
01419 int32_t dv = min_ind/7;
01420
01421
01422 if (du==0 || du==6 || dv==0 || dv==6)
01423 return false;
01424
01425
01426 Matrix c(9,1);
01427 for (int32_t i=-1; i<=+1; i++) {
01428 for (int32_t j=-1; j<=+1; j++) {
01429 int32_t cost_curr = cost[(dv+i)*7+(du+j)];
01430
01431
01432 c.val[(i+1)*3+(j+1)][0] = cost_curr;
01433 }
01434 }
01435 Matrix b = At*c;
01436 if (!b.solve(AtA))
01437 return false;
01438
01439
01440 float divisor = (b.val[2][0]*b.val[2][0]-4.0*b.val[0][0]*b.val[1][0]);
01441 if (fabs(divisor)<1e-8 || fabs(b.val[2][0])<1e-8)
01442 return false;
01443 float ddv = (2.0*b.val[0][0]*b.val[4][0]-b.val[2][0]*b.val[3][0])/divisor;
01444 float ddu = -(b.val[4][0]+2.0*b.val[1][0]*ddv)/b.val[2][0];
01445 if (fabs(ddu)>=1.0 || fabs(ddv)>=1.0)
01446 return false;
01447
01448
01449 u2 += (float)du-3.0+ddu;
01450 v2 += (float)dv-3.0+ddv;
01451
01452
01453 return true;
01454 }
01455
01456 void Matcher::relocateMinimum(const uint8_t* I1_du,const uint8_t* I1_dv,const int32_t* dims1,
01457 const uint8_t* I2_du,const uint8_t* I2_dv,const int32_t* dims2,
01458 const float &u1,const float &v1,
01459 float &u2,float &v2,
01460 uint8_t* desc_buffer) {
01461
01462
01463 if (u2-2<margin || u2+2>dims2[0]-1-margin || v2-2<margin || v2+2>dims2[1]-1-margin)
01464 return;
01465
01466
01467 __m128i xmm1,xmm2;
01468 computeSmallDescriptor(I1_du,I1_dv,dims1[2],(int32_t)u1,(int32_t)v1,desc_buffer);
01469 xmm1 = _mm_load_si128((__m128i*)(desc_buffer));
01470
01471
01472 int32_t cost[25];
01473 for (int32_t dv=0; dv<5; dv++) {
01474 for (int32_t du=0; du<5; du++) {
01475 computeSmallDescriptor(I2_du,I2_dv,dims2[2],(int32_t)u2+du-2,(int32_t)v2+dv-2,desc_buffer);
01476 xmm2 = _mm_load_si128((__m128i*)(desc_buffer));
01477 xmm2 = _mm_sad_epu8(xmm1,xmm2);
01478 cost[dv*5+du] = _mm_extract_epi16(xmm2,0)+_mm_extract_epi16(xmm2,4);
01479 }
01480 }
01481
01482
01483 int32_t min_ind = 0;
01484 int32_t min_cost = cost[0];
01485 for (int32_t i=1; i<25; i++) {
01486 if (cost[i]<min_cost) {
01487 min_ind = i;
01488 min_cost = cost[i];
01489 }
01490 }
01491
01492
01493 u2 += (float)(min_ind%5)-2.0;
01494 v2 += (float)(min_ind/5)-2.0;
01495 }
01496
01497 void Matcher::refinement (vector<Matcher::p_match> &p_matched,int32_t method) {
01498
01499
01500 uint8_t* desc_buffer = (uint8_t*)_mm_malloc(32*sizeof(uint8_t),16);
01501
01502
01503 vector<Matcher::p_match> p_matched_copy = p_matched;
01504 p_matched.clear();
01505
01506
01507 FLOAT A_data[9*6] = { 1, 1, 1,-1,-1, 1,
01508 0, 1, 0, 0,-1, 1,
01509 1, 1,-1, 1,-1, 1,
01510 1, 0, 0,-1, 0, 1,
01511 0, 0, 0, 0, 0, 1,
01512 1, 0, 0, 1, 0, 1,
01513 1, 1,-1,-1, 1, 1,
01514 0, 1, 0, 0, 1, 1,
01515 1, 1, 1, 1, 1, 1};
01516 Matrix A(9,6,A_data);
01517 Matrix At = ~A;
01518 Matrix AtA = At*A;
01519
01520 uint8_t* I1p_du_fit = I1p_du;
01521 uint8_t* I1p_dv_fit = I1p_dv;
01522 uint8_t* I2p_du_fit = I2p_du;
01523 uint8_t* I2p_dv_fit = I2p_dv;
01524 uint8_t* I1c_du_fit = I1c_du;
01525 uint8_t* I1c_dv_fit = I1c_dv;
01526 uint8_t* I2c_du_fit = I2c_du;
01527 uint8_t* I2c_dv_fit = I2c_dv;
01528 if (param.half_resolution) {
01529 I1p_du_fit = I1p_du_full;
01530 I1p_dv_fit = I1p_dv_full;
01531 I2p_du_fit = I2p_du_full;
01532 I2p_dv_fit = I2p_dv_full;
01533 I1c_du_fit = I1c_du_full;
01534 I1c_dv_fit = I1c_dv_full;
01535 I2c_du_fit = I2c_du_full;
01536 I2c_dv_fit = I2c_dv_full;
01537 }
01538
01539
01540 for (vector<Matcher::p_match>::iterator it=p_matched_copy.begin(); it!=p_matched_copy.end(); it++) {
01541
01542
01543 if (method==0 || method==2) {
01544 if (param.refinement==2) {
01545 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I1p_du_fit,I1p_dv_fit,dims_p,
01546 it->u1c,it->v1c,it->u1p,it->v1p,At,AtA,desc_buffer))
01547 continue;
01548 } else {
01549 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I1p_du_fit,I1p_dv_fit,dims_p,
01550 it->u1c,it->v1c,it->u1p,it->v1p,desc_buffer);
01551 }
01552 }
01553
01554
01555 if (method==1 || method==2) {
01556 if (param.refinement==2) {
01557 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I2c_du_fit,I2c_dv_fit,dims_c,
01558 it->u1c,it->v1c,it->u2c,it->v2c,At,AtA,desc_buffer))
01559 continue;
01560 } else {
01561 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I2c_du_fit,I2c_dv_fit,dims_c,
01562 it->u1c,it->v1c,it->u2c,it->v2c,desc_buffer);
01563 }
01564 }
01565
01566
01567 if (method==2) {
01568 if (param.refinement==2) {
01569 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I2p_du_fit,I2p_dv_fit,dims_p,
01570 it->u1c,it->v1c,it->u2p,it->v2p,At,AtA,desc_buffer))
01571 continue;
01572 } else {
01573 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I2p_du_fit,I2p_dv_fit,dims_p,
01574 it->u1c,it->v1c,it->u2p,it->v2p,desc_buffer);
01575 }
01576 }
01577
01578
01579 p_matched.push_back(*it);
01580 }
01581
01582
01583 _mm_free(desc_buffer);
01584 }
01585
01586 float Matcher::mean(const uint8_t* I,const int32_t &bpl,const int32_t &u_min,const int32_t &u_max,const int32_t &v_min,const int32_t &v_max) {
01587 float mean = 0;
01588 for (int32_t v=v_min; v<=v_max; v++)
01589 for (int32_t u=u_min; u<=u_max; u++)
01590 mean += (float)*(I+getAddressOffsetImage(u,v,bpl));
01591 return
01592 mean /= (float)((u_max-u_min+1)*(v_max-v_min+1));
01593 }
01594