3 #include <opencv2/core/types_c.h> 7 template<
typename T>
static inline typename std::enable_if<std::is_integral<T>::value,
size_t>::type L1dist(T a, T b) {
8 return (
size_t)abs((
int)a-b);
12 template<
typename T>
static inline typename std::enable_if<std::is_floating_point<T>::value,
float>::type L1dist(T a, T b) {
13 return fabs((
float)a-(
float)b);
17 template<
size_t nChannels,
typename T>
static inline auto L1dist(
const T* a,
const T* b) -> decltype(L1dist(*a,*b)) {
18 decltype(L1dist(*a,*b)) oResult = 0;
19 for(
size_t c=0; c<nChannels; ++c)
20 oResult += L1dist(a[c],b[c]);
25 template<
size_t nChannels, typename T> static inline auto L1dist(const T* a, const T* b,
size_t nElements, const uchar* m=NULL) -> decltype(L1dist<nChannels>(a,b)) {
26 decltype(L1dist<nChannels>(a,b)) oResult = 0;
27 size_t nTotElements = nElements*nChannels;
29 for(
size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
31 oResult += L1dist<nChannels>(a+n,b+n);
34 for(
size_t n=0; n<nTotElements; n+=nChannels)
35 oResult += L1dist<nChannels>(a+n,b+n);
41 template<
typename T>
static inline auto L1dist(
const T* a,
const T* b,
size_t nElements,
size_t nChannels,
const uchar* m=NULL) -> decltype(L1dist<3>(a,b,nElements,m)) {
42 CV_Assert(nChannels>0 && nChannels<=4);
44 case 1:
return L1dist<1>(a,b,nElements,m);
45 case 2:
return L1dist<2>(a,b,nElements,m);
46 case 3:
return L1dist<3>(a,b,nElements,m);
47 case 4:
return L1dist<4>(a,b,nElements,m);
53 template<
size_t nChannels,
typename T>
static inline auto L1dist_(
const cv::Vec<T,nChannels>& a,
const cv::Vec<T,nChannels>& b) -> decltype(L1dist<nChannels,T>((T*)(0),(T*)(0))) {
54 T a_array[nChannels], b_array[nChannels];
55 for(
size_t c=0; c<nChannels; ++c) {
56 a_array[c] = a[(int)c];
57 b_array[c] = b[(int)c];
59 return L1dist<nChannels>(a_array,b_array);
65 template<
typename T>
static inline auto L2sqrdist(T a, T b) -> decltype(L1dist(a,b)) {
66 auto oResult = L1dist(a,b);
67 return oResult*oResult;
71 template<
size_t nChannels,
typename T>
static inline auto L2sqrdist(
const T* a,
const T* b) -> decltype(L2sqrdist(*a,*b)) {
72 decltype(L2sqrdist(*a,*b)) oResult = 0;
73 for(
size_t c=0; c<nChannels; ++c)
74 oResult += L2sqrdist(a[c],b[c]);
79 template<
size_t nChannels, typename T> static inline auto L2sqrdist(const T* a, const T* b,
size_t nElements, const uchar* m=NULL) -> decltype(L2sqrdist<nChannels>(a,b)) {
80 decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
81 size_t nTotElements = nElements*nChannels;
83 for(
size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
85 oResult += L2sqrdist<nChannels>(a+n,b+n);
88 for(
size_t n=0; n<nTotElements; n+=nChannels)
89 oResult += L2sqrdist<nChannels>(a+n,b+n);
95 template<
typename T>
static inline auto L2sqrdist(
const T* a,
const T* b,
size_t nElements,
size_t nChannels,
const uchar* m=NULL) -> decltype(L2sqrdist<3>(a,b,nElements,m)) {
96 CV_Assert(nChannels>0 && nChannels<=4);
98 case 1:
return L2sqrdist<1>(a,b,nElements,m);
99 case 2:
return L2sqrdist<2>(a,b,nElements,m);
100 case 3:
return L2sqrdist<3>(a,b,nElements,m);
101 case 4:
return L2sqrdist<4>(a,b,nElements,m);
107 template<
size_t nChannels,
typename T>
static inline auto L2sqrdist_(
const cv::Vec<T,nChannels>& a,
const cv::Vec<T,nChannels>& b) -> decltype(L2sqrdist<nChannels,T>((T*)(0),(T*)(0))) {
108 T a_array[nChannels], b_array[nChannels];
109 for(
size_t c=0; c<nChannels; ++c) {
110 a_array[c] = a[(int)c];
111 b_array[c] = b[(int)c];
113 return L2sqrdist<nChannels>(a_array,b_array);
117 template<
size_t nChannels,
typename T>
static inline float L2dist(
const T* a,
const T* b) {
118 decltype(L2sqrdist(*a,*b)) oResult = 0;
119 for(
size_t c=0; c<nChannels; ++c)
120 oResult += L2sqrdist(a[c],b[c]);
121 return sqrt((
float)oResult);
125 template<
size_t nChannels, typename T> static inline
float L2dist(const T* a, const T* b,
size_t nElements, const uchar* m=NULL) {
126 decltype(L2sqrdist<nChannels>(a,b)) oResult = 0;
127 size_t nTotElements = nElements*nChannels;
129 for(
size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
131 oResult += L2sqrdist<nChannels>(a+n,b+n);
134 for(
size_t n=0; n<nTotElements; n+=nChannels)
135 oResult += L2sqrdist<nChannels>(a+n,b+n);
137 return sqrt((
float)oResult);
141 template<
typename T>
static inline float L2dist(
const T* a,
const T* b,
size_t nElements,
size_t nChannels,
const uchar* m=NULL) {
142 CV_Assert(nChannels>0 && nChannels<=4);
144 case 1:
return L2dist<1>(a,b,nElements,m);
145 case 2:
return L2dist<2>(a,b,nElements,m);
146 case 3:
return L2dist<3>(a,b,nElements,m);
147 case 4:
return L2dist<4>(a,b,nElements,m);
153 template<
size_t nChannels,
typename T>
static inline float L2dist_(
const cv::Vec<T,nChannels>& a,
const cv::Vec<T,nChannels>& b) {
154 T a_array[nChannels], b_array[nChannels];
155 for(
size_t c=0; c<nChannels; ++c) {
156 a_array[c] = a[(int)c];
157 b_array[c] = b[(int)c];
159 return L2dist<nChannels>(a_array,b_array);
165 template<
size_t nChannels,
typename T>
static inline typename std::enable_if<std::is_integral<T>::value,
size_t>::type cdist(
const T* curr,
const T* bg) {
166 static_assert(nChannels>1,
"cdist: requires more than one channel");
167 bool bNonConstDist =
false;
168 bool bNonNullDist = (curr[0]!=bg[0]);
169 bool bNonNullBG = (bg[0]>0);
170 for(
size_t c=1; c<nChannels; ++c) {
171 bNonConstDist |= (curr[c]!=curr[c-1]) || (bg[c]!=bg[c-1]);
172 bNonNullDist |= (curr[c]!=bg[c]);
173 bNonNullBG |= (bg[c]>0);
175 if(!bNonConstDist || !bNonNullDist)
179 for(
size_t c=0; c<nChannels; ++c)
186 for(
size_t c=0; c<nChannels; ++c) {
187 curr_sqr += curr[c]*curr[c];
188 bg_sqr += bg[c]*bg[c];
189 mix += curr[c]*bg[c];
191 return (
size_t)sqrt((
float)(curr_sqr-(mix*mix)/bg_sqr));
195 template<
size_t nChannels,
typename T>
static inline typename std::enable_if<std::is_floating_point<T>::value,
float>::type cdist(
const T* curr,
const T* bg) {
196 static_assert(nChannels>1,
"cdist: requires more than one channel");
197 bool bNonConstDist =
false;
198 bool bNonNullDist = (curr[0]!=bg[0]);
199 bool bNonNullBG = (bg[0]>0);
200 for(
size_t c=1; c<nChannels; ++c) {
201 bNonConstDist |= (curr[c]!=curr[c-1]) || (bg[c]!=bg[c-1]);
202 bNonNullDist |= (curr[c]!=bg[c]);
203 bNonNullBG |= (bg[c]>0);
205 if(!bNonConstDist || !bNonNullDist)
209 for(
size_t c=0; c<nChannels; ++c)
216 for(
size_t c=0; c<nChannels; ++c) {
217 curr_sqr += (float)curr[c]*curr[c];
218 bg_sqr += (float)bg[c]*bg[c];
219 mix += (float)curr[c]*bg[c];
221 if(curr_sqr<(mix*mix)/bg_sqr)
224 return (
float)sqrt(curr_sqr-(mix*mix)/bg_sqr);
228 template<
size_t nChannels,
typename T>
static inline auto cdist(
const T* a,
const T* b,
size_t nElements,
const uchar* m=NULL) -> decltype(cdist<nChannels>(a,b)) {
229 decltype(cdist<nChannels>(a,b)) oResult = 0;
230 size_t nTotElements = nElements*nChannels;
232 for(
size_t n=0,i=0; n<nTotElements; n+=nChannels,++i)
234 oResult += cdist<nChannels>(a+n,b+n);
237 for(
size_t n=0; n<nTotElements; n+=nChannels)
238 oResult += cdist<nChannels>(a+n,b+n);
244 template<
typename T>
static inline auto cdist(
const T* a,
const T* b,
size_t nElements,
size_t nChannels,
const uchar* m=NULL) -> decltype(cdist<3>(a,b,nElements,m)) {
245 CV_Assert(nChannels>0 && nChannels<=4);
247 case 2:
return cdist<2>(a,b,nElements,m);
248 case 3:
return cdist<3>(a,b,nElements,m);
249 case 4:
return cdist<4>(a,b,nElements,m);
255 template<
size_t nChannels,
typename T>
static inline auto cdist_(
const cv::Vec<T,nChannels>& a,
const cv::Vec<T,nChannels>& b) -> decltype(cdist<nChannels,T>((T*)(0),(T*)(0))) {
256 T a_array[nChannels], b_array[nChannels];
257 for(
size_t c=0; c<nChannels; ++c) {
258 a_array[c] = a[(int)c];
259 b_array[c] = b[(int)c];
261 return cdist<nChannels>(a_array,b_array);
265 template<
typename T>
static inline T cmixdist(T oL1Distance, T oCDistortion) {
266 return (oL1Distance/2+oCDistortion*4);
270 template<
size_t nChannels,
typename T>
static inline typename std::enable_if<std::is_integral<T>::value,
size_t>::type cmixdist(
const T* curr,
const T* bg) {
271 return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
274 template<
size_t nChannels,
typename T>
static inline typename std::enable_if<std::is_floating_point<T>::value,
float>::type cmixdist(
const T* curr,
const T* bg) {
275 return cmixdist(L1dist<nChannels>(curr,bg),cdist<nChannels>(curr,bg));
281 static const uchar popcount_LUT8[256] = {
282 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
283 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
284 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
285 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
286 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
287 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
288 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
289 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
290 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
291 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
292 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
293 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
294 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
295 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
296 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
297 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
301 template<
typename T>
static inline size_t popcount(T x) {
302 size_t nBytes =
sizeof(T);
304 for(
size_t l=0; l<nBytes; ++l)
305 nResult += popcount_LUT8[(uchar)(x>>l*8)];
310 template<
typename T>
static inline size_t hdist(T a, T b) {
311 return popcount(a^b);
315 template<
typename T>
static inline size_t gdist(T a, T b) {
316 return L1dist(popcount(a),popcount(b));
320 template<
size_t nChannels,
typename T>
static inline size_t popcount(
const T* x) {
321 size_t nBytes =
sizeof(T);
323 for(
size_t c=0; c<nChannels; ++c)
324 for(
size_t l=0; l<nBytes; ++l)
325 nResult += popcount_LUT8[(uchar)(*(x+c)>>l*8)];
330 template<
size_t nChannels,
typename T>
static inline size_t hdist(
const T* a,
const T* b) {
331 T xor_array[nChannels];
332 for(
size_t c=0; c<nChannels; ++c)
333 xor_array[c] = a[c]^b[c];
334 return popcount<nChannels>(xor_array);
338 template<
size_t nChannels,
typename T>
static inline size_t gdist(
const T* a,
const T* b) {
339 return L1dist(popcount<nChannels>(a),popcount<nChannels>(b));