| 2471 | } |
| 2472 | |
| 2473 | void cv::batchDistance( InputArray _src1, InputArray _src2, |
| 2474 | OutputArray _dist, int dtype, OutputArray _nidx, |
| 2475 | int normType, int K, InputArray _mask, |
| 2476 | int update, bool crosscheck ) |
| 2477 | { |
| 2478 | Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); |
| 2479 | int type = src1.type(); |
| 2480 | CV_Assert( type == src2.type() && src1.cols == src2.cols && |
| 2481 | (type == CV_32F || type == CV_8U)); |
| 2482 | CV_Assert( _nidx.needed() == (K > 0) ); |
| 2483 | |
| 2484 | if( dtype == -1 ) |
| 2485 | { |
| 2486 | dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ? CV_32S : CV_32F; |
| 2487 | } |
| 2488 | CV_Assert( (type == CV_8U && dtype == CV_32S) || dtype == CV_32F); |
| 2489 | |
| 2490 | K = std::min(K, src2.rows); |
| 2491 | |
| 2492 | _dist.create(src1.rows, (K > 0 ? K : src2.rows), dtype); |
| 2493 | Mat dist = _dist.getMat(), nidx; |
| 2494 | if( _nidx.needed() ) |
| 2495 | { |
| 2496 | _nidx.create(dist.size(), CV_32S); |
| 2497 | nidx = _nidx.getMat(); |
| 2498 | } |
| 2499 | |
| 2500 | if( update == 0 && K > 0 ) |
| 2501 | { |
| 2502 | dist = Scalar::all(dtype == CV_32S ? (double)INT_MAX : (double)FLT_MAX); |
| 2503 | nidx = Scalar::all(-1); |
| 2504 | } |
| 2505 | |
| 2506 | if( crosscheck ) |
| 2507 | { |
| 2508 | CV_Assert( K == 1 && update == 0 && mask.empty() ); |
| 2509 | Mat tdist, tidx; |
| 2510 | batchDistance(src2, src1, tdist, dtype, tidx, normType, K, mask, 0, false); |
| 2511 | |
| 2512 | // if an idx-th element from src1 appeared to be the nearest to i-th element of src2, |
| 2513 | // we update the minimum mutual distance between idx-th element of src1 and the whole src2 set. |
| 2514 | // As a result, if nidx[idx] = i*, it means that idx-th element of src1 is the nearest |
| 2515 | // to i*-th element of src2 and i*-th element of src2 is the closest to idx-th element of src1. |
| 2516 | // If nidx[idx] = -1, it means that there is no such ideal couple for it in src2. |
| 2517 | // This O(N) procedure is called cross-check and it helps to eliminate some false matches. |
| 2518 | if( dtype == CV_32S ) |
| 2519 | { |
| 2520 | for( int i = 0; i < tdist.rows; i++ ) |
| 2521 | { |
| 2522 | int idx = tidx.at<int>(i); |
| 2523 | int d = tdist.at<int>(i), d0 = dist.at<int>(idx); |
| 2524 | if( d < d0 ) |
| 2525 | { |
| 2526 | dist.at<int>(idx) = d; |
| 2527 | nidx.at<int>(idx) = i + update; |
| 2528 | } |
| 2529 | } |
| 2530 | } |