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) {
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);
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);
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);
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 delta_curr.val[0] = it->u1p - it->u1c;
00770 delta_curr.val[1] = it->v1p - it->v1c;
00771 delta_curr.val[2] = it->u2p - it->u1p;
00772 delta_curr.val[3] = 0;
00773 delta_curr.val[4] = it->u2c - it->u2p;
00774 delta_curr.val[5] = it->v2c - it->v2p;
00775 delta_curr.val[6] = it->u1c - it->u2c;
00776 delta_curr.val[7] = 0;
00777 }
00778
00779
00780 int32_t u_bin_min = min(max((int32_t)floor(it->u1c/(float)param.match_binsize)-1,0),u_bin_num-1);
00781 int32_t u_bin_max = min(max((int32_t)floor(it->u1c/(float)param.match_binsize)+1,0),u_bin_num-1);
00782 int32_t v_bin_min = min(max((int32_t)floor(it->v1c/(float)param.match_binsize)-1,0),v_bin_num-1);
00783 int32_t v_bin_max = min(max((int32_t)floor(it->v1c/(float)param.match_binsize)+1,0),v_bin_num-1);
00784
00785
00786 for (int32_t v_bin=v_bin_min; v_bin<=v_bin_max; v_bin++)
00787 for (int32_t u_bin=u_bin_min; u_bin<=u_bin_max; u_bin++)
00788 delta_accu[v_bin*u_bin_num+u_bin].push_back(delta_curr);
00789 }
00790
00791
00792 ranges.clear();
00793
00794
00795 for (int32_t v_bin=0; v_bin<v_bin_num; v_bin++) {
00796 for (int32_t u_bin=0; u_bin<u_bin_num; u_bin++) {
00797
00798
00799 delta delta_min(-param.match_radius);
00800 delta delta_max(+param.match_radius);
00801
00802
00803 if (delta_accu[v_bin*u_bin_num+u_bin].size()>0) {
00804
00805
00806 delta_min = delta(+1000000);
00807 delta_max = delta(-1000000);
00808
00809
00810 for (vector<Matcher::delta>::iterator it=delta_accu[v_bin*u_bin_num+u_bin].begin();
00811 it!=delta_accu[v_bin*u_bin_num+u_bin].end(); it++) {
00812 for (int32_t i=0; i<num_stages*2; i++) {
00813 if (it->val[i]<delta_min.val[i]) delta_min.val[i] = it->val[i];
00814 if (it->val[i]>delta_max.val[i]) delta_max.val[i] = it->val[i];
00815 }
00816 }
00817 }
00818
00819
00820 range r;
00821 for (int32_t i=0; i<num_stages; i++) {
00822
00823
00824 float delta_u = delta_max.val[i*2+0]-delta_min.val[i*2+0];
00825 if (delta_u<20) {
00826 delta_min.val[i*2+0] -= ceil((20-delta_u)/2);
00827 delta_max.val[i*2+0] += ceil((20-delta_u)/2);
00828 }
00829 float delta_v = delta_max.val[i*2+1]-delta_min.val[i*2+1];
00830 if (delta_v<20) {
00831 delta_min.val[i*2+1] -= ceil((20-delta_v)/2);
00832 delta_max.val[i*2+1] += ceil((20-delta_v)/2);
00833 }
00834
00835
00836 r.u_min[i] = delta_min.val[i*2+0];
00837 r.u_max[i] = delta_max.val[i*2+0];
00838 r.v_min[i] = delta_min.val[i*2+1];
00839 r.v_max[i] = delta_max.val[i*2+1];
00840 }
00841 ranges.push_back(r);
00842 }
00843 }
00844
00845
00846 delete []delta_accu;
00847 }
00848
00849 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) {
00850
00851
00852 int32_t step_size = sizeof(Matcher::maximum)/sizeof(int32_t);
00853
00854
00855 for (int32_t i=0; i<n; i++) {
00856
00857
00858 int32_t u = *(m+step_size*i+0);
00859 int32_t v = *(m+step_size*i+1);
00860 int32_t c = *(m+step_size*i+3);
00861
00862
00863 int32_t u_bin = min((int32_t)floor((float)u/(float)param.match_binsize),u_bin_num-1);
00864 int32_t v_bin = min((int32_t)floor((float)v/(float)param.match_binsize),v_bin_num-1);
00865
00866
00867 k[(c*v_bin_num+v_bin)*u_bin_num+u_bin].push_back(i);
00868 }
00869 }
00870
00871 inline void Matcher::findMatch (int32_t* m1,const int32_t &i1,int32_t* m2,const int32_t &step_size,vector<int32_t> *k2,
00872 const int32_t &u_bin_num,const int32_t &v_bin_num,const int32_t &stat_bin,
00873 int32_t& min_ind,int32_t stage,bool flow,bool use_prior) {
00874
00875
00876 min_ind = 0;
00877 int32_t min_cost = 10000000;
00878 int32_t u1 = *(m1+step_size*i1+0);
00879 int32_t v1 = *(m1+step_size*i1+1);
00880 int32_t c = *(m1+step_size*i1+3);
00881 __m128i xmm1 = _mm_load_si128((__m128i*)(m1+step_size*i1+4));
00882 __m128i xmm2 = _mm_load_si128((__m128i*)(m1+step_size*i1+8));
00883
00884 float u_min,u_max,v_min,v_max;
00885
00886
00887 if (use_prior) {
00888 u_min = u1+ranges[stat_bin].u_min[stage];
00889 u_max = u1+ranges[stat_bin].u_max[stage];
00890 v_min = v1+ranges[stat_bin].v_min[stage];
00891 v_max = v1+ranges[stat_bin].v_max[stage];
00892
00893
00894 } else {
00895 u_min = u1-param.match_radius;
00896 u_max = u1+param.match_radius;
00897 v_min = v1-param.match_radius;
00898 v_max = v1+param.match_radius;
00899 }
00900
00901
00902 if (!flow) {
00903 v_min = v1-param.match_disp_tolerance;
00904 v_max = v1+param.match_disp_tolerance;
00905 }
00906
00907
00908 int32_t u_bin_min = min(max((int32_t)floor(u_min/(float)param.match_binsize),0),u_bin_num-1);
00909 int32_t u_bin_max = min(max((int32_t)floor(u_max/(float)param.match_binsize),0),u_bin_num-1);
00910 int32_t v_bin_min = min(max((int32_t)floor(v_min/(float)param.match_binsize),0),v_bin_num-1);
00911 int32_t v_bin_max = min(max((int32_t)floor(v_max/(float)param.match_binsize),0),v_bin_num-1);
00912
00913
00914 for (int32_t u_bin=u_bin_min; u_bin<=u_bin_max; u_bin++) {
00915 for (int32_t v_bin=v_bin_min; v_bin<=v_bin_max; v_bin++) {
00916 int32_t k2_ind = (c*v_bin_num+v_bin)*u_bin_num+u_bin;
00917 for (vector<int32_t>::const_iterator i2_it=k2[k2_ind].begin(); i2_it!=k2[k2_ind].end(); i2_it++) {
00918 int32_t u2 = *(m2+step_size*(*i2_it)+0);
00919 int32_t v2 = *(m2+step_size*(*i2_it)+1);
00920 if (u2>=u_min && u2<=u_max && v2>=v_min && v2<=v_max) {
00921 __m128i xmm3 = _mm_load_si128((__m128i*)(m2+step_size*(*i2_it)+4));
00922 __m128i xmm4 = _mm_load_si128((__m128i*)(m2+step_size*(*i2_it)+8));
00923 xmm3 = _mm_sad_epu8 (xmm1,xmm3);
00924 xmm4 = _mm_sad_epu8 (xmm2,xmm4);
00925 xmm4 = _mm_add_epi16(xmm3,xmm4);
00926 int32_t cost = _mm_extract_epi16(xmm4,0)+_mm_extract_epi16(xmm4,4);
00927 if (cost<min_cost) {
00928 min_ind = *i2_it;
00929 min_cost = cost;
00930 }
00931 }
00932 }
00933 }
00934 }
00935 }
00936
00937 void Matcher::matching (int32_t *m1p,int32_t *m2p,int32_t *m1c,int32_t *m2c,
00938 int32_t n1p,int32_t n2p,int32_t n1c,int32_t n2c,
00939 vector<Matcher::p_match> &p_matched,int32_t method,bool use_prior) {
00940
00941
00942 int32_t step_size = sizeof(Matcher::maximum)/sizeof(int32_t);
00943
00944
00945 int32_t u_bin_num = (int32_t)ceil((float)dims_c[0]/(float)param.match_binsize);
00946 int32_t v_bin_num = (int32_t)ceil((float)dims_c[1]/(float)param.match_binsize);
00947 int32_t bin_num = 4*v_bin_num*u_bin_num;
00948
00949
00950 vector<int32_t> *k1p = new vector<int32_t>[bin_num];
00951 vector<int32_t> *k2p = new vector<int32_t>[bin_num];
00952 vector<int32_t> *k1c = new vector<int32_t>[bin_num];
00953 vector<int32_t> *k2c = new vector<int32_t>[bin_num];
00954
00955
00956 int32_t* M = (int32_t*)calloc(dims_c[0]*dims_c[1],sizeof(int32_t));
00957 int32_t i1p,i2p,i1c,i2c,i1c2;
00958 int32_t u1p,v1p,u2p,v2p,u1c,v1c,u2c,v2c;
00959
00961
00962 if (method==0) {
00963
00964
00965 createIndexVector(m1p,n1p,k1p,u_bin_num,v_bin_num);
00966 createIndexVector(m1c,n1c,k1c,u_bin_num,v_bin_num);
00967
00968
00969 for (i1c=0; i1c<n1c; i1c++) {
00970
00971
00972 u1c = *(m1c+step_size*i1c+0);
00973 v1c = *(m1c+step_size*i1c+1);
00974
00975
00976 int32_t u_bin = min((int32_t)floor((float)u1c/(float)param.match_binsize),u_bin_num-1);
00977 int32_t v_bin = min((int32_t)floor((float)v1c/(float)param.match_binsize),v_bin_num-1);
00978 int32_t stat_bin = v_bin*u_bin_num+u_bin;
00979
00980
00981 findMatch(m1c,i1c,m1p,step_size,k1p,u_bin_num,v_bin_num,stat_bin,i1p, 0,true,use_prior);
00982 findMatch(m1p,i1p,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c2,1,true,use_prior);
00983
00984
00985 if (i1c2==i1c) {
00986
00987
00988 u1p = *(m1p+step_size*i1p+0);
00989 v1p = *(m1p+step_size*i1p+1);
00990
00991
00992 if (*(M+getAddressOffsetImage(u1c,v1c,dims_c[0]))==0) {
00993 p_matched.push_back(Matcher::p_match(u1p,v1p,i1p,-1,-1,-1,u1c,v1c,i1c,-1,-1,-1));
00994 *(M+getAddressOffsetImage(u1c,v1c,dims_c[0])) = 1;
00995 }
00996 }
00997 }
00998
01000
01001 } else if (method==1) {
01002
01003
01004 createIndexVector(m1c,n1c,k1c,u_bin_num,v_bin_num);
01005 createIndexVector(m2c,n2c,k2c,u_bin_num,v_bin_num);
01006
01007
01008 for (i1c=0; i1c<n1c; i1c++) {
01009
01010
01011 u1c = *(m1c+step_size*i1c+0);
01012 v1c = *(m1c+step_size*i1c+1);
01013
01014
01015 int32_t u_bin = min((int32_t)floor((float)u1c/(float)param.match_binsize),u_bin_num-1);
01016 int32_t v_bin = min((int32_t)floor((float)v1c/(float)param.match_binsize),v_bin_num-1);
01017 int32_t stat_bin = v_bin*u_bin_num+u_bin;
01018
01019
01020 findMatch(m1c,i1c,m2c,step_size,k2c,u_bin_num,v_bin_num,stat_bin,i2c, 0,false,use_prior);
01021 findMatch(m2c,i2c,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c2,1,false,use_prior);
01022
01023
01024 if (i1c2==i1c) {
01025
01026
01027 u2c = *(m2c+step_size*i2c+0);
01028 v2c = *(m2c+step_size*i2c+1);
01029
01030
01031 if (u1c>=u2c) {
01032
01033
01034 if (*(M+getAddressOffsetImage(u1c,v1c,dims_c[0]))==0) {
01035 p_matched.push_back(Matcher::p_match(-1,-1,-1,-1,-1,-1,u1c,v1c,i1c,u2c,v2c,i2c));
01036 *(M+getAddressOffsetImage(u1c,v1c,dims_c[0])) = 1;
01037 }
01038 }
01039 }
01040 }
01041
01043
01044 } else {
01045
01046
01047 createIndexVector(m1p,n1p,k1p,u_bin_num,v_bin_num);
01048 createIndexVector(m2p,n2p,k2p,u_bin_num,v_bin_num);
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,m1p,step_size,k1p,u_bin_num,v_bin_num,stat_bin,i1p, 0,true ,use_prior);
01066 findMatch(m1p,i1p,m2p,step_size,k2p,u_bin_num,v_bin_num,stat_bin,i2p, 1,false,use_prior);
01067 findMatch(m2p,i2p,m2c,step_size,k2c,u_bin_num,v_bin_num,stat_bin,i2c, 2,true ,use_prior);
01068 findMatch(m2c,i2c,m1c,step_size,k1c,u_bin_num,v_bin_num,stat_bin,i1c2,3,false,use_prior);
01069
01070
01071 if (i1c2==i1c) {
01072
01073
01074 u1p = *(m1p+step_size*i1p+0); v1p = *(m1p+step_size*i1p+1);
01075 u2p = *(m2p+step_size*i2p+0); v2p = *(m2p+step_size*i2p+1);
01076 u2c = *(m2c+step_size*i2c+0); v2c = *(m2c+step_size*i2c+1);
01077
01078
01079 if (u1p>=u2p && u1c>=u2c) {
01080
01081
01082 if (*(M+getAddressOffsetImage(u1c,v1c,dims_c[0]))==0) {
01083 p_matched.push_back(Matcher::p_match(u1p,v1p,i1p,u2p,v2p,i2p,
01084 u1c,v1c,i1c,u2c,v2c,i2c));
01085 *(M+getAddressOffsetImage(u1c,v1c,dims_c[0])) = 1;
01086 }
01087
01088 }
01089 }
01090 }
01091 }
01092
01093
01094 free(M);
01095 delete []k1p;
01096 delete []k2p;
01097 delete []k1c;
01098 delete []k2c;
01099 }
01100
01101 void Matcher::removeOutliers (vector<Matcher::p_match> &p_matched,int32_t method) {
01102
01103
01104 if (p_matched.size()<=3)
01105 return;
01106
01107
01108 struct triangulateio in, out;
01109
01110
01111 in.numberofpoints = p_matched.size();
01112 in.pointlist = (float*)malloc(in.numberofpoints*2*sizeof(float));
01113 int32_t k=0;
01114
01115
01116
01117 vector<Matcher::p_match> p_matched_copy;
01118 vector<int32_t> num_support;
01119 for (vector<Matcher::p_match>::iterator it=p_matched.begin(); it!=p_matched.end(); it++) {
01120 p_matched_copy.push_back(*it);
01121 num_support.push_back(0);
01122 in.pointlist[k++] = it->u1c;
01123 in.pointlist[k++] = it->v1c;
01124 }
01125
01126
01127 in.numberofpointattributes = 0;
01128 in.pointattributelist = NULL;
01129 in.pointmarkerlist = NULL;
01130 in.numberofsegments = 0;
01131 in.numberofholes = 0;
01132 in.numberofregions = 0;
01133 in.regionlist = NULL;
01134
01135
01136 out.pointlist = NULL;
01137 out.pointattributelist = NULL;
01138 out.pointmarkerlist = NULL;
01139 out.trianglelist = NULL;
01140 out.triangleattributelist = NULL;
01141 out.neighborlist = NULL;
01142 out.segmentlist = NULL;
01143 out.segmentmarkerlist = NULL;
01144 out.edgelist = NULL;
01145 out.edgemarkerlist = NULL;
01146
01147
01148
01149 char parameters[] = "zQB";
01150 triangulate(parameters, &in, &out, NULL);
01151
01152
01153 for (int32_t i=0; i<out.numberoftriangles; i++) {
01154
01155
01156 int32_t p1 = out.trianglelist[i*3+0];
01157 int32_t p2 = out.trianglelist[i*3+1];
01158 int32_t p3 = out.trianglelist[i*3+2];
01159
01160
01161 if (method==0) {
01162
01163
01164 float p1_flow_u = p_matched_copy[p1].u1c-p_matched_copy[p1].u1p;
01165 float p1_flow_v = p_matched_copy[p1].v1c-p_matched_copy[p1].v1p;
01166
01167
01168 float p2_flow_u = p_matched_copy[p2].u1c-p_matched_copy[p2].u1p;
01169 float p2_flow_v = p_matched_copy[p2].v1c-p_matched_copy[p2].v1p;
01170
01171
01172 float p3_flow_u = p_matched_copy[p3].u1c-p_matched_copy[p3].u1p;
01173 float p3_flow_v = p_matched_copy[p3].v1c-p_matched_copy[p3].v1p;
01174
01175
01176 if (fabs(p1_flow_u-p2_flow_u)+fabs(p1_flow_v-p2_flow_v)<param.outlier_flow_tolerance) {
01177 num_support[p1]++;
01178 num_support[p2]++;
01179 }
01180
01181
01182 if (fabs(p2_flow_u-p3_flow_u)+fabs(p2_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01183 num_support[p2]++;
01184 num_support[p3]++;
01185 }
01186
01187
01188 if (fabs(p1_flow_u-p3_flow_u)+fabs(p1_flow_v-p3_flow_v)<param.outlier_flow_tolerance) {
01189 num_support[p1]++;
01190 num_support[p3]++;
01191 }
01192
01193
01194 } else if (method==1) {
01195
01196
01197 float p1_disp = p_matched_copy[p1].u1c-p_matched_copy[p1].u2c;
01198
01199
01200 float p2_disp = p_matched_copy[p2].u1c-p_matched_copy[p2].u2c;
01201
01202
01203 float p3_disp = p_matched_copy[p3].u1c-p_matched_copy[p3].u2c;
01204
01205
01206 if (fabs(p1_disp-p2_disp)<param.outlier_disp_tolerance) {
01207 num_support[p1]++;
01208 num_support[p2]++;
01209 }
01210
01211
01212 if (fabs(p2_disp-p3_disp)<param.outlier_disp_tolerance) {
01213 num_support[p2]++;
01214 num_support[p3]++;
01215 }
01216
01217
01218 if (fabs(p1_disp-p3_disp)<param.outlier_disp_tolerance) {
01219 num_support[p1]++;
01220 num_support[p3]++;
01221 }
01222
01223
01224 } else {
01225
01226
01227 float p1_flow_u = p_matched_copy[p1].u1c-p_matched_copy[p1].u1p;
01228 float p1_flow_v = p_matched_copy[p1].v1c-p_matched_copy[p1].v1p;
01229 float p1_disp = p_matched_copy[p1].u1p-p_matched_copy[p1].u2p;
01230
01231
01232 float p2_flow_u = p_matched_copy[p2].u1c-p_matched_copy[p2].u1p;
01233 float p2_flow_v = p_matched_copy[p2].v1c-p_matched_copy[p2].v1p;
01234 float p2_disp = p_matched_copy[p2].u1p-p_matched_copy[p2].u2p;
01235
01236
01237 float p3_flow_u = p_matched_copy[p3].u1c-p_matched_copy[p3].u1p;
01238 float p3_flow_v = p_matched_copy[p3].v1c-p_matched_copy[p3].v1p;
01239 float p3_disp = p_matched_copy[p3].u1p-p_matched_copy[p3].u2p;
01240
01241
01242 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) {
01243 num_support[p1]++;
01244 num_support[p2]++;
01245 }
01246
01247
01248 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) {
01249 num_support[p2]++;
01250 num_support[p3]++;
01251 }
01252
01253
01254 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) {
01255 num_support[p1]++;
01256 num_support[p3]++;
01257 }
01258 }
01259 }
01260
01261
01262 p_matched.clear();
01263 for (int i=0; i<in.numberofpoints; i++)
01264 if (num_support[i]>=4)
01265 p_matched.push_back(p_matched_copy[i]);
01266
01267
01268 free(in.pointlist);
01269 free(out.pointlist);
01270 free(out.trianglelist);
01271 }
01272
01273 bool Matcher::parabolicFitting(const uint8_t* I1_du,const uint8_t* I1_dv,const int32_t* dims1,
01274 const uint8_t* I2_du,const uint8_t* I2_dv,const int32_t* dims2,
01275 const float &u1,const float &v1,
01276 float &u2,float &v2,
01277 Matrix At,Matrix AtA,
01278 uint8_t* desc_buffer) {
01279
01280
01281 if (u2-3<margin || u2+3>dims2[0]-1-margin || v2-3<margin || v2+3>dims2[1]-1-margin)
01282 return false;
01283
01284
01285 __m128i xmm1,xmm2;
01286 computeSmallDescriptor(I1_du,I1_dv,dims1[2],(int32_t)u1,(int32_t)v1,desc_buffer);
01287 xmm1 = _mm_load_si128((__m128i*)(desc_buffer));
01288
01289
01290 int32_t cost[49];
01291 for (int32_t dv=0; dv<7; dv++) {
01292 for (int32_t du=0; du<7; du++) {
01293 computeSmallDescriptor(I2_du,I2_dv,dims2[2],(int32_t)u2+du-3,(int32_t)v2+dv-3,desc_buffer);
01294 xmm2 = _mm_load_si128((__m128i*)(desc_buffer));
01295 xmm2 = _mm_sad_epu8(xmm1,xmm2);
01296 cost[dv*7+du] = _mm_extract_epi16(xmm2,0)+_mm_extract_epi16(xmm2,4);
01297 }
01298 }
01299
01300
01301 int32_t min_ind = 0;
01302 int32_t min_cost = cost[0];
01303 for (int32_t i=1; i<49; i++) {
01304 if (cost[i]<min_cost) {
01305 min_ind = i;
01306 min_cost = cost[i];
01307 }
01308 }
01309
01310
01311 int32_t du = min_ind%7;
01312 int32_t dv = min_ind/7;
01313
01314
01315 if (du==0 || du==6 || dv==0 || dv==6)
01316 return false;
01317
01318
01319 Matrix c(9,1);
01320 for (int32_t i=-1; i<=+1; i++)
01321 for (int32_t j=-1; j<=+1; j++)
01322 c.val[(i+1)*3+(j+1)][0] = cost[(dv+i)*7+(du+j)];
01323 Matrix b = At*c;
01324 if (!b.solve(AtA))
01325 return false;
01326
01327
01328 float divisor = (b.val[2][0]*b.val[2][0]-4.0*b.val[0][0]*b.val[1][0]);
01329 if (fabs(divisor)<1e-8 || fabs(b.val[2][0])<1e-8)
01330 return false;
01331 float ddv = (2.0*b.val[0][0]*b.val[4][0]-b.val[2][0]*b.val[3][0])/divisor;
01332 float ddu = -(b.val[4][0]+2.0*b.val[1][0]*ddv)/b.val[2][0];
01333 if (fabs(ddu)>=1.0 || fabs(ddv)>=1.0)
01334 return false;
01335
01336
01337 u2 += (float)du-3.0+ddu;
01338 v2 += (float)dv-3.0+ddv;
01339
01340
01341 return true;
01342 }
01343
01344 void Matcher::relocateMinimum(const uint8_t* I1_du,const uint8_t* I1_dv,const int32_t* dims1,
01345 const uint8_t* I2_du,const uint8_t* I2_dv,const int32_t* dims2,
01346 const float &u1,const float &v1,
01347 float &u2,float &v2,
01348 uint8_t* desc_buffer) {
01349
01350
01351 if (u2-2<margin || u2+2>dims2[0]-1-margin || v2-2<margin || v2+2>dims2[1]-1-margin)
01352 return;
01353
01354
01355 __m128i xmm1,xmm2;
01356 computeSmallDescriptor(I1_du,I1_dv,dims1[2],(int32_t)u1,(int32_t)v1,desc_buffer);
01357 xmm1 = _mm_load_si128((__m128i*)(desc_buffer));
01358
01359
01360 int32_t cost[25];
01361 for (int32_t dv=0; dv<5; dv++) {
01362 for (int32_t du=0; du<5; du++) {
01363 computeSmallDescriptor(I2_du,I2_dv,dims2[2],(int32_t)u2+du-2,(int32_t)v2+dv-2,desc_buffer);
01364 xmm2 = _mm_load_si128((__m128i*)(desc_buffer));
01365 xmm2 = _mm_sad_epu8(xmm1,xmm2);
01366 cost[dv*5+du] = _mm_extract_epi16(xmm2,0)+_mm_extract_epi16(xmm2,4);
01367 }
01368 }
01369
01370
01371 int32_t min_ind = 0;
01372 int32_t min_cost = cost[0];
01373 for (int32_t i=1; i<25; i++) {
01374 if (cost[i]<min_cost) {
01375 min_ind = i;
01376 min_cost = cost[i];
01377 }
01378 }
01379
01380
01381 u2 += (float)(min_ind%5)-2.0;
01382 v2 += (float)(min_ind/5)-2.0;
01383 }
01384
01385 void Matcher::refinement (vector<Matcher::p_match> &p_matched,int32_t method) {
01386
01387
01388 uint8_t* desc_buffer = (uint8_t*)_mm_malloc(32*sizeof(uint8_t),16);
01389
01390
01391 vector<Matcher::p_match> p_matched_copy = p_matched;
01392 p_matched.clear();
01393
01394
01395 FLOAT A_data[9*6] = { 1, 1, 1,-1,-1, 1,
01396 0, 1, 0, 0,-1, 1,
01397 1, 1,-1, 1,-1, 1,
01398 1, 0, 0,-1, 0, 1,
01399 0, 0, 0, 0, 0, 1,
01400 1, 0, 0, 1, 0, 1,
01401 1, 1,-1,-1, 1, 1,
01402 0, 1, 0, 0, 1, 1,
01403 1, 1, 1, 1, 1, 1};
01404 Matrix A(9,6,A_data);
01405 Matrix At = ~A;
01406 Matrix AtA = At*A;
01407
01408 uint8_t* I1p_du_fit = I1p_du;
01409 uint8_t* I1p_dv_fit = I1p_dv;
01410 uint8_t* I2p_du_fit = I2p_du;
01411 uint8_t* I2p_dv_fit = I2p_dv;
01412 uint8_t* I1c_du_fit = I1c_du;
01413 uint8_t* I1c_dv_fit = I1c_dv;
01414 uint8_t* I2c_du_fit = I2c_du;
01415 uint8_t* I2c_dv_fit = I2c_dv;
01416 if (param.half_resolution) {
01417 I1p_du_fit = I1p_du_full;
01418 I1p_dv_fit = I1p_dv_full;
01419 I2p_du_fit = I2p_du_full;
01420 I2p_dv_fit = I2p_dv_full;
01421 I1c_du_fit = I1c_du_full;
01422 I1c_dv_fit = I1c_dv_full;
01423 I2c_du_fit = I2c_du_full;
01424 I2c_dv_fit = I2c_dv_full;
01425 }
01426
01427
01428 for (vector<Matcher::p_match>::iterator it=p_matched_copy.begin(); it!=p_matched_copy.end(); it++) {
01429
01430
01431 if (method==0 || method==2) {
01432 if (param.refinement==2) {
01433 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I1p_du_fit,I1p_dv_fit,dims_p,
01434 it->u1c,it->v1c,it->u1p,it->v1p,At,AtA,desc_buffer))
01435 continue;
01436 } else {
01437 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I1p_du_fit,I1p_dv_fit,dims_p,
01438 it->u1c,it->v1c,it->u1p,it->v1p,desc_buffer);
01439 }
01440 }
01441
01442
01443 if (method==1 || method==2) {
01444 if (param.refinement==2) {
01445 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I2c_du_fit,I2c_dv_fit,dims_c,
01446 it->u1c,it->v1c,it->u2c,it->v2c,At,AtA,desc_buffer))
01447 continue;
01448 } else {
01449 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I2c_du_fit,I2c_dv_fit,dims_c,
01450 it->u1c,it->v1c,it->u2c,it->v2c,desc_buffer);
01451 }
01452 }
01453
01454
01455 if (method==2) {
01456 if (param.refinement==2) {
01457 if (!parabolicFitting(I1c_du_fit,I1c_dv_fit,dims_c,I2p_du_fit,I2p_dv_fit,dims_p,
01458 it->u1c,it->v1c,it->u2p,it->v2p,At,AtA,desc_buffer))
01459 continue;
01460 } else {
01461 relocateMinimum(I1c_du_fit,I1c_dv_fit,dims_c,I2p_du_fit,I2p_dv_fit,dims_p,
01462 it->u1c,it->v1c,it->u2p,it->v2p,desc_buffer);
01463 }
01464 }
01465
01466
01467 p_matched.push_back(*it);
01468 }
01469
01470
01471 _mm_free(desc_buffer);
01472 }
01473
01474 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) {
01475 float mean;
01476 for (int32_t v=v_min; v<=v_max; v++)
01477 for (int32_t u=u_min; u<=u_max; u++)
01478 mean += (float)*(I+getAddressOffsetImage(u,v,bpl));
01479 return
01480 mean /= (float)((u_max-u_min+1)*(v_max-v_min+1));
01481 }