void vtransform(Size2D size, const typename Op::type * src0Base, ptrdiff_t src0Stride, const typename Op::type * src1Base, ptrdiff_t src1Stride, typename Op::type * dstBase, ptrdiff_t dstStride, const Op & op) { typedef typename Op::type type; typedef typename VecTraits<type>::vec128 vec128; typedef typename VecTraits<type>::vec64 vec64; if (src0Stride == src1Stride && src0Stride == dstStride && src0Stride == (ptrdiff_t)(size.width * sizeof(type))) { size.width *= size.height; size.height = 1; } const size_t step_base = 32 / sizeof(type); size_t roiw_base = size.width >= (step_base - 1) ? size.width - step_base + 1 : 0; const size_t step_tail = 8 / sizeof(type); size_t roiw_tail = size.width >= (step_tail - 1) ? size.width - step_tail + 1 : 0; for (size_t y = 0; y < size.height; ++y) { const type * src0 = internal::getRowPtr(src0Base, src0Stride, y); const type * src1 = internal::getRowPtr(src1Base, src1Stride, y); typename Op::type * dst = internal::getRowPtr(dstBase, dstStride, y); size_t x = 0; for( ; x < roiw_base; x += step_base ) { internal::prefetch(src0 + x); internal::prefetch(src1 + x); vec128 v_src00 = vld1q(src0 + x), v_src01 = vld1q(src0 + x + 16 / sizeof(type)); vec128 v_src10 = vld1q(src1 + x), v_src11 = vld1q(src1 + x + 16 / sizeof(type)); vec128 v_dst; op(v_src00, v_src10, v_dst); vst1q(dst + x, v_dst); op(v_src01, v_src11, v_dst); vst1q(dst + x + 16 / sizeof(type), v_dst); } for( ; x < roiw_tail; x += step_tail ) { vec64 v_src0 = vld1(src0 + x); vec64 v_src1 = vld1(src1 + x); vec64 v_dst; op(v_src0, v_src1, v_dst); vst1(dst + x, v_dst); } for (; x < size.width; ++x) { op(src0 + x, src1 + x, dst + x); } } }
float KVLD(const Image<float>& I1,const Image<float>& I2, std::vector<keypoint>& F1, std::vector<keypoint>& F2,const std::vector<Pair>& matches, std::vector<Pair>& matchesFiltered,std::vector<double>& score,libNumerics::matrix<float>& E,std::vector<bool>& valide, KvldParameters& kvldParameters){ matchesFiltered.clear(); score.clear(); ImageScale Chaine1(I1); ImageScale Chaine2(I2); std::cout<<"Image scale-space complete..."<<std::endl; float range1=getRange(I1,std::min(F1.size(),matches.size()),kvldParameters.inlierRate); float range2=getRange(I2,std::min(F2.size(),matches.size()),kvldParameters.inlierRate); size_t size=matches.size(); ////================distance map construction, for use of selecting neighbors===============// //std::cout<<"computing distance maps"<<std::endl; //libNumerics::matrix<float> dist1=libNumerics::matrix<float>::zeros(F1.size(), F1.size()); //libNumerics::matrix<float> dist2=libNumerics::matrix<float>::zeros(F2.size(), F2.size()); // for (int a1=0; a1<F1.size();++a1) // for (int a2=0; a2<F1.size();++a2) // dist1(a1,a2)=point_distance(F1[a1],F1[a2]); // for (int b1=0; b1<F2.size();++b1) // for (int b2=0; b2<F2.size();++b2) // dist2(b1,b2)=point_distance(F2[b1],F2[b2]); fill(valide.begin(),valide.end(), true); std::vector<double> scoretable(size, 0); std::vector<size_t> result(size, 0); //============main iteration for match verification==========// std::cout<<"main iteration"; bool change=true, initial=true; while(change){ std::cout<<"."; change=false; fill(scoretable.begin(), scoretable.end(), 0.0); fill(result.begin(), result.end(), 0); //========substep 1: search for each match its neighbors and verify if they are gvld-consistent ============// for (int it1=0; it1<size-1;it1++){ if (valide[it1]){ size_t a1=matches[it1].first, b1=matches[it1].second; for (int it2=it1+1; it2<size;it2++){ if (valide[it2]){ size_t a2=matches[it2].first, b2=matches[it2].second; float dist1=point_distance(F1[a1],F1[a2]); float dist2=point_distance(F2[b1],F2[b2]); if ( dist1>min_dist && dist2>min_dist && (dist1<range1 || dist2<range2)){ if(E(it1,it2)==-1){//update E if unknow E(it1,it2)=-2; E(it2,it1)=-2; if(!kvldParameters.geometry || consistent(F1[a1],F1[a2],F2[b1],F2[b2])<distance_thres){ VLD vld1(Chaine1,F1[a1],F1[a2]); VLD vld2(Chaine2,F2[b1],F2[b2]); //vld1.test(); double error=vld1.difference(vld2); //std::cout<<std::endl<<it1<<" "<<it2<<" "<<dist1(a1,a2)<<" "<< dist2(b1,b2)<<" "<<error<<std::endl; if (error<juge){ E(it1,it2)=(float)error; E(it2,it1)=(float)error; //std::cout<<E(it2,it1)<<std::endl; } } } if(E(it1,it2)>=0) { result[it1]+=1; result[it2]+=1; scoretable[it1]+=double(E(it1,it2)); scoretable[it2]+=double(E(it1,it2)); if (result[it1]>=max_connection) break; } } } } } } //========substep 2: remove false matches by K gvld-consistency criteria ============// for (int it=0; it<size;it++){ if (valide[it] && result[it]<kvldParameters.K) {valide[it]=false;change=true;} } //========substep 3: remove multiple matches to a same point by keeping the one with the best average gvld-consistency score ============// if(uniqueMatch){ for (int it1=0; it1<size-1;it1++){ if (valide[it1]){ size_t a1=matches[it1].first, b1=matches[it1].second; for (int it2=it1+1; it2<size;it2++) if (valide[it2]){ size_t a2=matches[it2].first, b2=matches[it2].second; if(a1==a2||b1==b2 ||(F1[a1].x==F1[a2].x && F1[a1].y==F1[a2].y && (F2[b1].x!=F2[b2].x || F2[b1].y!=F2[b2].y)) ||((F1[a1].x!=F1[a2].x || F1[a1].y!=F1[a2].y ) && F2[b1].x==F2[b2].x && F2[b1].y==F2[b2].y) ){ //cardinal comparison if(result[it1]>result[it2]){ valide[it2]=false;change=true; }else if(result[it1]<result[it2]){ valide[it1]=false;change=true; }else if(result[it1]==result[it2]){ //score comparison if (scoretable[it1]>scoretable[it2]){ valide[it1]=false;change=true; }else if (scoretable[it1]<scoretable[it2]){ valide[it2]=false;change=true; } } } } } } } //========substep 4: if geometric verification is set, re-score matches by geometric-consistency, and remove poorly scored ones ============================// if (uniqueMatch && kvldParameters.geometry){ for (int i=0;i<size;i++) scoretable[i]=0; std::vector<bool> switching; for (int i=0;i<size;i++) switching.push_back(false); for (int it1=0; it1<size;it1++){ if (valide[it1]) { size_t a1=matches[it1].first, b1=matches[it1].second; float index=0.0f; int good_index=0; for (int it2=0; it2<size;it2++){ if (it1!=it2 && valide[it2]){ size_t a2=matches[it2].first, b2=matches[it2].second; float dist1=point_distance(F1[a1],F1[a2]); float dist2=point_distance(F2[b1],F2[b2]); if ((dist1<range1 || dist2<range2) && (dist1>min_dist && dist2>min_dist) ){ float d=consistent(F1[a1],F1[a2],F2[b1],F2[b2]); scoretable[it1]+=d; index+=1; if (d<distance_thres) good_index++; } } } scoretable[it1]/=index; if (good_index<0.3f*float(index) && scoretable[it1]>1.2){switching[it1]=true;change=true;} } } for (int it1=0; it1<size;it1++){ if (switching[it1]) valide[it1]=false; } } } std::cout<<std::endl; //=============== generating output list ===================// for (int it=0; it<size;it++){ if (valide[it]){ matchesFiltered.push_back(matches[it]); score.push_back(scoretable[it]); } } return float(matchesFiltered.size())/matches.size(); }