1. 程式人生 > >各種距離在opencv中的實現

各種距離在opencv中的實現

1、歐氏距離,用L2實現

struct CV_EXPORTS L2
{
    enum { normType = NORM_L2 };
    typedef T ValueType;
    typedef typename Accumulator<T>::Type ResultType;

    ResultType operator()( const T* a, const T* b, int size ) const
    {
        return (ResultType)sqrt((double)normL2Sqr<ValueType, ResultType>(a, b, size));
    }
};

實現函式為normL2Sqr()

template<> inline float normL2Sqr(const float* a, const float* b, int n)
{
    if( n >= 8 )
        return normL2Sqr_(a, b, n);
    float s = 0;
    for( int i = 0; i < n; i++ )
    {
        float v = a[i] - b[i];
        s += v*v;
    }
    return s;
}

2、曼哈頓距離,用L1實現

struct CV_EXPORTS L1
{
    enum { normType = NORM_L1 };
    typedef T ValueType;
    typedef typename Accumulator<T>::Type ResultType;

    ResultType operator()( const T* a, const T* b, int size ) const
    {
        return normL1<ValueType, ResultType>(a, b, size);
    }
};

實現函式為normL1()

template<> inline float normL1(const float* a, const float* b, int n)
{
    if( n >= 8 )
        return normL1_(a, b, n);
    float s = 0;
    for( int i = 0; i < n; i++ )
    {
        float v = a[i] - b[i];
        s += std::abs(v);
    }
    return s;
}

3、漢明距離,用Hamming實現

struct CV_EXPORTS Hamming
{
    enum { normType = NORM_HAMMING };
    typedef unsigned char ValueType;
    typedef int ResultType;

    /** this will count the bits in a ^ b
     */
    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
    {
        return normHamming(a, b, size);
    }
};

實現函式為normHamming()

struct CV_EXPORTS Hamming
{
    enum { normType = NORM_HAMMING };
    typedef unsigned char ValueType;
    typedef int ResultType;

    /** this will count the bits in a ^ b
     */
    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
    {
        return normHamming(a, b, size);
    }
};

實現函式為Hamming(),兩個等長字串s1與s2之間的漢明距離定義為將其中一個變為另外一個所需要作的最小替換次數。例如字串“1111”與“1001”之間的漢明距離為2。

int normHamming(const uchar* a, const uchar* b, int n)
{
    int i = 0, result = 0;
#if CV_NEON
    uint32x4_t bits = vmovq_n_u32(0);
    for (; i <= n - 16; i += 16) {
        uint8x16_t A_vec = vld1q_u8 (a + i);
        uint8x16_t B_vec = vld1q_u8 (b + i);
        uint8x16_t AxorB = veorq_u8 (A_vec, B_vec);
        uint8x16_t bitsSet = vcntq_u8 (AxorB);
        uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
        uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
        bits = vaddq_u32(bits, bitSet4);
    }
    uint64x2_t bitSet2 = vpaddlq_u32 (bits);
    result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0);
    result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2);
#else
    for( ; i <= n - 4; i += 4 )
        result += popCountTable[a[i] ^ b[i]] + popCountTable[a[i+1] ^ b[i+1]] +
                popCountTable[a[i+2] ^ b[i+2]] + popCountTable[a[i+3] ^ b[i+3]];
#endif
    for( ; i < n; i++ )
        result += popCountTable[a[i] ^ b[i]];
    return result;
}